Merge all changes from the 3.18.0 release.
FossilOrigin-Name: ed28f15e052b34f6642c68711fa3ed765c396262327fd3dd9c520b346a4deb81
This commit is contained in:
+6
-1
@@ -634,7 +634,8 @@ fuzzcheck$(TEXE): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(TLIBS)
|
||||
|
||||
ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c sqlite3.c sqlite3.h $(TLIBS)
|
||||
$(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c \
|
||||
$(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS)
|
||||
|
||||
dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS)
|
||||
@@ -1167,6 +1168,10 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
|
||||
sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
|
||||
$(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
|
||||
|
||||
dbdump$(TEXE): $(TOP)/ext/misc/dbdump.c sqlite3.lo
|
||||
$(LTLINK) -DDBDUMP_STANDALONE -o $@ \
|
||||
$(TOP)/ext/misc/dbdump.c sqlite3.lo $(TLIBS)
|
||||
|
||||
showdb$(TEXE): $(TOP)/tool/showdb.c sqlite3.lo
|
||||
$(LTLINK) -o $@ $(TOP)/tool/showdb.c sqlite3.lo $(TLIBS)
|
||||
|
||||
|
||||
+5
-1
@@ -2181,6 +2181,10 @@ sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
|
||||
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
|
||||
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
dbdump.exe: $(TOP)\ext\misc\dbdump.c $(SQLITE3C) $(SQLITE3H)
|
||||
$(LTLINK) $(NO_WARN) -DDBDUMP_STANDALONE $(TOP)\ext\misc\dbdump.c $(SQLITE3C) \
|
||||
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS)
|
||||
|
||||
testloadext.lo: $(TOP)\src\test_loadext.c
|
||||
$(LTCOMPILE) $(NO_WARN) -c $(TOP)\src\test_loadext.c
|
||||
|
||||
@@ -2259,7 +2263,7 @@ clean:
|
||||
del /Q tclsqlite3.exe $(SQLITETCLH) $(SQLITETCLDECLSH) 2>NUL
|
||||
del /Q testloadext.dll 2>NUL
|
||||
del /Q testfixture.exe test.db 2>NUL
|
||||
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe 2>NUL
|
||||
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe dbdump.exe 2>NUL
|
||||
del /Q changeset.exe 2>NUL
|
||||
del /Q showjournal.exe showstat4.exe showwal.exe speedtest1.exe 2>NUL
|
||||
del /Q mptester.exe wordcount.exe rbu.exe srcck1.exe 2>NUL
|
||||
|
||||
@@ -8,6 +8,48 @@ If you are reading this on a Git mirror someplace, you are doing it wrong.
|
||||
The [official repository](https://www.sqlite.org/src/) is better. Go there
|
||||
now.
|
||||
|
||||
## Obtaining The Code
|
||||
|
||||
SQLite sources are managed using the
|
||||
[Fossil](https://www.fossil-scm.org/), a distributed version control system
|
||||
that was specifically designed to support SQLite development.
|
||||
If you do not want to use Fossil, you can download tarballs or ZIP
|
||||
archives as follows:
|
||||
|
||||
* Lastest trunk check-in:
|
||||
<https://www.sqlite.org/src/tarball/sqlite.tar.gz> or
|
||||
<https://www.sqlite.org/src/zip/sqlite.zip>.
|
||||
|
||||
* Latest release:
|
||||
<https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=release> or
|
||||
<https://www.sqlite.org/src/zip/sqlite.zip?r=release>.
|
||||
|
||||
* For other check-ins, substitute an appropriate branch name or
|
||||
tag or hash prefix for "release" in the URLs of the previous
|
||||
bullet. Or browse the [timeline](https://www.sqlite.org/src/timeline)
|
||||
to locate the check-in desired, click on its information page link,
|
||||
then click on the "Tarball" or "ZIP Archive" links on the information
|
||||
page.
|
||||
|
||||
If you do want to use Fossil to check out the source tree,
|
||||
first install Fossil version 2.0 or later.
|
||||
(Source tarballs and precompiled binaries available
|
||||
[here](https://www.fossil-scm.org/fossil/uv/download.html).)
|
||||
Then run commands like this:
|
||||
|
||||
mkdir ~/sqlite
|
||||
cd ~/sqlite
|
||||
fossil clone https://www.sqlite.org/src sqlite.fossil
|
||||
fossil open sqlite.fossil
|
||||
|
||||
After setting up a repository using the steps above, you can always
|
||||
update to the lastest version using:
|
||||
|
||||
fossil update trunk ;# latest trunk check-in
|
||||
fossil update release ;# latest official release
|
||||
|
||||
Or type "fossil ui" to get a web-based user interface.
|
||||
|
||||
## Compiling
|
||||
|
||||
First create a directory in which to place
|
||||
@@ -18,13 +60,13 @@ script found at the root of the source tree. Then run "make".
|
||||
|
||||
For example:
|
||||
|
||||
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
|
||||
mkdir bld ;# Build will occur in a sibling directory
|
||||
cd bld ;# Change to the build directory
|
||||
../sqlite/configure ;# Run the configure script
|
||||
make ;# Run the makefile.
|
||||
make sqlite3.c ;# Build the "amalgamation" source file
|
||||
make test ;# Run some tests (requires Tcl)
|
||||
tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite"
|
||||
mkdir bld ;# Build will occur in a sibling directory
|
||||
cd bld ;# Change to the build directory
|
||||
../sqlite/configure ;# Run the configure script
|
||||
make ;# Run the makefile.
|
||||
make sqlite3.c ;# Build the "amalgamation" source file
|
||||
make test ;# Run some tests (requires Tcl)
|
||||
|
||||
See the makefile for additional targets.
|
||||
|
||||
@@ -43,13 +85,13 @@ with the provided "Makefile.msc" to build one of the supported targets.
|
||||
|
||||
For example:
|
||||
|
||||
mkdir bld
|
||||
cd bld
|
||||
nmake /f Makefile.msc TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
|
||||
nmake /f Makefile.msc test TOP=..\sqlite
|
||||
mkdir bld
|
||||
cd bld
|
||||
nmake /f Makefile.msc TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.c TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.dll TOP=..\sqlite
|
||||
nmake /f Makefile.msc sqlite3.exe TOP=..\sqlite
|
||||
nmake /f Makefile.msc test TOP=..\sqlite
|
||||
|
||||
There are several build options that can be set via the NMAKE command
|
||||
line. For example, to build for WinRT, simply add "FOR_WINRT=1" argument
|
||||
|
||||
@@ -644,6 +644,7 @@ RCC = $(RCC) -DSQLITE_ENABLE_API_ARMOR=1
|
||||
|
||||
!IF $(DEBUG)>2
|
||||
TCC = $(TCC) -DSQLITE_DEBUG=1
|
||||
TCC = $(TCC) -DSQLITE_ENABLE_WHERETRACE -DSQLITE_ENABLE_SELECTTRACE
|
||||
RCC = $(RCC) -DSQLITE_DEBUG=1
|
||||
!ENDIF
|
||||
|
||||
|
||||
@@ -55,9 +55,9 @@ AS_IF([ test x"$enable_editline" != xno ],[
|
||||
LIBS=""
|
||||
AC_SEARCH_LIBS([readline],[edit],[
|
||||
AC_DEFINE([HAVE_EDITLINE],1,Define to use BSD editline)
|
||||
READLINE_LIBS=$LIBS
|
||||
READLINE_LIBS="$LIBS -ltinfo"
|
||||
enable_readline=no
|
||||
])
|
||||
],[],[-ltinfo])
|
||||
AS_UNSET(ac_cv_search_readline)
|
||||
LIBS=$sLIBS
|
||||
])
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
## Loadable Extensions
|
||||
|
||||
Various [loadable extensions](https://www.sqlite.org/loadext.html) for
|
||||
SQLite are found in subfolders.
|
||||
|
||||
Most subfolders are dedicated to a single loadable extension (for
|
||||
example FTS5, or RTREE). But the misc/ subfolder contains a collection
|
||||
of smaller single-file extensions.
|
||||
@@ -1,2 +0,0 @@
|
||||
Version loadable extensions to SQLite are found in subfolders
|
||||
of this folder.
|
||||
+6
-3
@@ -349,8 +349,9 @@ int sqlite3Fts3PutVarint(char *p, sqlite_int64 v){
|
||||
** Return the number of bytes read, or 0 on error.
|
||||
** The value is stored in *v.
|
||||
*/
|
||||
int sqlite3Fts3GetVarint(const char *p, sqlite_int64 *v){
|
||||
const char *pStart = p;
|
||||
int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
|
||||
const unsigned char *p = (const unsigned char*)pBuf;
|
||||
const unsigned char *pStart = p;
|
||||
u32 a;
|
||||
u64 b;
|
||||
int shift;
|
||||
@@ -1397,7 +1398,9 @@ static int fts3InitVtab(
|
||||
char *z;
|
||||
int n = 0;
|
||||
z = (char *)sqlite3Fts3NextToken(aCol[iCol], &n);
|
||||
memcpy(zCsr, z, n);
|
||||
if( n>0 ){
|
||||
memcpy(zCsr, z, n);
|
||||
}
|
||||
zCsr[n] = '\0';
|
||||
sqlite3Fts3Dequote(zCsr);
|
||||
p->azColumn[iCol] = zCsr;
|
||||
|
||||
+13
-13
@@ -136,16 +136,16 @@ static int unicodeAddExceptions(
|
||||
){
|
||||
const unsigned char *z = (const unsigned char *)zIn;
|
||||
const unsigned char *zTerm = &z[nIn];
|
||||
int iCode;
|
||||
unsigned int iCode;
|
||||
int nEntry = 0;
|
||||
|
||||
assert( bAlnum==0 || bAlnum==1 );
|
||||
|
||||
while( z<zTerm ){
|
||||
READ_UTF8(z, zTerm, iCode);
|
||||
assert( (sqlite3FtsUnicodeIsalnum(iCode) & 0xFFFFFFFE)==0 );
|
||||
if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
|
||||
&& sqlite3FtsUnicodeIsdiacritic(iCode)==0
|
||||
assert( (sqlite3FtsUnicodeIsalnum((int)iCode) & 0xFFFFFFFE)==0 );
|
||||
if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum
|
||||
&& sqlite3FtsUnicodeIsdiacritic((int)iCode)==0
|
||||
){
|
||||
nEntry++;
|
||||
}
|
||||
@@ -162,13 +162,13 @@ static int unicodeAddExceptions(
|
||||
z = (const unsigned char *)zIn;
|
||||
while( z<zTerm ){
|
||||
READ_UTF8(z, zTerm, iCode);
|
||||
if( sqlite3FtsUnicodeIsalnum(iCode)!=bAlnum
|
||||
&& sqlite3FtsUnicodeIsdiacritic(iCode)==0
|
||||
if( sqlite3FtsUnicodeIsalnum((int)iCode)!=bAlnum
|
||||
&& sqlite3FtsUnicodeIsdiacritic((int)iCode)==0
|
||||
){
|
||||
int i, j;
|
||||
for(i=0; i<nNew && aNew[i]<iCode; i++);
|
||||
for(i=0; i<nNew && aNew[i]<(int)iCode; i++);
|
||||
for(j=nNew; j>i; j--) aNew[j] = aNew[j-1];
|
||||
aNew[i] = iCode;
|
||||
aNew[i] = (int)iCode;
|
||||
nNew++;
|
||||
}
|
||||
}
|
||||
@@ -318,7 +318,7 @@ static int unicodeNext(
|
||||
){
|
||||
unicode_cursor *pCsr = (unicode_cursor *)pC;
|
||||
unicode_tokenizer *p = ((unicode_tokenizer *)pCsr->base.pTokenizer);
|
||||
int iCode = 0;
|
||||
unsigned int iCode = 0;
|
||||
char *zOut;
|
||||
const unsigned char *z = &pCsr->aInput[pCsr->iOff];
|
||||
const unsigned char *zStart = z;
|
||||
@@ -330,7 +330,7 @@ static int unicodeNext(
|
||||
** the input. */
|
||||
while( z<zTerm ){
|
||||
READ_UTF8(z, zTerm, iCode);
|
||||
if( unicodeIsAlnum(p, iCode) ) break;
|
||||
if( unicodeIsAlnum(p, (int)iCode) ) break;
|
||||
zStart = z;
|
||||
}
|
||||
if( zStart>=zTerm ) return SQLITE_DONE;
|
||||
@@ -350,7 +350,7 @@ static int unicodeNext(
|
||||
|
||||
/* Write the folded case of the last character read to the output */
|
||||
zEnd = z;
|
||||
iOut = sqlite3FtsUnicodeFold(iCode, p->bRemoveDiacritic);
|
||||
iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic);
|
||||
if( iOut ){
|
||||
WRITE_UTF8(zOut, iOut);
|
||||
}
|
||||
@@ -358,8 +358,8 @@ static int unicodeNext(
|
||||
/* If the cursor is not at EOF, read the next character */
|
||||
if( z>=zTerm ) break;
|
||||
READ_UTF8(z, zTerm, iCode);
|
||||
}while( unicodeIsAlnum(p, iCode)
|
||||
|| sqlite3FtsUnicodeIsdiacritic(iCode)
|
||||
}while( unicodeIsAlnum(p, (int)iCode)
|
||||
|| sqlite3FtsUnicodeIsdiacritic((int)iCode)
|
||||
);
|
||||
|
||||
/* Set the output variables and return. */
|
||||
|
||||
+10
-11
@@ -127,9 +127,9 @@ int sqlite3FtsUnicodeIsalnum(int c){
|
||||
0xFFFFFFFF, 0xFC00FFFF, 0xF8000001, 0xF8000001,
|
||||
};
|
||||
|
||||
if( c<128 ){
|
||||
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
|
||||
}else if( c<(1<<22) ){
|
||||
if( (unsigned int)c<128 ){
|
||||
return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
|
||||
}else if( (unsigned int)c<(1<<22) ){
|
||||
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
|
||||
int iRes = 0;
|
||||
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
|
||||
@@ -322,16 +322,17 @@ int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
|
||||
|
||||
int ret = c;
|
||||
|
||||
assert( c>=0 );
|
||||
assert( sizeof(unsigned short)==2 && sizeof(unsigned char)==1 );
|
||||
|
||||
if( c<128 ){
|
||||
if( c>='A' && c<='Z' ) ret = c + ('a' - 'A');
|
||||
}else if( c<65536 ){
|
||||
const struct TableEntry *p;
|
||||
int iHi = sizeof(aEntry)/sizeof(aEntry[0]) - 1;
|
||||
int iLo = 0;
|
||||
int iRes = -1;
|
||||
|
||||
assert( c>aEntry[0].iCode );
|
||||
while( iHi>=iLo ){
|
||||
int iTest = (iHi + iLo) / 2;
|
||||
int cmp = (c - aEntry[iTest].iCode);
|
||||
@@ -342,14 +343,12 @@ int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
|
||||
iHi = iTest-1;
|
||||
}
|
||||
}
|
||||
assert( iRes<0 || c>=aEntry[iRes].iCode );
|
||||
|
||||
if( iRes>=0 ){
|
||||
const struct TableEntry *p = &aEntry[iRes];
|
||||
if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
|
||||
ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
|
||||
assert( ret>0 );
|
||||
}
|
||||
assert( iRes>=0 && c>=aEntry[iRes].iCode );
|
||||
p = &aEntry[iRes];
|
||||
if( c<(p->iCode + p->nRange) && 0==(0x01 & p->flags & (p->iCode ^ c)) ){
|
||||
ret = (c + (aiOff[p->flags>>1])) & 0x0000FFFF;
|
||||
assert( ret>0 );
|
||||
}
|
||||
|
||||
if( bRemoveDiacritic ) ret = remove_diacritic(ret);
|
||||
|
||||
@@ -4956,11 +4956,14 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
|
||||
** Convert the text beginning at *pz into an integer and return
|
||||
** its value. Advance *pz to point to the first character past
|
||||
** the integer.
|
||||
**
|
||||
** This function used for parameters to merge= and incrmerge=
|
||||
** commands.
|
||||
*/
|
||||
static int fts3Getint(const char **pz){
|
||||
const char *z = *pz;
|
||||
int i = 0;
|
||||
while( (*z)>='0' && (*z)<='9' ) i = 10*i + *(z++) - '0';
|
||||
while( (*z)>='0' && (*z)<='9' && i<214748363 ) i = 10*i + *(z++) - '0';
|
||||
*pz = z;
|
||||
return i;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
srcdir=`dirname $(dirname $(dirname $(dirname $0)))`
|
||||
./testfixture $srcdir/test/fts3.test --output=fts3cov-out.txt
|
||||
|
||||
echo ""
|
||||
|
||||
for f in `ls $srcdir/ext/fts3/*.c`
|
||||
do
|
||||
f=`basename $f`
|
||||
echo -ne "$f: "
|
||||
gcov -b $f | grep Taken | sed 's/Taken at least once://'
|
||||
done
|
||||
|
||||
@@ -227,7 +227,7 @@ proc print_isalnum {zFunc lRange} {
|
||||
an_print_ascii_bitmap $lRange
|
||||
puts {
|
||||
if( (unsigned int)c<128 ){
|
||||
return ( (aAscii[c >> 5] & (1 << (c & 0x001F)))==0 );
|
||||
return ( (aAscii[c >> 5] & ((unsigned int)1 << (c & 0x001F)))==0 );
|
||||
}else if( (unsigned int)c<(1<<22) ){
|
||||
unsigned int key = (((unsigned int)c)<<10) | 0x000003FF;
|
||||
int iRes = 0;
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
## Miscellaneous Extensions
|
||||
|
||||
This folder contains a collection of smaller loadable extensions.
|
||||
See <https://www.sqlite.org/loadext.html> for instructions on how
|
||||
to compile and use loadable extensions.
|
||||
Each extension in this folder is implemented in a single file of C code.
|
||||
|
||||
Each source file contains a description in its header comment. See the
|
||||
header comments for details about each extension. Additional notes are
|
||||
as follows:
|
||||
|
||||
* **carray.c** — This module implements the
|
||||
[carray](https://www.sqlite.org/carray.html) table-valued function.
|
||||
It is a good example of how to go about implementing a custom
|
||||
[table-valued function](https://www.sqlite.org/vtab.html#tabfunc2).
|
||||
|
||||
* **dbdump.c** — This is not actually a loadable extension, but
|
||||
rather a library that implements an approximate equivalent to the
|
||||
".dump" command of the
|
||||
[command-line shell](https://www.sqlite.org/cli.html).
|
||||
|
||||
* **memvfs.c** — This file implements a custom
|
||||
[VFS](https://www.sqlite.org/vfs.html) that stores an entire database
|
||||
file in a single block of RAM. It serves as a good example of how
|
||||
to implement a simple custom VFS.
|
||||
|
||||
* **rot13.c** — This file implements the very simple rot13()
|
||||
substitution function. This file makes a good template for implementing
|
||||
new custom SQL functions for SQLite.
|
||||
|
||||
* **series.c** — This is an implementation of the
|
||||
"generate_series" [virtual table](https://www.sqlite.org/vtab.html).
|
||||
It can make a good template for new custom virtual table implementations.
|
||||
|
||||
* **shathree.c** — An implementation of the sha3() and
|
||||
sha3_query() SQL functions. The file is named "shathree.c" instead
|
||||
of "sha3.c" because the default entry point names in SQLite are based
|
||||
on the source filename with digits removed, so if we used the name
|
||||
"sha3.c" then the entry point would conflict with the prior "sha1.c"
|
||||
extension.
|
||||
@@ -0,0 +1,717 @@
|
||||
/*
|
||||
** 2016-03-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.
|
||||
**
|
||||
******************************************************************************
|
||||
**
|
||||
** This file implements a C-language subroutine that converts the content
|
||||
** of an SQLite database into UTF-8 text SQL statements that can be used
|
||||
** to exactly recreate the original database. ROWID values are preserved.
|
||||
**
|
||||
** A prototype of the implemented subroutine is this:
|
||||
**
|
||||
** int sqlite3_db_dump(
|
||||
** sqlite3 *db,
|
||||
** const char *zSchema,
|
||||
** const char *zTable,
|
||||
** void (*xCallback)(void*, const char*),
|
||||
** void *pArg
|
||||
** );
|
||||
**
|
||||
** The db parameter is the database connection. zSchema is the schema within
|
||||
** that database which is to be dumped. Usually the zSchema is "main" but
|
||||
** can also be "temp" or any ATTACH-ed database. If zTable is not NULL, then
|
||||
** only the content of that one table is dumped. If zTable is NULL, then all
|
||||
** tables are dumped.
|
||||
**
|
||||
** The generate text is passed to xCallback() in multiple calls. The second
|
||||
** argument to xCallback() is a copy of the pArg parameter. The first
|
||||
** argument is some of the output text that this routine generates. The
|
||||
** signature to xCallback() is designed to make it compatible with fputs().
|
||||
**
|
||||
** The sqlite3_db_dump() subroutine returns SQLITE_OK on success or some error
|
||||
** code if it encounters a problem.
|
||||
**
|
||||
** If this file is compiled with -DDBDUMP_STANDALONE then a "main()" routine
|
||||
** is included so that this routine becomes a command-line utility. The
|
||||
** command-line utility takes two or three arguments which are the name
|
||||
** of the database file, the schema, and optionally the table, forming the
|
||||
** first three arguments of a single call to the library routine.
|
||||
*/
|
||||
#include "sqlite3.h"
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
** The state of the dump process.
|
||||
*/
|
||||
typedef struct DState DState;
|
||||
struct DState {
|
||||
sqlite3 *db; /* The database connection */
|
||||
int nErr; /* Number of errors seen so far */
|
||||
int rc; /* Error code */
|
||||
int writableSchema; /* True if in writable_schema mode */
|
||||
int (*xCallback)(const char*,void*); /* Send output here */
|
||||
void *pArg; /* Argument to xCallback() */
|
||||
};
|
||||
|
||||
/*
|
||||
** A variable length string to which one can append text.
|
||||
*/
|
||||
typedef struct DText DText;
|
||||
struct DText {
|
||||
char *z; /* The text */
|
||||
int n; /* Number of bytes of content in z[] */
|
||||
int nAlloc; /* Number of bytes allocated to z[] */
|
||||
};
|
||||
|
||||
/*
|
||||
** Initialize and destroy a DText object
|
||||
*/
|
||||
static void initText(DText *p){
|
||||
memset(p, 0, sizeof(*p));
|
||||
}
|
||||
static void freeText(DText *p){
|
||||
sqlite3_free(p->z);
|
||||
initText(p);
|
||||
}
|
||||
|
||||
/* zIn is either a pointer to a NULL-terminated string in memory obtained
|
||||
** from malloc(), or a NULL pointer. The string pointed to by zAppend is
|
||||
** added to zIn, and the result returned in memory obtained from malloc().
|
||||
** zIn, if it was not NULL, is freed.
|
||||
**
|
||||
** If the third argument, quote, is not '\0', then it is used as a
|
||||
** quote character for zAppend.
|
||||
*/
|
||||
static void appendText(DText *p, char const *zAppend, char quote){
|
||||
int len;
|
||||
int i;
|
||||
int nAppend = (int)(strlen(zAppend) & 0x3fffffff);
|
||||
|
||||
len = nAppend+p->n+1;
|
||||
if( quote ){
|
||||
len += 2;
|
||||
for(i=0; i<nAppend; i++){
|
||||
if( zAppend[i]==quote ) len++;
|
||||
}
|
||||
}
|
||||
|
||||
if( p->n+len>=p->nAlloc ){
|
||||
char *zNew;
|
||||
p->nAlloc = p->nAlloc*2 + len + 20;
|
||||
zNew = sqlite3_realloc(p->z, p->nAlloc);
|
||||
if( zNew==0 ){
|
||||
freeText(p);
|
||||
return;
|
||||
}
|
||||
p->z = zNew;
|
||||
}
|
||||
|
||||
if( quote ){
|
||||
char *zCsr = p->z+p->n;
|
||||
*zCsr++ = quote;
|
||||
for(i=0; i<nAppend; i++){
|
||||
*zCsr++ = zAppend[i];
|
||||
if( zAppend[i]==quote ) *zCsr++ = quote;
|
||||
}
|
||||
*zCsr++ = quote;
|
||||
p->n = (int)(zCsr - p->z);
|
||||
*zCsr = '\0';
|
||||
}else{
|
||||
memcpy(p->z+p->n, zAppend, nAppend);
|
||||
p->n += nAppend;
|
||||
p->z[p->n] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Attempt to determine if identifier zName needs to be quoted, either
|
||||
** because it contains non-alphanumeric characters, or because it is an
|
||||
** SQLite keyword. Be conservative in this estimate: When in doubt assume
|
||||
** that quoting is required.
|
||||
**
|
||||
** Return '"' if quoting is required. Return 0 if no quoting is required.
|
||||
*/
|
||||
static char quoteChar(const char *zName){
|
||||
/* All SQLite keywords, in alphabetical order */
|
||||
static const char *azKeywords[] = {
|
||||
"ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS",
|
||||
"ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY",
|
||||
"CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT",
|
||||
"CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
|
||||
"CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE",
|
||||
"DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH",
|
||||
"ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN",
|
||||
"FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF",
|
||||
"IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER",
|
||||
"INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY",
|
||||
"LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL",
|
||||
"NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA",
|
||||
"PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP",
|
||||
"REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT",
|
||||
"ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP",
|
||||
"TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE",
|
||||
"UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE",
|
||||
"WITH", "WITHOUT",
|
||||
};
|
||||
int i, lwr, upr, mid, c;
|
||||
if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
|
||||
for(i=0; zName[i]; i++){
|
||||
if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
|
||||
}
|
||||
lwr = 0;
|
||||
upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1;
|
||||
while( lwr<=upr ){
|
||||
mid = (lwr+upr)/2;
|
||||
c = sqlite3_stricmp(azKeywords[mid], zName);
|
||||
if( c==0 ) return '"';
|
||||
if( c<0 ){
|
||||
lwr = mid+1;
|
||||
}else{
|
||||
upr = mid-1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Release memory previously allocated by tableColumnList().
|
||||
*/
|
||||
static void freeColumnList(char **azCol){
|
||||
int i;
|
||||
for(i=1; azCol[i]; i++){
|
||||
sqlite3_free(azCol[i]);
|
||||
}
|
||||
/* azCol[0] is a static string */
|
||||
sqlite3_free(azCol);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return a list of pointers to strings which are the names of all
|
||||
** columns in table zTab. The memory to hold the names is dynamically
|
||||
** allocated and must be released by the caller using a subsequent call
|
||||
** to freeColumnList().
|
||||
**
|
||||
** The azCol[0] entry is usually NULL. However, if zTab contains a rowid
|
||||
** value that needs to be preserved, then azCol[0] is filled in with the
|
||||
** name of the rowid column.
|
||||
**
|
||||
** The first regular column in the table is azCol[1]. The list is terminated
|
||||
** by an entry with azCol[i]==0.
|
||||
*/
|
||||
static char **tableColumnList(DState *p, const char *zTab){
|
||||
char **azCol = 0;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
char *zSql;
|
||||
int nCol = 0;
|
||||
int nAlloc = 0;
|
||||
int nPK = 0; /* Number of PRIMARY KEY columns seen */
|
||||
int isIPK = 0; /* True if one PRIMARY KEY column of type INTEGER */
|
||||
int preserveRowid = 1;
|
||||
int rc;
|
||||
|
||||
zSql = sqlite3_mprintf("PRAGMA table_info=%Q", zTab);
|
||||
if( zSql==0 ) return 0;
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc ) return 0;
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
if( nCol>=nAlloc-2 ){
|
||||
char **azNew;
|
||||
nAlloc = nAlloc*2 + nCol + 10;
|
||||
azNew = sqlite3_realloc(azCol, nAlloc*sizeof(azCol[0]));
|
||||
if( azNew==0 ) goto col_oom;
|
||||
azCol = azNew;
|
||||
azCol[0] = 0;
|
||||
}
|
||||
azCol[++nCol] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 1));
|
||||
if( azCol[nCol]==0 ) goto col_oom;
|
||||
if( sqlite3_column_int(pStmt, 5) ){
|
||||
nPK++;
|
||||
if( nPK==1
|
||||
&& sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
|
||||
"INTEGER")==0
|
||||
){
|
||||
isIPK = 1;
|
||||
}else{
|
||||
isIPK = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
azCol[nCol+1] = 0;
|
||||
|
||||
/* The decision of whether or not a rowid really needs to be preserved
|
||||
** is tricky. We never need to preserve a rowid for a WITHOUT ROWID table
|
||||
** or a table with an INTEGER PRIMARY KEY. We are unable to preserve
|
||||
** rowids on tables where the rowid is inaccessible because there are other
|
||||
** columns in the table named "rowid", "_rowid_", and "oid".
|
||||
*/
|
||||
if( isIPK ){
|
||||
/* If a single PRIMARY KEY column with type INTEGER was seen, then it
|
||||
** might be an alise for the ROWID. But it might also be a WITHOUT ROWID
|
||||
** table or a INTEGER PRIMARY KEY DESC column, neither of which are
|
||||
** ROWID aliases. To distinguish these cases, check to see if
|
||||
** there is a "pk" entry in "PRAGMA index_list". There will be
|
||||
** no "pk" index if the PRIMARY KEY really is an alias for the ROWID.
|
||||
*/
|
||||
zSql = sqlite3_mprintf("SELECT 1 FROM pragma_index_list(%Q)"
|
||||
" WHERE origin='pk'", zTab);
|
||||
if( zSql==0 ) goto col_oom;
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc ){
|
||||
freeColumnList(azCol);
|
||||
return 0;
|
||||
}
|
||||
rc = sqlite3_step(pStmt);
|
||||
sqlite3_finalize(pStmt);
|
||||
pStmt = 0;
|
||||
preserveRowid = rc==SQLITE_ROW;
|
||||
}
|
||||
if( preserveRowid ){
|
||||
/* Only preserve the rowid if we can find a name to use for the
|
||||
** rowid */
|
||||
static char *azRowid[] = { "rowid", "_rowid_", "oid" };
|
||||
int i, j;
|
||||
for(j=0; j<3; j++){
|
||||
for(i=1; i<=nCol; i++){
|
||||
if( sqlite3_stricmp(azRowid[j],azCol[i])==0 ) break;
|
||||
}
|
||||
if( i>nCol ){
|
||||
/* At this point, we know that azRowid[j] is not the name of any
|
||||
** ordinary column in the table. Verify that azRowid[j] is a valid
|
||||
** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
|
||||
** tables will fail this last check */
|
||||
int rc;
|
||||
rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
|
||||
if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return azCol;
|
||||
|
||||
col_oom:
|
||||
sqlite3_finalize(pStmt);
|
||||
freeColumnList(azCol);
|
||||
p->nErr++;
|
||||
p->rc = SQLITE_NOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Send mprintf-formatted content to the output callback.
|
||||
*/
|
||||
static void output_formatted(DState *p, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
char *z;
|
||||
va_start(ap, zFormat);
|
||||
z = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
p->xCallback(z, p->pArg);
|
||||
sqlite3_free(z);
|
||||
}
|
||||
|
||||
/*
|
||||
** Output the given string as a quoted string using SQL quoting conventions.
|
||||
**
|
||||
** The "\n" and "\r" characters are converted to char(10) and char(13)
|
||||
** to prevent them from being transformed by end-of-line translators.
|
||||
*/
|
||||
static void output_quoted_string(DState *p, const unsigned char *z){
|
||||
int i;
|
||||
char c;
|
||||
int inQuote = 0;
|
||||
int bStarted = 0;
|
||||
|
||||
for(i=0; (c = z[i])!=0 && c!='\'' && c!='\n' && c!='\r'; i++){}
|
||||
if( c==0 ){
|
||||
output_formatted(p, "'%s'", z);
|
||||
return;
|
||||
}
|
||||
while( *z ){
|
||||
for(i=0; (c = z[i])!=0 && c!='\n' && c!='\r' && c!='\''; i++){}
|
||||
if( c=='\'' ) i++;
|
||||
if( i ){
|
||||
if( !inQuote ){
|
||||
if( bStarted ) p->xCallback("||", p->pArg);
|
||||
p->xCallback("'", p->pArg);
|
||||
inQuote = 1;
|
||||
}
|
||||
output_formatted(p, "%.*s", i, z);
|
||||
z += i;
|
||||
bStarted = 1;
|
||||
}
|
||||
if( c=='\'' ){
|
||||
p->xCallback("'", p->pArg);
|
||||
continue;
|
||||
}
|
||||
if( inQuote ){
|
||||
p->xCallback("'", p->pArg);
|
||||
inQuote = 0;
|
||||
}
|
||||
if( c==0 ){
|
||||
break;
|
||||
}
|
||||
for(i=0; (c = z[i])=='\r' || c=='\n'; i++){
|
||||
if( bStarted ) p->xCallback("||", p->pArg);
|
||||
output_formatted(p, "char(%d)", c);
|
||||
bStarted = 1;
|
||||
}
|
||||
z += i;
|
||||
}
|
||||
if( inQuote ) p->xCallback("'", p->pArg);
|
||||
}
|
||||
|
||||
/*
|
||||
** This is an sqlite3_exec callback routine used for dumping the database.
|
||||
** Each row received by this callback consists of a table name,
|
||||
** the table type ("index" or "table") and SQL to create the table.
|
||||
** This routine should print text sufficient to recreate the table.
|
||||
*/
|
||||
static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
|
||||
int rc;
|
||||
const char *zTable;
|
||||
const char *zType;
|
||||
const char *zSql;
|
||||
DState *p = (DState*)pArg;
|
||||
sqlite3_stmt *pStmt;
|
||||
|
||||
(void)azCol;
|
||||
if( nArg!=3 ) return 1;
|
||||
zTable = azArg[0];
|
||||
zType = azArg[1];
|
||||
zSql = azArg[2];
|
||||
|
||||
if( strcmp(zTable, "sqlite_sequence")==0 ){
|
||||
p->xCallback("DELETE FROM sqlite_sequence;\n", p->pArg);
|
||||
}else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
|
||||
p->xCallback("ANALYZE sqlite_master;\n", p->pArg);
|
||||
}else if( strncmp(zTable, "sqlite_", 7)==0 ){
|
||||
return 0;
|
||||
}else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
|
||||
if( !p->writableSchema ){
|
||||
p->xCallback("PRAGMA writable_schema=ON;\n", p->pArg);
|
||||
p->writableSchema = 1;
|
||||
}
|
||||
output_formatted(p,
|
||||
"INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
|
||||
"VALUES('table','%q','%q',0,'%q');",
|
||||
zTable, zTable, zSql);
|
||||
return 0;
|
||||
}else{
|
||||
if( sqlite3_strglob("CREATE TABLE ['\"]*", zSql)==0 ){
|
||||
p->xCallback("CREATE TABLE IF NOT EXISTS ", p->pArg);
|
||||
p->xCallback(zSql+13, p->pArg);
|
||||
}else{
|
||||
p->xCallback(zSql, p->pArg);
|
||||
}
|
||||
p->xCallback(";\n", p->pArg);
|
||||
}
|
||||
|
||||
if( strcmp(zType, "table")==0 ){
|
||||
DText sSelect;
|
||||
DText sTable;
|
||||
char **azCol;
|
||||
int i;
|
||||
int nCol;
|
||||
|
||||
azCol = tableColumnList(p, zTable);
|
||||
if( azCol==0 ) return 0;
|
||||
|
||||
initText(&sTable);
|
||||
appendText(&sTable, "INSERT INTO ", 0);
|
||||
|
||||
/* Always quote the table name, even if it appears to be pure ascii,
|
||||
** in case it is a keyword. Ex: INSERT INTO "table" ... */
|
||||
appendText(&sTable, zTable, quoteChar(zTable));
|
||||
|
||||
/* If preserving the rowid, add a column list after the table name.
|
||||
** In other words: "INSERT INTO tab(rowid,a,b,c,...) VALUES(...)"
|
||||
** instead of the usual "INSERT INTO tab VALUES(...)".
|
||||
*/
|
||||
if( azCol[0] ){
|
||||
appendText(&sTable, "(", 0);
|
||||
appendText(&sTable, azCol[0], 0);
|
||||
for(i=1; azCol[i]; i++){
|
||||
appendText(&sTable, ",", 0);
|
||||
appendText(&sTable, azCol[i], quoteChar(azCol[i]));
|
||||
}
|
||||
appendText(&sTable, ")", 0);
|
||||
}
|
||||
appendText(&sTable, " VALUES(", 0);
|
||||
|
||||
/* Build an appropriate SELECT statement */
|
||||
initText(&sSelect);
|
||||
appendText(&sSelect, "SELECT ", 0);
|
||||
if( azCol[0] ){
|
||||
appendText(&sSelect, azCol[0], 0);
|
||||
appendText(&sSelect, ",", 0);
|
||||
}
|
||||
for(i=1; azCol[i]; i++){
|
||||
appendText(&sSelect, azCol[i], quoteChar(azCol[i]));
|
||||
if( azCol[i+1] ){
|
||||
appendText(&sSelect, ",", 0);
|
||||
}
|
||||
}
|
||||
nCol = i;
|
||||
if( azCol[0]==0 ) nCol--;
|
||||
freeColumnList(azCol);
|
||||
appendText(&sSelect, " FROM ", 0);
|
||||
appendText(&sSelect, zTable, quoteChar(zTable));
|
||||
|
||||
rc = sqlite3_prepare_v2(p->db, sSelect.z, -1, &pStmt, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
p->nErr++;
|
||||
if( p->rc==SQLITE_OK ) p->rc = rc;
|
||||
}else{
|
||||
while( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
p->xCallback(sTable.z, p->pArg);
|
||||
for(i=0; i<nCol; i++){
|
||||
if( i ) p->xCallback(",", p->pArg);
|
||||
switch( sqlite3_column_type(pStmt,i) ){
|
||||
case SQLITE_INTEGER: {
|
||||
output_formatted(p, "%lld", sqlite3_column_int64(pStmt,i));
|
||||
break;
|
||||
}
|
||||
case SQLITE_FLOAT: {
|
||||
double r = sqlite3_column_double(pStmt,i);
|
||||
output_formatted(p, "%!.20g", r);
|
||||
break;
|
||||
}
|
||||
case SQLITE_NULL: {
|
||||
p->xCallback("NULL", p->pArg);
|
||||
break;
|
||||
}
|
||||
case SQLITE_TEXT: {
|
||||
output_quoted_string(p, sqlite3_column_text(pStmt,i));
|
||||
break;
|
||||
}
|
||||
case SQLITE_BLOB: {
|
||||
int nByte = sqlite3_column_bytes(pStmt,i);
|
||||
unsigned char *a = (unsigned char*)sqlite3_column_blob(pStmt,i);
|
||||
int j;
|
||||
p->xCallback("x'", p->pArg);
|
||||
for(j=0; j<nByte; j++){
|
||||
char zWord[3];
|
||||
zWord[0] = "0123456789abcdef"[(a[j]>>4)&15];
|
||||
zWord[1] = "0123456789abcdef"[a[j]&15];
|
||||
zWord[2] = 0;
|
||||
p->xCallback(zWord, p->pArg);
|
||||
}
|
||||
p->xCallback("'", p->pArg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
p->xCallback(");\n", p->pArg);
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
freeText(&sTable);
|
||||
freeText(&sSelect);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Execute a query statement that will generate SQL output. Print
|
||||
** the result columns, comma-separated, on a line and then add a
|
||||
** semicolon terminator to the end of that line.
|
||||
**
|
||||
** If the number of columns is 1 and that column contains text "--"
|
||||
** then write the semicolon on a separate line. That way, if a
|
||||
** "--" comment occurs at the end of the statement, the comment
|
||||
** won't consume the semicolon terminator.
|
||||
*/
|
||||
static void output_sql_from_query(
|
||||
DState *p, /* Query context */
|
||||
const char *zSelect, /* SELECT statement to extract content */
|
||||
...
|
||||
){
|
||||
sqlite3_stmt *pSelect;
|
||||
int rc;
|
||||
int nResult;
|
||||
int i;
|
||||
const char *z;
|
||||
char *zSql;
|
||||
va_list ap;
|
||||
va_start(ap, zSelect);
|
||||
zSql = sqlite3_vmprintf(zSelect, ap);
|
||||
va_end(ap);
|
||||
if( zSql==0 ){
|
||||
p->rc = SQLITE_NOMEM;
|
||||
p->nErr++;
|
||||
return;
|
||||
}
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pSelect, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc!=SQLITE_OK || !pSelect ){
|
||||
output_formatted(p, "/**** ERROR: (%d) %s *****/\n", rc,
|
||||
sqlite3_errmsg(p->db));
|
||||
p->nErr++;
|
||||
return;
|
||||
}
|
||||
rc = sqlite3_step(pSelect);
|
||||
nResult = sqlite3_column_count(pSelect);
|
||||
while( rc==SQLITE_ROW ){
|
||||
z = (const char*)sqlite3_column_text(pSelect, 0);
|
||||
p->xCallback(z, p->pArg);
|
||||
for(i=1; i<nResult; i++){
|
||||
p->xCallback(",", p->pArg);
|
||||
p->xCallback((const char*)sqlite3_column_text(pSelect,i), p->pArg);
|
||||
}
|
||||
if( z==0 ) z = "";
|
||||
while( z[0] && (z[0]!='-' || z[1]!='-') ) z++;
|
||||
if( z[0] ){
|
||||
p->xCallback("\n;\n", p->pArg);
|
||||
}else{
|
||||
p->xCallback(";\n", p->pArg);
|
||||
}
|
||||
rc = sqlite3_step(pSelect);
|
||||
}
|
||||
rc = sqlite3_finalize(pSelect);
|
||||
if( rc!=SQLITE_OK ){
|
||||
output_formatted(p, "/**** ERROR: (%d) %s *****/\n", rc,
|
||||
sqlite3_errmsg(p->db));
|
||||
if( (rc&0xff)!=SQLITE_CORRUPT ) p->nErr++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Run zQuery. Use dump_callback() as the callback routine so that
|
||||
** the contents of the query are output as SQL statements.
|
||||
**
|
||||
** If we get a SQLITE_CORRUPT error, rerun the query after appending
|
||||
** "ORDER BY rowid DESC" to the end.
|
||||
*/
|
||||
static void run_schema_dump_query(
|
||||
DState *p,
|
||||
const char *zQuery,
|
||||
...
|
||||
){
|
||||
char *zErr = 0;
|
||||
char *z;
|
||||
va_list ap;
|
||||
va_start(ap, zQuery);
|
||||
z = sqlite3_vmprintf(zQuery, ap);
|
||||
va_end(ap);
|
||||
sqlite3_exec(p->db, z, dump_callback, p, &zErr);
|
||||
sqlite3_free(z);
|
||||
if( zErr ){
|
||||
output_formatted(p, "/****** %s ******/\n", zErr);
|
||||
sqlite3_free(zErr);
|
||||
p->nErr++;
|
||||
zErr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Convert an SQLite database into SQL statements that will recreate that
|
||||
** database.
|
||||
*/
|
||||
int sqlite3_db_dump(
|
||||
sqlite3 *db, /* The database connection */
|
||||
const char *zSchema, /* Which schema to dump. Usually "main". */
|
||||
const char *zTable, /* Which table to dump. NULL means everything. */
|
||||
int (*xCallback)(const char*,void*), /* Output sent to this callback */
|
||||
void *pArg /* Second argument of the callback */
|
||||
){
|
||||
DState x;
|
||||
memset(&x, 0, sizeof(x));
|
||||
x.rc = sqlite3_exec(db, "BEGIN", 0, 0, 0);
|
||||
if( x.rc ) return x.rc;
|
||||
x.db = db;
|
||||
x.xCallback = xCallback;
|
||||
x.pArg = pArg;
|
||||
xCallback("PRAGMA foreign_keys=OFF;\nBEGIN TRANSACTION;\n", pArg);
|
||||
if( zTable==0 ){
|
||||
run_schema_dump_query(&x,
|
||||
"SELECT name, type, sql FROM \"%w\".sqlite_master "
|
||||
"WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'",
|
||||
zSchema
|
||||
);
|
||||
run_schema_dump_query(&x,
|
||||
"SELECT name, type, sql FROM \"%w\".sqlite_master "
|
||||
"WHERE name=='sqlite_sequence'", zSchema
|
||||
);
|
||||
output_sql_from_query(&x,
|
||||
"SELECT sql FROM sqlite_master "
|
||||
"WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
|
||||
);
|
||||
}else{
|
||||
run_schema_dump_query(&x,
|
||||
"SELECT name, type, sql FROM \"%w\".sqlite_master "
|
||||
"WHERE tbl_name=%Q COLLATE nocase AND type=='table'"
|
||||
" AND sql NOT NULL",
|
||||
zSchema, zTable
|
||||
);
|
||||
output_sql_from_query(&x,
|
||||
"SELECT sql FROM \"%w\".sqlite_master "
|
||||
"WHERE sql NOT NULL"
|
||||
" AND type IN ('index','trigger','view')"
|
||||
" AND tbl_name=%Q COLLATE nocase",
|
||||
zSchema, zTable
|
||||
);
|
||||
}
|
||||
if( x.writableSchema ){
|
||||
xCallback("PRAGMA writable_schema=OFF;\n", pArg);
|
||||
}
|
||||
xCallback(x.nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n", pArg);
|
||||
sqlite3_exec(db, "COMMIT", 0, 0, 0);
|
||||
return x.rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The generic subroutine is above. The code the follows implements
|
||||
** the command-line interface.
|
||||
*/
|
||||
#ifdef DBDUMP_STANDALONE
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
** Command-line interface
|
||||
*/
|
||||
int main(int argc, char **argv){
|
||||
sqlite3 *db;
|
||||
const char *zDb;
|
||||
const char *zSchema;
|
||||
const char *zTable = 0;
|
||||
int rc;
|
||||
|
||||
if( argc<2 || argc>4 ){
|
||||
fprintf(stderr, "Usage: %s DATABASE ?SCHEMA? ?TABLE?\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
zDb = argv[1];
|
||||
zSchema = argc>=3 ? argv[2] : "main";
|
||||
zTable = argc==4 ? argv[3] : 0;
|
||||
|
||||
rc = sqlite3_open(zDb, &db);
|
||||
if( rc ){
|
||||
fprintf(stderr, "Cannot open \"%s\": %s\n", zDb, sqlite3_errmsg(db));
|
||||
sqlite3_close(db);
|
||||
return 1;
|
||||
}
|
||||
rc = sqlite3_db_dump(db, zSchema, zTable,
|
||||
(int(*)(const char*,void*))fputs, (void*)stdout);
|
||||
if( rc ){
|
||||
fprintf(stderr, "Error: sqlite3_db_dump() returns %d\n", rc);
|
||||
}
|
||||
sqlite3_close(db);
|
||||
return rc!=SQLITE_OK;
|
||||
}
|
||||
#endif /* DBDUMP_STANDALONE */
|
||||
+138
-20
@@ -138,9 +138,10 @@ static const char * const jsonType[] = {
|
||||
#define JNODE_RAW 0x01 /* Content is raw, not JSON encoded */
|
||||
#define JNODE_ESCAPE 0x02 /* Content is text with \ escapes */
|
||||
#define JNODE_REMOVE 0x04 /* Do not output */
|
||||
#define JNODE_REPLACE 0x08 /* Replace with JsonNode.iVal */
|
||||
#define JNODE_APPEND 0x10 /* More ARRAY/OBJECT entries at u.iAppend */
|
||||
#define JNODE_LABEL 0x20 /* Is a label of an object */
|
||||
#define JNODE_REPLACE 0x08 /* Replace with JsonNode.u.iReplace */
|
||||
#define JNODE_PATCH 0x10 /* Patch with JsonNode.u.pPatch */
|
||||
#define JNODE_APPEND 0x20 /* More ARRAY/OBJECT entries at u.iAppend */
|
||||
#define JNODE_LABEL 0x40 /* Is a label of an object */
|
||||
|
||||
|
||||
/* A single node of parsed JSON
|
||||
@@ -148,12 +149,13 @@ static const char * const jsonType[] = {
|
||||
struct JsonNode {
|
||||
u8 eType; /* One of the JSON_ type values */
|
||||
u8 jnFlags; /* JNODE flags */
|
||||
u8 iVal; /* Replacement value when JNODE_REPLACE */
|
||||
u32 n; /* Bytes of content, or number of sub-nodes */
|
||||
union {
|
||||
const char *zJContent; /* Content for INT, REAL, and STRING */
|
||||
u32 iAppend; /* More terms for ARRAY and OBJECT */
|
||||
u32 iKey; /* Key for ARRAY objects in json_tree() */
|
||||
u32 iReplace; /* Replacement content for JNODE_REPLACE */
|
||||
JsonNode *pPatch; /* Node chain of patch for JNODE_PATCH */
|
||||
} u;
|
||||
};
|
||||
|
||||
@@ -410,6 +412,13 @@ static void jsonRenderNode(
|
||||
JsonString *pOut, /* Write JSON here */
|
||||
sqlite3_value **aReplace /* Replacement values */
|
||||
){
|
||||
if( pNode->jnFlags & (JNODE_REPLACE|JNODE_PATCH) ){
|
||||
if( pNode->jnFlags & JNODE_REPLACE ){
|
||||
jsonAppendValue(pOut, aReplace[pNode->u.iReplace]);
|
||||
return;
|
||||
}
|
||||
pNode = pNode->u.pPatch;
|
||||
}
|
||||
switch( pNode->eType ){
|
||||
default: {
|
||||
assert( pNode->eType==JSON_NULL );
|
||||
@@ -441,12 +450,7 @@ static void jsonRenderNode(
|
||||
jsonAppendChar(pOut, '[');
|
||||
for(;;){
|
||||
while( j<=pNode->n ){
|
||||
if( pNode[j].jnFlags & (JNODE_REMOVE|JNODE_REPLACE) ){
|
||||
if( pNode[j].jnFlags & JNODE_REPLACE ){
|
||||
jsonAppendSeparator(pOut);
|
||||
jsonAppendValue(pOut, aReplace[pNode[j].iVal]);
|
||||
}
|
||||
}else{
|
||||
if( (pNode[j].jnFlags & JNODE_REMOVE)==0 ){
|
||||
jsonAppendSeparator(pOut);
|
||||
jsonRenderNode(&pNode[j], pOut, aReplace);
|
||||
}
|
||||
@@ -468,11 +472,7 @@ static void jsonRenderNode(
|
||||
jsonAppendSeparator(pOut);
|
||||
jsonRenderNode(&pNode[j], pOut, aReplace);
|
||||
jsonAppendChar(pOut, ':');
|
||||
if( pNode[j+1].jnFlags & JNODE_REPLACE ){
|
||||
jsonAppendValue(pOut, aReplace[pNode[j+1].iVal]);
|
||||
}else{
|
||||
jsonRenderNode(&pNode[j+1], pOut, aReplace);
|
||||
}
|
||||
jsonRenderNode(&pNode[j+1], pOut, aReplace);
|
||||
}
|
||||
j += 1 + jsonNodeSize(&pNode[j+1]);
|
||||
}
|
||||
@@ -699,7 +699,6 @@ static int jsonParseAddNode(
|
||||
p = &pParse->aNode[pParse->nNode];
|
||||
p->eType = (u8)eType;
|
||||
p->jnFlags = 0;
|
||||
p->iVal = 0;
|
||||
p->n = n;
|
||||
p->u.zJContent = zContent;
|
||||
return pParse->nNode++;
|
||||
@@ -1165,6 +1164,25 @@ static void jsonWrongNumArgs(
|
||||
sqlite3_free(zMsg);
|
||||
}
|
||||
|
||||
/*
|
||||
** Mark all NULL entries in the Object passed in as JNODE_REMOVE.
|
||||
*/
|
||||
static void jsonRemoveAllNulls(JsonNode *pNode){
|
||||
int i, n;
|
||||
assert( pNode->eType==JSON_OBJECT );
|
||||
n = pNode->n;
|
||||
for(i=2; i<=n; i += jsonNodeSize(&pNode[i])+1){
|
||||
switch( pNode[i].eType ){
|
||||
case JSON_NULL:
|
||||
pNode[i].jnFlags |= JNODE_REMOVE;
|
||||
break;
|
||||
case JSON_OBJECT:
|
||||
jsonRemoveAllNulls(&pNode[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
** SQL functions used for testing and debugging
|
||||
@@ -1357,6 +1375,105 @@ static void jsonExtractFunc(
|
||||
jsonParseReset(&x);
|
||||
}
|
||||
|
||||
/* This is the RFC 7396 MergePatch algorithm.
|
||||
*/
|
||||
static JsonNode *jsonMergePatch(
|
||||
JsonParse *pParse, /* The JSON parser that contains the TARGET */
|
||||
int iTarget, /* Node of the TARGET in pParse */
|
||||
JsonNode *pPatch /* The PATCH */
|
||||
){
|
||||
u32 i, j;
|
||||
u32 iRoot;
|
||||
JsonNode *pTarget;
|
||||
if( pPatch->eType!=JSON_OBJECT ){
|
||||
return pPatch;
|
||||
}
|
||||
assert( iTarget>=0 && iTarget<pParse->nNode );
|
||||
pTarget = &pParse->aNode[iTarget];
|
||||
assert( (pPatch->jnFlags & JNODE_APPEND)==0 );
|
||||
if( pTarget->eType!=JSON_OBJECT ){
|
||||
jsonRemoveAllNulls(pPatch);
|
||||
return pPatch;
|
||||
}
|
||||
iRoot = iTarget;
|
||||
for(i=1; i<pPatch->n; i += jsonNodeSize(&pPatch[i+1])+1){
|
||||
u32 nKey;
|
||||
const char *zKey;
|
||||
assert( pPatch[i].eType==JSON_STRING );
|
||||
assert( pPatch[i].jnFlags & JNODE_LABEL );
|
||||
nKey = pPatch[i].n;
|
||||
zKey = pPatch[i].u.zJContent;
|
||||
assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
|
||||
for(j=1; j<pTarget->n; j += jsonNodeSize(&pTarget[j+1])+1 ){
|
||||
assert( pTarget[j].eType==JSON_STRING );
|
||||
assert( pTarget[j].jnFlags & JNODE_LABEL );
|
||||
assert( (pPatch[i].jnFlags & JNODE_RAW)==0 );
|
||||
if( pTarget[j].n==nKey && strncmp(pTarget[j].u.zJContent,zKey,nKey)==0 ){
|
||||
if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH) ) break;
|
||||
if( pPatch[i+1].eType==JSON_NULL ){
|
||||
pTarget[j+1].jnFlags |= JNODE_REMOVE;
|
||||
}else{
|
||||
JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]);
|
||||
if( pNew==0 ) return 0;
|
||||
pTarget = &pParse->aNode[iTarget];
|
||||
if( pNew!=&pTarget[j+1] ){
|
||||
pTarget[j+1].u.pPatch = pNew;
|
||||
pTarget[j+1].jnFlags |= JNODE_PATCH;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( j>=pTarget->n && pPatch[i+1].eType!=JSON_NULL ){
|
||||
int iStart, iPatch;
|
||||
iStart = jsonParseAddNode(pParse, JSON_OBJECT, 2, 0);
|
||||
jsonParseAddNode(pParse, JSON_STRING, nKey, zKey);
|
||||
iPatch = jsonParseAddNode(pParse, JSON_TRUE, 0, 0);
|
||||
if( pParse->oom ) return 0;
|
||||
jsonRemoveAllNulls(pPatch);
|
||||
pTarget = &pParse->aNode[iTarget];
|
||||
pParse->aNode[iRoot].jnFlags |= JNODE_APPEND;
|
||||
pParse->aNode[iRoot].u.iAppend = iStart - iRoot;
|
||||
iRoot = iStart;
|
||||
pParse->aNode[iPatch].jnFlags |= JNODE_PATCH;
|
||||
pParse->aNode[iPatch].u.pPatch = &pPatch[i+1];
|
||||
}
|
||||
}
|
||||
return pTarget;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the json_mergepatch(JSON1,JSON2) function. Return a JSON
|
||||
** object that is the result of running the RFC 7396 MergePatch() algorithm
|
||||
** on the two arguments.
|
||||
*/
|
||||
static void jsonPatchFunc(
|
||||
sqlite3_context *ctx,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
JsonParse x; /* The JSON that is being patched */
|
||||
JsonParse y; /* The patch */
|
||||
JsonNode *pResult; /* The result of the merge */
|
||||
|
||||
UNUSED_PARAM(argc);
|
||||
if( jsonParse(&x, ctx, (const char*)sqlite3_value_text(argv[0])) ) return;
|
||||
if( jsonParse(&y, ctx, (const char*)sqlite3_value_text(argv[1])) ){
|
||||
jsonParseReset(&x);
|
||||
return;
|
||||
}
|
||||
pResult = jsonMergePatch(&x, 0, y.aNode);
|
||||
assert( pResult!=0 || x.oom );
|
||||
if( pResult ){
|
||||
jsonReturnJson(pResult, ctx, 0);
|
||||
}else{
|
||||
sqlite3_result_error_nomem(ctx);
|
||||
}
|
||||
jsonParseReset(&x);
|
||||
jsonParseReset(&y);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON
|
||||
** object that contains all name/value given in arguments. Or if any name
|
||||
@@ -1460,11 +1577,11 @@ static void jsonReplaceFunc(
|
||||
if( x.nErr ) goto replace_err;
|
||||
if( pNode ){
|
||||
pNode->jnFlags |= (u8)JNODE_REPLACE;
|
||||
pNode->iVal = (u8)(i+1);
|
||||
pNode->u.iReplace = i + 1;
|
||||
}
|
||||
}
|
||||
if( x.aNode[0].jnFlags & JNODE_REPLACE ){
|
||||
sqlite3_result_value(ctx, argv[x.aNode[0].iVal]);
|
||||
sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
|
||||
}else{
|
||||
jsonReturnJson(x.aNode, ctx, argv);
|
||||
}
|
||||
@@ -1514,11 +1631,11 @@ static void jsonSetFunc(
|
||||
goto jsonSetDone;
|
||||
}else if( pNode && (bApnd || bIsSet) ){
|
||||
pNode->jnFlags |= (u8)JNODE_REPLACE;
|
||||
pNode->iVal = (u8)(i+1);
|
||||
pNode->u.iReplace = i + 1;
|
||||
}
|
||||
}
|
||||
if( x.aNode[0].jnFlags & JNODE_REPLACE ){
|
||||
sqlite3_result_value(ctx, argv[x.aNode[0].iVal]);
|
||||
sqlite3_result_value(ctx, argv[x.aNode[0].u.iReplace]);
|
||||
}else{
|
||||
jsonReturnJson(x.aNode, ctx, argv);
|
||||
}
|
||||
@@ -2161,6 +2278,7 @@ int sqlite3Json1Init(sqlite3 *db){
|
||||
{ "json_extract", -1, 0, jsonExtractFunc },
|
||||
{ "json_insert", -1, 0, jsonSetFunc },
|
||||
{ "json_object", -1, 0, jsonObjectFunc },
|
||||
{ "json_patch", 2, 0, jsonPatchFunc },
|
||||
{ "json_quote", 1, 0, jsonQuoteFunc },
|
||||
{ "json_remove", -1, 0, jsonRemoveFunc },
|
||||
{ "json_replace", -1, 0, jsonReplaceFunc },
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
**
|
||||
** The sha3_query(Y) function evalutes all queries in the SQL statements of Y
|
||||
** and returns a hash of their results.
|
||||
**
|
||||
** The SIZE argument is optional. If omitted, the SHA3-256 hash algorithm
|
||||
** is used. If SIZE is included it must be one of the integers 224, 256,
|
||||
** 384, or 512, to determine SHA3 hash variant that is computed.
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
|
||||
+9
-9
@@ -459,15 +459,15 @@ static i64 readInt64(u8 *p){
|
||||
memcpy(&x, p, 8);
|
||||
return x;
|
||||
#else
|
||||
return (
|
||||
(((i64)p[0]) << 56) +
|
||||
(((i64)p[1]) << 48) +
|
||||
(((i64)p[2]) << 40) +
|
||||
(((i64)p[3]) << 32) +
|
||||
(((i64)p[4]) << 24) +
|
||||
(((i64)p[5]) << 16) +
|
||||
(((i64)p[6]) << 8) +
|
||||
(((i64)p[7]) << 0)
|
||||
return (i64)(
|
||||
(((u64)p[0]) << 56) +
|
||||
(((u64)p[1]) << 48) +
|
||||
(((u64)p[2]) << 40) +
|
||||
(((u64)p[3]) << 32) +
|
||||
(((u64)p[4]) << 24) +
|
||||
(((u64)p[5]) << 16) +
|
||||
(((u64)p[6]) << 8) +
|
||||
(((u64)p[7]) << 0)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -749,6 +749,10 @@ sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
|
||||
sqlite3_analyzer$(EXE): sqlite3_analyzer.c
|
||||
$(TCCX) $(TCL_FLAGS) sqlite3_analyzer.c -o $@ $(LIBTCL) $(THREADLIB)
|
||||
|
||||
dbdump$(EXE): $(TOP)/ext/misc/dbdump.c sqlite3.o
|
||||
$(TCCX) -DDBDUMP_STANDALONE -o dbdump$(EXE) \
|
||||
$(TOP)/ext/misc/dbdump.c sqlite3.o $(THREADLIB)
|
||||
|
||||
# Rules to build the 'testfixture' application.
|
||||
#
|
||||
TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
C Merge\sall\srecent\schanges\sfrom\strunk.
|
||||
D 2017-03-13T18:31:14.352
|
||||
F Makefile.in c75fd72f81bb47a1df670516b9ea271b8d836acc43032fe6cfc96563b8783029
|
||||
C Merge\sall\schanges\sfrom\sthe\s3.18.0\srelease.
|
||||
D 2017-03-30T20:26:06.627
|
||||
F Makefile.in 227347646e289e3b016ebb7a391ad6ed4ab56525834d56d47d1a83b8d97d6989
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc f8501d6bcb057964cb48af4406d87bb797630d41d3fe85a3569e3397bdddeeed
|
||||
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
|
||||
F Makefile.msc b66da6600003ed72fae3372fd4cd0148f9b4b5cf52cd3d272dbd8f17ca1c0354
|
||||
F README.md 2b15fae33852f2f53996774c21fb41e1d94181c4401a0e43ac93e11f2cc901b9
|
||||
F VERSION 3605fa447e4623f5ff4a6adc97b1fde9a257b8f2
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
@@ -11,10 +11,10 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am 1a47d071e3d5435f8f7ebff7eb6703848bbd65d4
|
||||
F autoconf/Makefile.msc 3de603bcec5c07462801a20fd7dc1b871400af99
|
||||
F autoconf/Makefile.msc 92e3d7fd64dc5c23a23d33824ee4709aaea00a6331c4bb41a1aadcf6600a49f7
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
|
||||
F autoconf/configure.ac cacf2616abf6e4a569bde2ef365c143caeec40bc
|
||||
F autoconf/configure.ac 2893b823ecc86cea13739f6c8109a41392254d1db08235c5615e0af5722c8578
|
||||
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
|
||||
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
|
||||
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
|
||||
@@ -36,7 +36,7 @@ F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html b5a3c07d33ecb8e019ce8f7660fe2dbbad9d7977
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
|
||||
F ext/README.txt 913a7bd3f4837ab14d7e063304181787658b14e1
|
||||
F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd w ext/README.txt
|
||||
F ext/async/README.txt e12275968f6fde133a80e04387d0e839b0c51f91
|
||||
F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74
|
||||
F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
|
||||
@@ -70,7 +70,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c 95c7041ea75d82d2d9a4cd058904ba889751f5b8
|
||||
F ext/fts3/fts3.c f0d5de1bc2155ba7cd7c0c1a751779a3a8857fa34d5c12f3b233a23fa2e79ea2
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a
|
||||
F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
|
||||
@@ -86,15 +86,16 @@ F ext/fts3/fts3_tokenize_vtab.c a27593ab19657166f6fa5ec073b678cc29a75860
|
||||
F ext/fts3/fts3_tokenizer.c a22bf311a71f3efa9d7012d8cc48fc9b0f3dace7
|
||||
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145
|
||||
F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057
|
||||
F ext/fts3/fts3_write.c c3863f23b6b4623c8b9d5cf31c12ce4469f78ca9
|
||||
F ext/fts3/fts3_unicode.c 525a3bd9a7564603c5c061b7de55403a565307758a94600e8a2f6b00d1c40d9d
|
||||
F ext/fts3/fts3_unicode2.c cc04fc672bfd42b1e650398cb0bf71f64f9aae032cfe75bbcfe75b9cf966029c
|
||||
F ext/fts3/fts3_write.c a51d48d646974ee2fb4b17fcd5da0416a5759a32dcacc2cce2ba00d5a767848e
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87fea4ac01b73
|
||||
F ext/fts3/tool/fts3view.c 202801a2056995b763864d60c2dee744d46f1677
|
||||
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
|
||||
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl 2debed3f582d77b3fdd0b8830880250021571fd8
|
||||
F ext/fts3/unicode/mkunicode.tcl ab0543a3b2399092ea2dd75df1bef333405b0d7f6b8c4951a0fbb60e780cb69f
|
||||
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
|
||||
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
|
||||
F ext/fts5/fts5.h 62f3e33ceeb9a428db139f9c012186b371da1cc7
|
||||
@@ -206,16 +207,18 @@ F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
|
||||
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
|
||||
F ext/icu/icu.c 84900472a088a3a172c6c079f58a1d3a1952c332
|
||||
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||
F ext/misc/README.md 8e008c8d2b02e09096b31dfba033253ac27c6c06a18aa5826e299fa7601d90b2
|
||||
F ext/misc/amatch.c 211108e201105e4bb0c076527b8cfd34330fc234
|
||||
F ext/misc/carray.c 40c27641010a4dc67e3690bdb7c9d36ca58b3c2d
|
||||
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
|
||||
F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
|
||||
F ext/misc/csv.c 531a46cbad789fca0aa9db69a0e6c8ac9e68767d
|
||||
F ext/misc/dbdump.c 34174d537318027b159e3341105866c05a4149376ede59988c82280bed144e6d
|
||||
F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
|
||||
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
|
||||
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
|
||||
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
|
||||
F ext/misc/json1.c 552a7d730863419e05dc947265b28bd411680e2e
|
||||
F ext/misc/json1.c 92b9e404bd79cc76d3ef2b3a9e37bf775700f7d645466fd41d2e8742e3fa16fb
|
||||
F ext/misc/memvfs.c e5225bc22e79dde6b28380f3a068ddf600683a33
|
||||
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
|
||||
@@ -225,7 +228,7 @@ F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
|
||||
F ext/misc/scrub.c 1c5bfb8b0cd18b602fcb55755e84abf0023ac2fb
|
||||
F ext/misc/series.c e11e534ada797d5b816d7e7a93c022306563ca35
|
||||
F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56
|
||||
F ext/misc/shathree.c 38aa4c3c3d3c3fc34b8ea367bed299d8d8a224b2
|
||||
F ext/misc/shathree.c fa185d7aee0ad0aca5e091b4a2db7baff11796170e5793b5de99e511a13af448
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c a4723b6aff748a417b5091b68a46443265c40f0d
|
||||
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
|
||||
@@ -268,7 +271,7 @@ F ext/rbu/sqlite3rbu.c 2a89efba9eeba8e6c89a498dc195e8efbdde2694
|
||||
F ext/rbu/sqlite3rbu.h 6fb6294c34a9ca93b5894a33bca530c6f08decba
|
||||
F ext/rbu/test_rbu.c 5aa22616afac6f71ebd3d9bc9bf1006cfabcca88
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c d99720f7cc800ec9917f5053e8fda41f6ff82871
|
||||
F ext/rtree/rtree.c 3be16f2e49220ca778fde2dd1d1bf67815db4888bcc0cd0a8145dd9a3bb2e87c
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
F ext/rtree/rtree1.test 42dadfc7b44a436cd74a1bebc0b9b689e4eaf7ec
|
||||
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
|
||||
@@ -325,7 +328,7 @@ F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 172c83775a403c826283713bfdd10b5d29b9aafa80d909ef54c1bb9e398b81d3
|
||||
F main.mk c1eca02dc5500469a14320357534135f86bbcbb43b1ddad4bf70c235aacb37f1
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -338,38 +341,38 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 3b23977620ce9662ac54443f65b87ba996e36121
|
||||
F src/analyze.c 6d8234916c29be943e6ea28b5bef67dff98d9905
|
||||
F src/analyze.c 0d0ccf7520a201d8747ea2f02c92c26e26f801bc161f714f27b9f7630dde0421
|
||||
F src/attach.c 8c476f8bd5d2afe11d925f890d30e527e5b0ce43
|
||||
F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792
|
||||
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
|
||||
F src/btree.c 75b117045699d59ff5603792e46482032ce98ba4
|
||||
F src/btree.c 9f218dcf45716023de7e479774bc821b05efe5388a670ae2ee6f6716de5cecb9
|
||||
F src/btree.h bf64dfeeddeebdb775a5eba0098bbc00d073290d
|
||||
F src/btreeInt.h cd55d39d9916270837a88c12e701047cba0729b0
|
||||
F src/build.c 43f903c9082040ced2b421543cb0300c2973647d
|
||||
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c a9984df73898c042a5cfc8f9d8e7723d02bc35c9
|
||||
F src/ctime.c 47d91a25ad8f199a71a5b1b7b169d6dd0d6e98c5719eca801568798743d1161c
|
||||
F src/date.c ee676e7694dfadbdd2fde1a258a71be8360ba5ae
|
||||
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
|
||||
F src/delete.c 0d9d5549d42e79ce4d82ff1db1e6c81e36d2f67c
|
||||
F src/expr.c f12a581f342a6fd85d14c31e4fb84f16b3dd107f54d7728dddb62cebc79d7ce1
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 2e9aabe1aee76273aff8a84ee92c464e095400ae
|
||||
F src/func.c c67273e1ec08abbdcc14c189892a3ff6eeece86b
|
||||
F src/func.c 9d52522cc8ae7f5cdadfe14594262f1618bc1f86083c4cd6da861b4cf5af6174
|
||||
F src/global.c 4a34512d82fc5aa13c802db06bcfff5e1d3de955
|
||||
F src/hash.c 63d0ee752a3b92d4695b2b1f5259c4621b2cfebd
|
||||
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
|
||||
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 3ed64afc49c0a2221e397b9f65d231ffbef506fe
|
||||
F src/insert.c d4bb3a135948553d18cf992f76f7ed7b18aa0327f250607b5a6671e55d9947d5
|
||||
F src/legacy.c b143b1fe422524cb29cb5ac907c8a44684333d75
|
||||
F src/loadext.c a68d8d1d14cf7488bb29dc5311cb1ce9a4404258
|
||||
F src/loadext.c a72909474dadce771d3669bf84bf689424f6f87d471fee898589c3ef9b2acfd9
|
||||
F src/main.c 0c3fecdde19dc698bb59d1901a8696a6be36ff64
|
||||
F src/malloc.c 89c98e3619d362dcffa5c1c639b364b65b474751
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c fd7cd6fe21d46fe0a4186367dd8dc26d87b787eb
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
|
||||
F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a
|
||||
F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
|
||||
@@ -394,21 +397,21 @@ F src/parse.y 48b03113704ee8bd78ee6996d81de7fbee22e105
|
||||
F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870
|
||||
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
|
||||
F src/pcache1.c 6d8c7bc6bbae077a0c76440cf32342a65dfeac75
|
||||
F src/pragma.c 69997bfa269233889d2019071550e249174c8491
|
||||
F src/pragma.c ae2407b542a3dc14285dd41983e3f50de537eda23d3e7350963814766f7a931f
|
||||
F src/pragma.h c9c763958fec92b04125571472c9500b351c5f7f
|
||||
F src/prepare.c 601681ecade57127ffbb5df1e096a30f29eff54c
|
||||
F src/printf.c 67427bbee66d891fc6f6f5aada857e9cdb368c1c
|
||||
F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c 3e518b962d932a997fae373366880fc028c75706
|
||||
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
||||
F src/select.c 2496d0cc6368dabe7ad2e4c7f5ed3ad9aa3b4d11cd90f33fa1d1ef72493f43aa
|
||||
F src/shell.c 353f3cebb938099577494326e2853010512e0625
|
||||
F src/sqlite.h.in 329de1e75636972ba4b9388971ba47d3e2cb9116
|
||||
F src/shell.c ceb2b2f1f958ea2c47a7f37972d0f715fbf9dcf6a34a5e98c886b85e3ce6a238
|
||||
F src/sqlite.h.in c30314cc52075796a78b3e14d1e032565c7e97b2a0fa2ffa068f38ed76ca6c0f
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3_private.h a81a9c5f97c095cc3e86914a05f8fabe0011f4a1
|
||||
F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
|
||||
F src/sqliteInt.h 85eba6f13086a33be08ef7237af7b8be9884d0f3
|
||||
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
|
||||
F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28
|
||||
F src/sqliteInt.h 0c3e3daa672992437966213392f415b3d30273a92845536f8a0a94080a13880a
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
F src/tclsqlite.c 6c2151b6d8d98e183a04466d40df8889c0574d79
|
||||
@@ -427,7 +430,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
|
||||
F src/test_bestindex.c d23f80d334c59662af69191854c76b8d3d0c8c96
|
||||
F src/test_blob.c f65ac717da2618691cf9dad094e6da0219dcd208
|
||||
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
|
||||
F src/test_config.c 58800d20433a5af029aad7e937fabf5a4b8ab5ef
|
||||
F src/test_config.c 075bd5db1e2a605bd7838d66512ac06d0184a2953457b50626cb6655f367cc03
|
||||
F src/test_delete.c af7eab5702f853fb1c62a5f7665e2234cf1ae17b
|
||||
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
|
||||
F src/test_devsym.c 4e58dec2602d8e139ca08659f62a62450587cb58
|
||||
@@ -437,7 +440,7 @@ F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d
|
||||
F src/test_init.c 4413c211a94b62157ca4c145b3f27c497f03c664
|
||||
F src/test_intarray.c 988fc61cb0ff539f4172c0d95f15287c92516f64
|
||||
F src/test_intarray.h f3b7672f5d1056eac563c0d6ea8480a660b1475c
|
||||
F src/test_journal.c d3b83f2bcb7792c709e57abddc456a2b1818643a
|
||||
F src/test_journal.c 619f2aa10e0d7a5f87c0f06825bc61dfce1c6b9c7f3ad990fb13de6c3b8874a3
|
||||
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
|
||||
F src/test_malloc.c c05f6c40bd6c8bfe5f1718212f81fd5687f91766
|
||||
F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e
|
||||
@@ -469,11 +472,11 @@ F src/update.c 456d4a4656f8a03c2abc88a51b19172197400e58
|
||||
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
|
||||
F src/util.c ca8440ede81e155d15cff7c101654f60b55a9ae6
|
||||
F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569
|
||||
F src/vdbe.c b6dfec95671b4b22f4f3d9f3d7f081405b8043e0
|
||||
F src/vdbe.h 59998ffd71d7caa8886bc78dafaf8caeccd4c13c
|
||||
F src/vdbeInt.h 4e4b15b2e1330e1636e4e01974eab2b0b985092f
|
||||
F src/vdbe.c 316eae267851a274c05a4b31581afb88558101ebe40369ef525494f1d85abb14
|
||||
F src/vdbe.h caa5346d52bae2a3c8c1dcfa60a7a4dc878a9e3865cb8239da55808b316c8158
|
||||
F src/vdbeInt.h 5db089ce18c4feff8820ec6e4cac2d2c82e03d4b1d96f10a6e43832147b8dffe
|
||||
F src/vdbeapi.c 995f635640bdbc38d95f24c467b87e79646b4ce4
|
||||
F src/vdbeaux.c 57361f2e761d92a254638bdbfc03fc68ae6aebc6
|
||||
F src/vdbeaux.c ecd0468611925d218e1eb4b3f538907904b136f0e15e333291a232b521bfcef1
|
||||
F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
|
||||
F src/vdbemem.c 3b5a9a5b375458d3e12a50ae1aaa41eeec2175fd
|
||||
F src/vdbesort.c eda25cb2d1727efca6f7862fea32b8aa33c0face
|
||||
@@ -529,7 +532,7 @@ F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
|
||||
F test/auth.test c6ede04bee65637ff354b43fc1235aa560c0863e
|
||||
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
|
||||
F test/auth3.test 0d48b901cf111c14b4b1b5205c7d28f1a278190f
|
||||
F test/autoanalyze1.test 1ba80d5e1412d46503566b70741a5eea060da929
|
||||
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
|
||||
F test/autoinc.test 6ae8fb69c9f656962464ae4e6667045d0dfc3b46
|
||||
F test/autoindex1.test 14b63a9f1e405fe6d5bfc8c8d00249c2ebaf13ea
|
||||
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
|
||||
@@ -584,7 +587,7 @@ F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
|
||||
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
|
||||
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
|
||||
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
|
||||
F test/check.test 92b23a91fb7be12fba7ee9ce518217e2919a21da
|
||||
F test/check.test 33a698e8c63613449d85d624a38ef669bf20331daabebe3891c9405dd6df463a
|
||||
F test/close.test 83947daf3b700631f90f4850ddaab455be4af73d
|
||||
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
|
||||
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
|
||||
@@ -598,7 +601,7 @@ F test/collate7.test 8ec29d98f3ee4ccebce6e16ce3863fb6b8c7b868
|
||||
F test/collate8.test cd9b3d3f999b8520ffaa7cc1647061fc5bab1334
|
||||
F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a
|
||||
F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
|
||||
F test/collateB.test 8ec2accd2d7166c1eff0d2a39bc90262c6f89632
|
||||
F test/collateB.test 1e68906951b846570f29f20102ed91d29e634854ee47454d725f2151ecac0b95
|
||||
F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1
|
||||
F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b
|
||||
F test/conflict.test 029faa2d81a0d1cafb5f88614beb663d972c01db
|
||||
@@ -835,7 +838,7 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
|
||||
F test/fuzz3.test b47377143f0c80f91ed29d722861077ff34415d5
|
||||
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
|
||||
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
|
||||
F test/fuzzcheck.c a87e6067a8d19844bade916841cb76150ecf24a2
|
||||
F test/fuzzcheck.c 2152602232c96d9c790eff3013e1369ce59de3203fa0b75bc613531448454e61
|
||||
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
|
||||
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
@@ -914,6 +917,7 @@ F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
|
||||
F test/json101.test c0897616f32d95431f37fd291cb78742181980ac
|
||||
F test/json102.test bf3fe7a706d30936a76a0f7a0375e1e8e73aff5a
|
||||
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
|
||||
F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
|
||||
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/kvtest.c b9a9822dda05a1aa481215a52e2fc93cd8b22ee5
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
@@ -958,7 +962,7 @@ F test/mallocI.test 6c23a71df077fa5d387be90e7e669c5b368ca38a
|
||||
F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
|
||||
F test/mallocK.test 27cb5566a6e5f2d76f9d4aa2eca45524401fd61e
|
||||
F test/mallocL.test fb311ff80afddf3b1a75e52289081f4754d901dc
|
||||
F test/mallocM.test 491001d1e273233048d265ec6d38fdd23745b0284f0c93bc98c94b64451c9c28
|
||||
F test/mallocM.test 78bbe9d3da84a5c679123cdb40d7b2010b18fc46e13897e4f253c6ba6fbff134
|
||||
F test/malloc_common.tcl 8d368ee0b9d77c9643b174448f137c18b68e49f4
|
||||
F test/manydb.test 3cd8e52ab3112cb8365afeedd6e8231977920577
|
||||
F test/mem5.test c6460fba403c5703141348cd90de1c294188c68f
|
||||
@@ -1012,8 +1016,8 @@ F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
|
||||
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
|
||||
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
|
||||
F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f
|
||||
F test/ossfuzz.c 6dc75478809cfbd4609409a87179ddc2ffaa092e8adb27c1982c5a944a7dd81f
|
||||
F test/ossshell.c d9f1a6f43e7bab45d6be857a5800f5d4a1861db3
|
||||
F test/ossfuzz.c f5abed3177f719df3c3109901fcdd26b9fb7f581c8da50fc26f3a81ddfb2c2ae
|
||||
F test/ossshell.c 296ab63067841bd1b1e97b46a0b2af48ee7f69d50d1a723008bee12dd7122622
|
||||
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
|
||||
F test/pager1.test 15d423765637d8cd54b025f90ed6c8dc311e2fc3
|
||||
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
|
||||
@@ -1028,7 +1032,7 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854
|
||||
F test/pcache.test 9a04fa260cb47dd4fdc5d13c5e97054e05931592
|
||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test 46ad98770d3c04ce2418cab2cc527647bfe961a7
|
||||
F test/permutations.test af720e7d139e7e5417341d0f0eef2b911c0b067852138dc2f5b6a451b5725118
|
||||
F test/pragma.test d3b32e689ffd885b2e7bcaabab21ee4652a4f99f
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
|
||||
@@ -1115,7 +1119,7 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
|
||||
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
|
||||
F test/shared_err.test 2f2aee20db294b9924e81f6ccbe60f19e21e8506
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test bc1ca4161e1f459c9cd412d3f21f4ee635cf2322
|
||||
F test/shell1.test 50226a3a66bbd42a902e9f7698f768927eb33a56e9cfc55b7c157c38eb3e80ac
|
||||
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
|
||||
F test/shell3.test 9b95ba643eaa228376f06a898fb410ee9b6e57c1
|
||||
F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
|
||||
@@ -1168,6 +1172,7 @@ F test/subtype1.test 7fe09496352f97053af1437150751be2d0a0cae8
|
||||
F test/superlock.test c86eacd6cead5da9c5ecd25f3d46fca30a927ef2
|
||||
F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849
|
||||
F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529
|
||||
F test/sync2.test 29af00fe9e468a1e20315d1edced8f8a32ac156df983ae9b53802e7d472675d5
|
||||
F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c
|
||||
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
|
||||
F test/tabfunc01.test 699251cb99651415218a891384510a685c7ab012
|
||||
@@ -1360,6 +1365,7 @@ F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092
|
||||
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
|
||||
F test/triggerE.test 15fa63f1097db1f83dd62d121616006978063d1f
|
||||
F test/triggerF.test 55b1eb13433997faac3a4948c1d8252f6c8c636b
|
||||
F test/triggerG.test 175cafdc6399d85231a09e82e051b0e45a2fd1f23dd08ae715bc359716149ab6
|
||||
F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1
|
||||
F test/tt3_index.c 39eec10a35f57672225be4d182862152896dee4a
|
||||
F test/tt3_lookaside1.c 0377e202c3c2a50d688cb65ba203afeda6fafeb9
|
||||
@@ -1521,7 +1527,7 @@ F tool/replace.tcl 60f91e8dd06ab81f74d213ecbd9c9945f32ac048
|
||||
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
F tool/run-speed-test.sh f95d19fd669b68c4c38b6b475242841d47c66076
|
||||
F tool/showdb.c c695a5d5c8110640e0d9fadf5e254da90c79c36e
|
||||
F tool/showdb.c e6bc9dba233bf1b57ca0a525a2bba762db4e223de84990739db3f09c46151b1e
|
||||
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
|
||||
F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
|
||||
F tool/showstat4.c b14159aa062f661b394ba37b6b7b94bfb8012ab9
|
||||
@@ -1568,7 +1574,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 9b43917380ed60f11ebd8210bb7b9e444e1b9b0c 68f6dc7af1013f296a11db14c007cc13cc3fe56832848bfed835ed8f74dcc676
|
||||
R a69508ffc3dce9a8eb7a6c4125dfe03a
|
||||
P 3d04b2cd7a68cf58ae739a5c6813562130e5c50c800c208c82769f76037f8f66 424a0d380332858ee55bdebc4af3789f74e70a2b3ba1cf29d84b9b4bcf3e2e37
|
||||
R 6d0f353b5301e13bfa3fc1119a23c0b2
|
||||
U drh
|
||||
Z 80f668a2a3637e507006793fa87f79f8
|
||||
Z 226af4d62e9a0804bc0108a41855537c
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
3d04b2cd7a68cf58ae739a5c6813562130e5c50c800c208c82769f76037f8f66
|
||||
ed28f15e052b34f6642c68711fa3ed765c396262327fd3dd9c520b346a4deb81
|
||||
+1
-1
@@ -1204,7 +1204,7 @@ static void analyzeOneTable(
|
||||
regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
|
||||
for(j=0; j<pPk->nKeyCol; j++){
|
||||
k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
|
||||
assert( k>=0 && k<pTab->nCol );
|
||||
assert( k>=0 && k<pIdx->nColumn );
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
|
||||
VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
|
||||
}
|
||||
|
||||
+28
-14
@@ -2867,6 +2867,31 @@ int sqlite3BtreeGetAutoVacuum(Btree *p){
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** If the user has not set the safety-level for this database connection
|
||||
** using "PRAGMA synchronous", and if the safety-level is not already
|
||||
** set to the value passed to this function as the second parameter,
|
||||
** set it so.
|
||||
*/
|
||||
#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS
|
||||
static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){
|
||||
sqlite3 *db;
|
||||
Db *pDb;
|
||||
if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){
|
||||
while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; }
|
||||
if( pDb->bSyncSet==0
|
||||
&& pDb->safety_level!=safety_level
|
||||
&& pDb!=&db->aDb[1]
|
||||
){
|
||||
pDb->safety_level = safety_level;
|
||||
sqlite3PagerSetFlags(pBt->pPager,
|
||||
pDb->safety_level | (db->flags & PAGER_FLAGS_MASK));
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define setDefaultSyncFlag(pBt,safety_level)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Get a reference to pPage1 of the database file. This will
|
||||
@@ -2940,26 +2965,15 @@ static int lockBtree(BtShared *pBt){
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto page1_init_failed;
|
||||
}else{
|
||||
#if SQLITE_DEFAULT_SYNCHRONOUS!=SQLITE_DEFAULT_WAL_SYNCHRONOUS
|
||||
sqlite3 *db;
|
||||
Db *pDb;
|
||||
if( (db=pBt->db)!=0 && (pDb=db->aDb)!=0 ){
|
||||
while( pDb->pBt==0 || pDb->pBt->pBt!=pBt ){ pDb++; }
|
||||
if( pDb->bSyncSet==0
|
||||
&& pDb->safety_level==SQLITE_DEFAULT_SYNCHRONOUS+1
|
||||
){
|
||||
pDb->safety_level = SQLITE_DEFAULT_WAL_SYNCHRONOUS+1;
|
||||
sqlite3PagerSetFlags(pBt->pPager,
|
||||
pDb->safety_level | (db->flags & PAGER_FLAGS_MASK));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS+1);
|
||||
if( isOpen==0 ){
|
||||
releasePage(pPage1);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
rc = SQLITE_NOTADB;
|
||||
}else{
|
||||
setDefaultSyncFlag(pBt, SQLITE_DEFAULT_SYNCHRONOUS+1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -66,6 +66,12 @@ static const char * const azCompileOpt[] = {
|
||||
#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
|
||||
"DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_SYNCHRONOUS
|
||||
"DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_WAL_SYNCHRONOUS
|
||||
"DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
|
||||
#endif
|
||||
#if SQLITE_DIRECT_OVERFLOW_READ
|
||||
"DIRECT_OVERFLOW_READ",
|
||||
#endif
|
||||
|
||||
+1
-3
@@ -204,15 +204,13 @@ static void instrFunc(
|
||||
if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
|
||||
zHaystack = sqlite3_value_blob(argv[0]);
|
||||
zNeedle = sqlite3_value_blob(argv[1]);
|
||||
assert( zNeedle!=0 );
|
||||
assert( zHaystack!=0 || nHaystack==0 );
|
||||
isText = 0;
|
||||
}else{
|
||||
zHaystack = sqlite3_value_text(argv[0]);
|
||||
zNeedle = sqlite3_value_text(argv[1]);
|
||||
isText = 1;
|
||||
if( zHaystack==0 || zNeedle==0 ) return;
|
||||
}
|
||||
if( zNeedle==0 || (nHaystack && zHaystack==0) ) return;
|
||||
while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
|
||||
N++;
|
||||
do{
|
||||
|
||||
@@ -2227,8 +2227,6 @@ static int xferOptimization(
|
||||
** sorted order. */
|
||||
for(i=0; i<pSrcIdx->nColumn; i++){
|
||||
const char *zColl = pSrcIdx->azColl[i];
|
||||
assert( sqlite3_stricmp(sqlite3StrBINARY, zColl)!=0
|
||||
|| sqlite3StrBINARY==zColl );
|
||||
if( sqlite3_stricmp(sqlite3StrBINARY, zColl) ) break;
|
||||
}
|
||||
if( i==pSrcIdx->nColumn ){
|
||||
|
||||
+3
-1
@@ -421,7 +421,9 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
sqlite3_system_errno,
|
||||
/* Version 3.14.0 and later */
|
||||
sqlite3_trace_v2,
|
||||
sqlite3_expanded_sql
|
||||
sqlite3_expanded_sql,
|
||||
/* Version 3.18.0 and later */
|
||||
sqlite3_set_last_insert_rowid
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+5
-12
@@ -57,7 +57,9 @@
|
||||
*/
|
||||
#include <sys/sysctl.h>
|
||||
#include <malloc/malloc.h>
|
||||
#ifdef SQLITE_MIGHT_BE_SINGLE_CORE
|
||||
#include <libkern/OSAtomic.h>
|
||||
#endif /* SQLITE_MIGHT_BE_SINGLE_CORE */
|
||||
static malloc_zone_t* _sqliteZone_;
|
||||
#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
|
||||
#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
|
||||
@@ -250,19 +252,10 @@ static int sqlite3MemInit(void *NotUsed){
|
||||
}else{
|
||||
/* only 1 core, use our own zone to contention over global locks,
|
||||
** e.g. we have our own dedicated locks */
|
||||
bool success;
|
||||
malloc_zone_t* newzone = malloc_create_zone(4096, 0);
|
||||
malloc_set_zone_name(newzone, "Sqlite_Heap");
|
||||
do{
|
||||
success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone,
|
||||
(void * volatile *)&_sqliteZone_);
|
||||
}while(!_sqliteZone_);
|
||||
if( !success ){
|
||||
/* somebody registered a zone first */
|
||||
malloc_destroy_zone(newzone);
|
||||
}
|
||||
_sqliteZone_ = malloc_create_zone(4096, 0);
|
||||
malloc_set_zone_name(_sqliteZone_, "Sqlite_Heap");
|
||||
}
|
||||
#endif
|
||||
#endif /* defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) */
|
||||
UNUSED_PARAMETER(NotUsed);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
+2
-1
@@ -1015,7 +1015,7 @@ void sqlite3Pragma(
|
||||
if( !db->autoCommit ){
|
||||
sqlite3ErrorMsg(pParse,
|
||||
"Safety level may not be changed inside a transaction");
|
||||
}else{
|
||||
}else if( iDb!=1 ){
|
||||
int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK;
|
||||
if( iLevel==0 ) iLevel = 1;
|
||||
pDb->safety_level = iLevel;
|
||||
@@ -1505,6 +1505,7 @@ void sqlite3Pragma(
|
||||
int iDataCur, iIdxCur;
|
||||
int r1 = -1;
|
||||
|
||||
if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
|
||||
if( pTab->pCheck==0
|
||||
&& (pTab->tabFlags & TF_HasNotNull)==0
|
||||
&& (pTab->pIndex==0 || isQuick)
|
||||
|
||||
+3
-2
@@ -400,12 +400,13 @@ void sqlite3VXPrintf(
|
||||
nOut = etBUFSIZE;
|
||||
zOut = buf;
|
||||
}else{
|
||||
nOut = precision + 10 + precision/3;
|
||||
zOut = zExtra = sqlite3Malloc( nOut );
|
||||
u64 n = (u64)precision + 10 + precision/3;
|
||||
zOut = zExtra = sqlite3Malloc( n );
|
||||
if( zOut==0 ){
|
||||
setStrAccumError(pAccum, STRACCUM_NOMEM);
|
||||
return;
|
||||
}
|
||||
nOut = (int)n;
|
||||
}
|
||||
bufpt = &zOut[nOut-1];
|
||||
if( xtype==etORDINAL ){
|
||||
|
||||
+11
-3
@@ -2085,6 +2085,7 @@ static int callback(void *pArg, int nArg, char **azArg, char **azCol){
|
||||
static int captureOutputCallback(void *pArg, int nArg, char **azArg, char **az){
|
||||
ShellText *p = (ShellText*)pArg;
|
||||
int i;
|
||||
UNUSED_PARAMETER(az);
|
||||
if( p->n ) appendText(p, "|", 0);
|
||||
for(i=0; i<nArg; i++){
|
||||
if( i ) appendText(p, ",", 0);
|
||||
@@ -2926,7 +2927,6 @@ static char **tableColumnList(ShellState *p, const char *zTab){
|
||||
** ordinary column in the table. Verify that azRowid[j] is a valid
|
||||
** name for the rowid before adding it to azCol[0]. WITHOUT ROWID
|
||||
** tables will fail this last check */
|
||||
int rc;
|
||||
rc = sqlite3_table_column_metadata(p->db,0,zTab,azRowid[j],0,0,0,0,0);
|
||||
if( rc==SQLITE_OK ) azCol[0] = azRowid[j];
|
||||
break;
|
||||
@@ -2959,14 +2959,14 @@ static void toggleSelectOrder(sqlite3 *db){
|
||||
** the table type ("index" or "table") and SQL to create the table.
|
||||
** This routine should print text sufficient to recreate the table.
|
||||
*/
|
||||
static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
|
||||
static int dump_callback(void *pArg, int nArg, char **azArg, char **azNotUsed){
|
||||
int rc;
|
||||
const char *zTable;
|
||||
const char *zType;
|
||||
const char *zSql;
|
||||
ShellState *p = (ShellState *)pArg;
|
||||
|
||||
UNUSED_PARAMETER(azCol);
|
||||
UNUSED_PARAMETER(azNotUsed);
|
||||
if( nArg!=3 ) return 1;
|
||||
zTable = azArg[0];
|
||||
zType = azArg[1];
|
||||
@@ -3169,6 +3169,7 @@ static char zHelp[] =
|
||||
".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n"
|
||||
".schema ?PATTERN? Show the CREATE statements matching PATTERN\n"
|
||||
" Add --indent for pretty-printing\n"
|
||||
".selftest ?--init? Run tests defined in the SELFTEST table\n"
|
||||
".separator COL ?ROW? Change the column separator and optionally the row\n"
|
||||
" separator for both the output mode and .import\n"
|
||||
#if defined(SQLITE_ENABLE_SESSION)
|
||||
@@ -4685,7 +4686,14 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
const char *z = azArg[i]+1;
|
||||
if( z[0]=='-' ) z++;
|
||||
if( strcmp(z,"preserve-rowids")==0 ){
|
||||
#ifdef SQLITE_OMIT_VIRTUALTABLE
|
||||
raw_printf(stderr, "The --preserve-rowids option is not compatible"
|
||||
" with SQLITE_OMIT_VIRTUALTABLE\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
#else
|
||||
ShellSetFlag(p, SHFLG_PreserveRowid);
|
||||
#endif
|
||||
}else
|
||||
{
|
||||
raw_printf(stderr, "Unknown option \"%s\" on \".dump\"\n", azArg[i]);
|
||||
|
||||
+6
-5
@@ -114,8 +114,8 @@ extern "C" {
|
||||
** system</a>. ^The SQLITE_SOURCE_ID macro evaluates to
|
||||
** a string which identifies a particular check-in of SQLite
|
||||
** within its configuration management system. ^The SQLITE_SOURCE_ID
|
||||
** string contains the date and time of the check-in (UTC) and an SHA1
|
||||
** hash of the entire source tree.
|
||||
** string contains the date and time of the check-in (UTC) and a SHA1
|
||||
** or SHA3-256 hash of the entire source tree.
|
||||
**
|
||||
** See also: [sqlite3_libversion()],
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
@@ -3425,9 +3425,9 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
**
|
||||
** [[SQLITE_LIMIT_VDBE_OP]] ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
|
||||
** <dd>The maximum number of instructions in a virtual machine program
|
||||
** used to implement an SQL statement. This limit is not currently
|
||||
** enforced, though that might be added in some future release of
|
||||
** SQLite.</dd>)^
|
||||
** used to implement an SQL statement. If [sqlite3_prepare_v2()] or
|
||||
** the equivalent tries to allocate space for more than this many opcodes
|
||||
** in a single prepared statement, an SQLITE_NOMEM error is returned.</dd>)^
|
||||
**
|
||||
** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
|
||||
** <dd>The maximum number of arguments on a function.</dd>)^
|
||||
@@ -3465,6 +3465,7 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
|
||||
#define SQLITE_LIMIT_TRIGGER_DEPTH 10
|
||||
#define SQLITE_LIMIT_WORKER_THREADS 11
|
||||
|
||||
|
||||
/*
|
||||
** CAPI3REF: Compiling An SQL Statement
|
||||
** KEYWORDS: {SQL statement compiler}
|
||||
|
||||
@@ -282,6 +282,8 @@ struct sqlite3_api_routines {
|
||||
/* Version 3.14.0 and later */
|
||||
int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
|
||||
char *(*expanded_sql)(sqlite3_stmt*);
|
||||
/* Version 3.18.0 and later */
|
||||
void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -540,6 +542,8 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
/* Version 3.14.0 and later */
|
||||
#define sqlite3_trace_v2 sqlite3_api->trace_v2
|
||||
#define sqlite3_expanded_sql sqlite3_api->expanded_sql
|
||||
/* Version 3.18.0 and later */
|
||||
#define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
+1
-1
@@ -1127,7 +1127,7 @@ typedef int VList;
|
||||
** and the one-based values are used internally.
|
||||
*/
|
||||
#ifndef SQLITE_DEFAULT_SYNCHRONOUS
|
||||
# define SQLITE_DEFAULT_SYNCHRONOUS (PAGER_SYNCHRONOUS_FULL-1)
|
||||
# define SQLITE_DEFAULT_SYNCHRONOUS 2
|
||||
#endif
|
||||
#ifndef SQLITE_DEFAULT_WAL_SYNCHRONOUS
|
||||
# define SQLITE_DEFAULT_WAL_SYNCHRONOUS SQLITE_DEFAULT_SYNCHRONOUS
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@
|
||||
** Not currently enforced.
|
||||
*/
|
||||
#ifndef SQLITE_MAX_VDBE_OP
|
||||
# define SQLITE_MAX_VDBE_OP 25000
|
||||
# define SQLITE_MAX_VDBE_OP 250000000
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -770,6 +770,8 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
|
||||
LINKVAR( DEFAULT_CACHE_SIZE );
|
||||
LINKVAR( DEFAULT_PAGE_SIZE );
|
||||
LINKVAR( DEFAULT_FILE_FORMAT );
|
||||
LINKVAR( DEFAULT_SYNCHRONOUS );
|
||||
LINKVAR( DEFAULT_WAL_SYNCHRONOUS );
|
||||
LINKVAR( MAX_ATTACHED );
|
||||
LINKVAR( MAX_DEFAULT_PAGE_SIZE );
|
||||
LINKVAR( MAX_WORKER_THREADS );
|
||||
|
||||
@@ -557,6 +557,9 @@ static int jtWrite(
|
||||
u32 pgno = (u32)(iOfst/p->nPagesize + 1);
|
||||
assert( (iAmt==1||iAmt==(int)p->nPagesize) &&
|
||||
((iOfst+iAmt)%p->nPagesize)==0 );
|
||||
/* The following assert() statements may fail if this layer is used
|
||||
** with a connection in "PRAGMA synchronous=off" mode. If they
|
||||
** fail with sync=normal or sync=full, this may indicate problem. */
|
||||
assert( pgno<=p->nPage || p->nSync>0 );
|
||||
assert( pgno>p->nPage || sqlite3BitvecTest(p->pWritable, pgno) );
|
||||
}
|
||||
|
||||
+46
-18
@@ -403,9 +403,7 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
|
||||
}else{
|
||||
c = 's';
|
||||
}
|
||||
|
||||
sqlite3_snprintf(100, zCsr, "%c", c);
|
||||
zCsr += sqlite3Strlen30(zCsr);
|
||||
*(zCsr++) = c;
|
||||
sqlite3_snprintf(100, zCsr, "%d[", pMem->n);
|
||||
zCsr += sqlite3Strlen30(zCsr);
|
||||
for(i=0; i<16 && i<pMem->n; i++){
|
||||
@@ -417,9 +415,7 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
|
||||
if( z<32 || z>126 ) *zCsr++ = '.';
|
||||
else *zCsr++ = z;
|
||||
}
|
||||
|
||||
sqlite3_snprintf(100, zCsr, "]%s", encnames[pMem->enc]);
|
||||
zCsr += sqlite3Strlen30(zCsr);
|
||||
*(zCsr++) = ']';
|
||||
if( f & MEM_Zero ){
|
||||
sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero);
|
||||
zCsr += sqlite3Strlen30(zCsr);
|
||||
@@ -2337,19 +2333,39 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
|
||||
|
||||
/* Opcode: Once P1 P2 * * *
|
||||
**
|
||||
** If the P1 value is equal to the P1 value on the OP_Init opcode at
|
||||
** instruction 0, then jump to P2. If the two P1 values differ, then
|
||||
** set the P1 value on this opcode to equal the P1 value on the OP_Init
|
||||
** and fall through.
|
||||
** Fall through to the next instruction the first time this opcode is
|
||||
** encountered on each invocation of the byte-code program. Jump to P2
|
||||
** on the second and all subsequent encounters during the same invocation.
|
||||
**
|
||||
** Top-level programs determine first invocation by comparing the P1
|
||||
** operand against the P1 operand on the OP_Init opcode at the beginning
|
||||
** of the program. If the P1 values differ, then fall through and make
|
||||
** the P1 of this opcode equal to the P1 of OP_Init. If P1 values are
|
||||
** the same then take the jump.
|
||||
**
|
||||
** For subprograms, there is a bitmask in the VdbeFrame that determines
|
||||
** whether or not the jump should be taken. The bitmask is necessary
|
||||
** because the self-altering code trick does not work for recursive
|
||||
** triggers.
|
||||
*/
|
||||
case OP_Once: { /* jump */
|
||||
u32 iAddr; /* Address of this instruction */
|
||||
assert( p->aOp[0].opcode==OP_Init );
|
||||
VdbeBranchTaken(p->aOp[0].p1==pOp->p1, 2);
|
||||
if( p->aOp[0].p1==pOp->p1 ){
|
||||
goto jump_to_p2;
|
||||
if( p->pFrame ){
|
||||
iAddr = (int)(pOp - p->aOp);
|
||||
if( (p->pFrame->aOnce[iAddr/8] & (1<<(iAddr & 7)))!=0 ){
|
||||
VdbeBranchTaken(1, 2);
|
||||
goto jump_to_p2;
|
||||
}
|
||||
p->pFrame->aOnce[iAddr/8] |= 1<<(iAddr & 7);
|
||||
}else{
|
||||
pOp->p1 = p->aOp[0].p1;
|
||||
if( p->aOp[0].p1==pOp->p1 ){
|
||||
VdbeBranchTaken(1, 2);
|
||||
goto jump_to_p2;
|
||||
}
|
||||
}
|
||||
VdbeBranchTaken(0, 2);
|
||||
pOp->p1 = p->aOp[0].p1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2662,8 +2678,13 @@ case OP_Column: {
|
||||
** 2. the length(X) function if X is a blob, and
|
||||
** 3. if the content length is zero.
|
||||
** So we might as well use bogus content rather than reading
|
||||
** content from disk. */
|
||||
static u8 aZero[8]; /* This is the bogus content */
|
||||
** content from disk.
|
||||
**
|
||||
** Although sqlite3VdbeSerialGet() may read at most 8 bytes from the
|
||||
** buffer passed to it, debugging function VdbeMemPrettyPrint() may
|
||||
** read up to 16. So 16 bytes of bogus content is supplied.
|
||||
*/
|
||||
static u8 aZero[16]; /* This is the bogus content */
|
||||
sqlite3VdbeSerialGet(aZero, t, pDest);
|
||||
}else{
|
||||
rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest);
|
||||
@@ -5870,7 +5891,8 @@ case OP_Program: { /* jump */
|
||||
if( pProgram->nCsr==0 ) nMem++;
|
||||
nByte = ROUND8(sizeof(VdbeFrame))
|
||||
+ nMem * sizeof(Mem)
|
||||
+ pProgram->nCsr * sizeof(VdbeCursor *);
|
||||
+ pProgram->nCsr * sizeof(VdbeCursor*)
|
||||
+ (pProgram->nOp + 7)/8;
|
||||
pFrame = sqlite3DbMallocZero(db, nByte);
|
||||
if( !pFrame ){
|
||||
goto no_mem;
|
||||
@@ -5921,6 +5943,8 @@ case OP_Program: { /* jump */
|
||||
p->nMem = pFrame->nChildMem;
|
||||
p->nCursor = (u16)pFrame->nChildCsr;
|
||||
p->apCsr = (VdbeCursor **)&aMem[p->nMem];
|
||||
pFrame->aOnce = (u8*)&p->apCsr[pProgram->nCsr];
|
||||
memset(pFrame->aOnce, 0, (pProgram->nOp + 7)/8);
|
||||
p->aOp = aOp = pProgram->aOp;
|
||||
p->nOp = pProgram->nOp;
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
@@ -6950,7 +6974,11 @@ case OP_Init: { /* jump */
|
||||
sqlite3_free(z);
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
if( db->nVdbeExec>1 ){
|
||||
char *z = sqlite3MPrintf(db, "-- %s", zTrace);
|
||||
(void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, z);
|
||||
sqlite3DbFree(db, z);
|
||||
}else{
|
||||
(void)db->xTrace(SQLITE_TRACE_STMT, db->pTraceArg, p, zTrace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ struct SubProgram {
|
||||
int nOp; /* Elements in aOp[] */
|
||||
int nMem; /* Number of memory cells required */
|
||||
int nCsr; /* Number of cursors required */
|
||||
u8 *aOnce; /* Array of OP_Once flags */
|
||||
void *token; /* id that may be used to recursive triggers */
|
||||
SubProgram *pNext; /* Next sub-program already visited */
|
||||
};
|
||||
|
||||
@@ -164,6 +164,7 @@ struct VdbeFrame {
|
||||
i64 *anExec; /* Event counters from parent frame */
|
||||
Mem *aMem; /* Array of memory cells for parent frame */
|
||||
VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
|
||||
u8 *aOnce; /* Bitmask used by OP_Once */
|
||||
void *token; /* Copy of SubProgram.token */
|
||||
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
|
||||
AuxData *pAuxData; /* Linked list of auxdata allocations */
|
||||
|
||||
@@ -117,6 +117,12 @@ static int growOpArray(Vdbe *v, int nOp){
|
||||
UNUSED_PARAMETER(nOp);
|
||||
#endif
|
||||
|
||||
/* Ensure that the size of a VDBE does not grow too large */
|
||||
if( nNew > p->db->aLimit[SQLITE_LIMIT_VDBE_OP] ){
|
||||
sqlite3OomFault(p->db);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
assert( nOp<=(1024/sizeof(Op)) );
|
||||
assert( nNew>=(p->nOpAlloc+nOp) );
|
||||
pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
|
||||
|
||||
@@ -29,7 +29,7 @@ source $testdir/tester.tcl
|
||||
# These tests also use "PRAGMA stats" which are only enabled for
|
||||
# debugging builds.
|
||||
#
|
||||
ifcapable {!debug || !analyze} {
|
||||
ifcapable {!debug || !analyze || !vtab} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
+11
-1
@@ -481,6 +481,16 @@ do_catchsql_test 9.3 {
|
||||
UPDATE t1 SET c=a*2 WHERE a=1;
|
||||
} {1 {CHECK constraint failed: c-check}}
|
||||
|
||||
|
||||
# Integrity check on a VIEW with columns.
|
||||
#
|
||||
db close
|
||||
db2 close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 10.1 {
|
||||
CREATE TABLE t1(x);
|
||||
CREATE VIEW v1(y) AS SELECT x FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix collateB
|
||||
|
||||
do_execsql_test collateB-1.1 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY);
|
||||
@@ -60,4 +61,17 @@ do_execsql_test collateB-1.17 {
|
||||
SELECT *,'|' FROM t1, t2, t3 WHERE b=x2 AND a=x1 AND 1=a;
|
||||
} {1 11 1 11 |}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test an assert() failure that was occuring if an index were created
|
||||
# on a column explicitly declared "COLLATE binary".
|
||||
reset_db
|
||||
do_execsql_test 2.1 {
|
||||
CREATE TABLE t4(a COLLATE binary);
|
||||
CREATE INDEX i4 ON t4(a);
|
||||
INSERT INTO t4 VALUES('one'), ('two'), ('three');
|
||||
VACUUM;
|
||||
}
|
||||
|
||||
integrity_check 2.2
|
||||
|
||||
finish_test
|
||||
|
||||
+21
-5
@@ -805,6 +805,7 @@ static void showHelp(void){
|
||||
" --load-db ARGS... Load template databases from files into SOURCE_DB\n"
|
||||
" -m TEXT Add a description to the database\n"
|
||||
" --native-vfs Use the native VFS for initially empty database files\n"
|
||||
" --native-malloc Turn off MEMSYS3/5 and Lookaside\n"
|
||||
" --oss-fuzz Enable OSS-FUZZ testing\n"
|
||||
" --prng-seed N Seed value for the PRGN inside of SQLite\n"
|
||||
" --rebuild Rebuild and vacuum the database file\n"
|
||||
@@ -851,6 +852,7 @@ int main(int argc, char **argv){
|
||||
void *pHeap = 0; /* Heap for use by SQLite */
|
||||
int ossFuzz = 0; /* enable OSS-FUZZ testing */
|
||||
int ossFuzzThisDb = 0; /* ossFuzz value for this particular database */
|
||||
int nativeMalloc = 0; /* Turn off MEMSYS3/5 and lookaside if true */
|
||||
sqlite3_vfs *pDfltVfs; /* The default VFS */
|
||||
|
||||
iBegin = timeOfDay();
|
||||
@@ -911,6 +913,9 @@ int main(int argc, char **argv){
|
||||
if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
|
||||
zMsg = argv[++i];
|
||||
}else
|
||||
if( strcmp(z,"native-malloc")==0 ){
|
||||
nativeMalloc = 1;
|
||||
}else
|
||||
if( strcmp(z,"native-vfs")==0 ){
|
||||
nativeFlag = 1;
|
||||
}else
|
||||
@@ -972,7 +977,7 @@ int main(int argc, char **argv){
|
||||
/* Process each source database separately */
|
||||
for(iSrcDb=0; iSrcDb<nSrcDb; iSrcDb++){
|
||||
rc = sqlite3_open_v2(azSrcDb[iSrcDb], &db,
|
||||
SQLITE_OPEN_READONLY, pDfltVfs->zName);
|
||||
SQLITE_OPEN_READWRITE, pDfltVfs->zName);
|
||||
if( rc ){
|
||||
fatalError("cannot open source database %s - %s",
|
||||
azSrcDb[iSrcDb], sqlite3_errmsg(db));
|
||||
@@ -1013,7 +1018,7 @@ int main(int argc, char **argv){
|
||||
ossFuzzThisDb = sqlite3_column_int(pStmt,1);
|
||||
if( verboseFlag ) printf("Config: oss-fuzz=%d\n", ossFuzzThisDb);
|
||||
}
|
||||
if( strcmp(zName, "limit-mem")==0 ){
|
||||
if( strcmp(zName, "limit-mem")==0 && !nativeMalloc ){
|
||||
#if !defined(SQLITE_ENABLE_MEMSYS3) && !defined(SQLITE_ENABLE_MEMSYS5)
|
||||
fatalError("the limit-mem option requires -DSQLITE_ENABLE_MEMSYS5"
|
||||
" or _MEMSYS3");
|
||||
@@ -1047,6 +1052,8 @@ int main(int argc, char **argv){
|
||||
sqlite3_close(db);
|
||||
return 0;
|
||||
}
|
||||
rc = sqlite3_exec(db, "PRAGMA query_only=1;", 0, 0, 0);
|
||||
if( rc ) fatalError("cannot set database to query-only");
|
||||
if( zExpDb!=0 || zExpSql!=0 ){
|
||||
sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
|
||||
writefileFunc, 0, 0);
|
||||
@@ -1141,14 +1148,19 @@ int main(int argc, char **argv){
|
||||
}
|
||||
|
||||
/* Limit available memory, if requested */
|
||||
if( nMemThisDb>0 ){
|
||||
sqlite3_shutdown();
|
||||
sqlite3_shutdown();
|
||||
if( nMemThisDb>0 && !nativeMalloc ){
|
||||
pHeap = realloc(pHeap, nMemThisDb);
|
||||
if( pHeap==0 ){
|
||||
fatalError("failed to allocate %d bytes of heap memory", nMem);
|
||||
}
|
||||
sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nMemThisDb, 128);
|
||||
}
|
||||
|
||||
/* Disable lookaside with the --native-malloc option */
|
||||
if( nativeMalloc ){
|
||||
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
|
||||
}
|
||||
|
||||
/* Reset the in-memory virtual filesystem */
|
||||
formatVfs();
|
||||
@@ -1205,9 +1217,13 @@ int main(int argc, char **argv){
|
||||
runSql(db, (char*)pSql->a, runFlags);
|
||||
}while( timeoutTest );
|
||||
setAlarm(0);
|
||||
sqlite3_exec(db, "PRAGMA temp_store_directory=''", 0, 0, 0);
|
||||
sqlite3_close(db);
|
||||
}
|
||||
if( sqlite3_memory_used()>0 ) fatalError("memory leak");
|
||||
if( sqlite3_memory_used()>0 ){
|
||||
fatalError("memory leak: %lld bytes outstanding",
|
||||
sqlite3_memory_used());
|
||||
}
|
||||
reformatVfs();
|
||||
nTest++;
|
||||
g.zTestName[0] = 0;
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
# 2017-03-22
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements tests for json_patch(A,B) SQL function.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable !json1 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# This is the example from pages 2 and 3 of RFC-7396
|
||||
do_execsql_test json104-100 {
|
||||
SELECT json_patch('{
|
||||
"a": "b",
|
||||
"c": {
|
||||
"d": "e",
|
||||
"f": "g"
|
||||
}
|
||||
}','{
|
||||
"a":"z",
|
||||
"c": {
|
||||
"f": null
|
||||
}
|
||||
}');
|
||||
} {{{"a":"z","c":{"d":"e"}}}}
|
||||
|
||||
|
||||
# This is the example from pages 4 and 5 of RFC-7396
|
||||
do_execsql_test json104-110 {
|
||||
SELECT json_patch('{
|
||||
"title": "Goodbye!",
|
||||
"author" : {
|
||||
"givenName" : "John",
|
||||
"familyName" : "Doe"
|
||||
},
|
||||
"tags":[ "example", "sample" ],
|
||||
"content": "This will be unchanged"
|
||||
}','{
|
||||
"title": "Hello!",
|
||||
"phoneNumber": "+01-123-456-7890",
|
||||
"author": {
|
||||
"familyName": null
|
||||
},
|
||||
"tags": [ "example" ]
|
||||
}');
|
||||
} {{{"title":"Hello!","author":{"givenName":"John"},"tags":["example"],"content":"This will be unchanged","phoneNumber":"+01-123-456-7890"}}}
|
||||
|
||||
do_execsql_test json104-200 {
|
||||
SELECT json_patch('[1,2,3]','{"x":null}');
|
||||
} {{{}}}
|
||||
do_execsql_test json104-210 {
|
||||
SELECT json_patch('[1,2,3]','{"x":null,"y":1,"z":null}');
|
||||
} {{{"y":1}}}
|
||||
do_execsql_test json104-220 {
|
||||
SELECT json_patch('{}','{"a":{"bb":{"ccc":null}}}');
|
||||
} {{{"a":{"bb":{}}}}}
|
||||
do_execsql_test json104-221 {
|
||||
SELECT json_patch('{}','{"a":{"bb":{"ccc":[1,null,3]}}}');
|
||||
} {{{"a":{"bb":{"ccc":[1,null,3]}}}}}
|
||||
do_execsql_test json104-222 {
|
||||
SELECT json_patch('{}','{"a":{"bb":{"ccc":[1,{"dddd":null},3]}}}');
|
||||
} {{{"a":{"bb":{"ccc":[1,{"dddd":null},3]}}}}}
|
||||
|
||||
# Example test cases at the end of the RFC-7396 document
|
||||
do_execsql_test json104-300 {
|
||||
SELECT json_patch('{"a":"b"}','{"a":"c"}');
|
||||
} {{{"a":"c"}}}
|
||||
do_execsql_test json104-300a {
|
||||
SELECT coalesce(json_patch(null,'{"a":"c"}'), 'real-null');
|
||||
} {{real-null}}
|
||||
do_execsql_test json104-301 {
|
||||
SELECT json_patch('{"a":"b"}','{"b":"c"}');
|
||||
} {{{"a":"b","b":"c"}}}
|
||||
do_execsql_test json104-302 {
|
||||
SELECT json_patch('{"a":"b"}','{"a":null}');
|
||||
} {{{}}}
|
||||
do_execsql_test json104-303 {
|
||||
SELECT json_patch('{"a":"b","b":"c"}','{"a":null}');
|
||||
} {{{"b":"c"}}}
|
||||
do_execsql_test json104-304 {
|
||||
SELECT json_patch('{"a":["b"]}','{"a":"c"}');
|
||||
} {{{"a":"c"}}}
|
||||
do_execsql_test json104-305 {
|
||||
SELECT json_patch('{"a":"c"}','{"a":["b"]}');
|
||||
} {{{"a":["b"]}}}
|
||||
do_execsql_test json104-306 {
|
||||
SELECT json_patch('{"a":{"b":"c"}}','{"a":{"b":"d","c":null}}');
|
||||
} {{{"a":{"b":"d"}}}}
|
||||
do_execsql_test json104-307 {
|
||||
SELECT json_patch('{"a":[{"b":"c"}]}','{"a":[1]}');
|
||||
} {{{"a":[1]}}}
|
||||
do_execsql_test json104-308 {
|
||||
SELECT json_patch('["a","b"]','["c","d"]');
|
||||
} {{["c","d"]}}
|
||||
do_execsql_test json104-309 {
|
||||
SELECT json_patch('{"a":"b"}','["c"]');
|
||||
} {{["c"]}}
|
||||
do_execsql_test json104-310 {
|
||||
SELECT json_patch('{"a":"foo"}','null');
|
||||
} {{null}}
|
||||
do_execsql_test json104-310a {
|
||||
SELECT coalesce(json_patch('{"a":"foo"}',null), 'real-null');
|
||||
} {{real-null}}
|
||||
do_execsql_test json104-311 {
|
||||
SELECT json_patch('{"a":"foo"}','"bar"');
|
||||
} {{"bar"}}
|
||||
do_execsql_test json104-312 {
|
||||
SELECT json_patch('{"e":null}','{"a":1}');
|
||||
} {{{"e":null,"a":1}}}
|
||||
do_execsql_test json104-313 {
|
||||
SELECT json_patch('[1,2]','{"a":"b","c":null}');
|
||||
} {{{"a":"b"}}}
|
||||
do_execsql_test json104-314 {
|
||||
SELECT json_patch('{}','{"a":{"bb":{"ccc":null}}}');
|
||||
} {{{"a":{"bb":{}}}}}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
+17
-1
@@ -21,7 +21,7 @@ sqlite3_db_config_lookaside db 0 0 0
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(x);
|
||||
}
|
||||
do_faultsim_test 1 -faults oom-t* -body {
|
||||
do_faultsim_test 1 -faults oom* -body {
|
||||
execsql {
|
||||
SELECT 'abc' FROM ( SELECT 'xyz' FROM t1 WHERE (SELECT 1) )
|
||||
}
|
||||
@@ -29,4 +29,20 @@ do_faultsim_test 1 -faults oom-t* -body {
|
||||
faultsim_test_result {0 {}}
|
||||
}
|
||||
|
||||
do_execsql_test 2.0.1 { SELECT instr(x'', x'') } {1}
|
||||
do_execsql_test 2.0.2 { SELECT instr(x'12345678', x'') } {1}
|
||||
do_execsql_test 2.0.3 { SELECT instr(x'', x'1234') } {0}
|
||||
|
||||
do_faultsim_test 2.1 -faults oom* -body {
|
||||
execsql { SELECT instr (x'00', zeroblob(1)) }
|
||||
} -test {
|
||||
faultsim_test_result {0 1}
|
||||
}
|
||||
|
||||
do_faultsim_test 2.2 -faults oom* -body {
|
||||
execsql { SELECT instr (zeroblob(1), x'00') }
|
||||
} -test {
|
||||
faultsim_test_result {0 1}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+60
-11
@@ -4,8 +4,26 @@
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "sqlite3.h"
|
||||
|
||||
/* Global debugging settings. OSS-Fuzz will have all debugging turned
|
||||
** off. But if LLVMFuzzerTestOneInput() is called interactively from
|
||||
** the ossshell utility program, then these flags might be set.
|
||||
*/
|
||||
static unsigned mDebug = 0;
|
||||
#define FUZZ_SQL_TRACE 0x0001 /* Set an sqlite3_trace() callback */
|
||||
#define FUZZ_SHOW_MAX_DELAY 0x0002 /* Show maximum progress callback delay */
|
||||
#define FUZZ_SHOW_ERRORS 0x0004 /* Print error messages from SQLite */
|
||||
|
||||
/* The ossshell utility program invokes this interface to see the
|
||||
** debugging flags. Unused by OSS-Fuzz.
|
||||
*/
|
||||
void ossfuzz_set_debug_flags(unsigned x){
|
||||
mDebug = x;
|
||||
}
|
||||
|
||||
/* Return the current real-world time in milliseconds since the
|
||||
** Julian epoch (-4714-11-24).
|
||||
*/
|
||||
@@ -23,6 +41,17 @@ static sqlite3_int64 timeOfDay(void){
|
||||
return t;
|
||||
}
|
||||
|
||||
/* An instance of the following object is passed by pointer as the
|
||||
** client data to various callbacks.
|
||||
*/
|
||||
typedef struct FuzzCtx {
|
||||
sqlite3 *db; /* The database connection */
|
||||
sqlite3_int64 iCutoffTime; /* Stop processing at this time. */
|
||||
sqlite3_int64 iLastCb; /* Time recorded for previous progress callback */
|
||||
sqlite3_int64 mxInterval; /* Longest interval between two progress calls */
|
||||
unsigned nCb; /* Number of progress callbacks */
|
||||
} FuzzCtx;
|
||||
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
/*
|
||||
** Progress handler callback.
|
||||
@@ -30,9 +59,14 @@ static sqlite3_int64 timeOfDay(void){
|
||||
** The argument is the cutoff-time after which all processing should
|
||||
** stop. So return non-zero if the cut-off time is exceeded.
|
||||
*/
|
||||
static int progress_handler(void *pReturn) {
|
||||
sqlite3_int64 iCutoffTime = *(sqlite3_int64*)pReturn;
|
||||
return timeOfDay()>=iCutoffTime;
|
||||
static int progress_handler(void *pClientData) {
|
||||
FuzzCtx *p = (FuzzCtx*)pClientData;
|
||||
sqlite3_int64 iNow = timeOfDay();
|
||||
int rc = iNow>=p->iCutoffTime;
|
||||
sqlite3_int64 iDiff = iNow - p->iLastCb;
|
||||
if( iDiff > p->mxInterval ) p->mxInterval = iDiff;
|
||||
p->nCb++;
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -54,12 +88,12 @@ static int exec_handler(void *pCnt, int argc, char **argv, char **namev){
|
||||
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
int execCnt = 0; /* Abort row callback when count reaches zero */
|
||||
char *zErrMsg = 0; /* Error message returned by sqlite_exec() */
|
||||
sqlite3 *db; /* The database connection */
|
||||
uint8_t uSelector; /* First byte of input data[] */
|
||||
int rc; /* Return code from various interfaces */
|
||||
char *zSql; /* Zero-terminated copy of data[] */
|
||||
sqlite3_int64 iCutoff; /* Cutoff timer */
|
||||
FuzzCtx cx; /* Fuzzing context */
|
||||
|
||||
memset(&cx, 0, sizeof(cx));
|
||||
if( size<3 ) return 0; /* Early out if unsufficient data */
|
||||
|
||||
/* Extract the selector byte from the beginning of the input. But only
|
||||
@@ -72,7 +106,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
}
|
||||
|
||||
/* Open the database connection. Only use an in-memory database. */
|
||||
rc = sqlite3_open_v2("fuzz.db", &db,
|
||||
rc = sqlite3_open_v2("fuzz.db", &cx.db,
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY, 0);
|
||||
if( rc ) return 0;
|
||||
|
||||
@@ -82,12 +116,16 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
** (which will block further processing) if more than 10 seconds have
|
||||
** elapsed since the start of the test.
|
||||
*/
|
||||
iCutoff = timeOfDay() + 10000; /* Now + 10 seconds */
|
||||
sqlite3_progress_handler(db, 10, progress_handler, (void*)&iCutoff);
|
||||
cx.iLastCb = timeOfDay();
|
||||
cx.iCutoffTime = cx.iLastCb + 10000; /* Now + 10 seconds */
|
||||
sqlite3_progress_handler(cx.db, 10, progress_handler, (void*)&cx);
|
||||
#endif
|
||||
|
||||
/* Set a limit on the maximum size of a prepared statement */
|
||||
sqlite3_limit(cx.db, SQLITE_LIMIT_VDBE_OP, 25000);
|
||||
|
||||
/* Bit 1 of the selector enables foreign key constraints */
|
||||
sqlite3_db_config(db, SQLITE_DBCONFIG_ENABLE_FKEY, uSelector&1, &rc);
|
||||
sqlite3_db_config(cx.db, SQLITE_DBCONFIG_ENABLE_FKEY, uSelector&1, &rc);
|
||||
uSelector >>= 1;
|
||||
|
||||
/* Remaining bits of the selector determine a limit on the number of
|
||||
@@ -97,11 +135,22 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
/* Run the SQL. The sqlite_exec() interface expects a zero-terminated
|
||||
** string, so make a copy. */
|
||||
zSql = sqlite3_mprintf("%.*s", (int)size, data);
|
||||
sqlite3_exec(db, zSql, exec_handler, (void*)&execCnt, &zErrMsg);
|
||||
sqlite3_exec(cx.db, zSql, exec_handler, (void*)&execCnt, &zErrMsg);
|
||||
|
||||
/* Show any errors */
|
||||
if( (mDebug & FUZZ_SHOW_ERRORS)!=0 && zErrMsg ){
|
||||
printf("Error: %s\n", zErrMsg);
|
||||
}
|
||||
|
||||
/* Cleanup and return */
|
||||
sqlite3_free(zErrMsg);
|
||||
sqlite3_free(zSql);
|
||||
sqlite3_close(db);
|
||||
sqlite3_exec(cx.db, "PRAGMA temp_store_directory=''", 0, 0, 0);
|
||||
sqlite3_close(cx.db);
|
||||
|
||||
if( mDebug & FUZZ_SHOW_MAX_DELAY ){
|
||||
printf("Progress callback count....... %d\n", cx.nCb);
|
||||
printf("Max time between callbacks.... %d ms\n", (int)cx.mxInterval);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sqlite3.h"
|
||||
|
||||
/*
|
||||
@@ -16,6 +17,13 @@
|
||||
*/
|
||||
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
|
||||
|
||||
/* Must match equivalent #defines in ossfuzz.c */
|
||||
#define FUZZ_SQL_TRACE 0x0001 /* Set an sqlite3_trace() callback */
|
||||
#define FUZZ_SHOW_MAX_DELAY 0x0002 /* Show maximum progress callback delay */
|
||||
#define FUZZ_SHOW_ERRORS 0x0004 /* Show SQL errors */
|
||||
extern void ossfuzz_set_debug_flags(unsigned);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Read files named on the command-line and invoke the fuzzer for
|
||||
@@ -27,9 +35,32 @@ int main(int argc, char **argv){
|
||||
int nErr = 0;
|
||||
uint8_t *zBuf = 0;
|
||||
size_t sz;
|
||||
unsigned mDebug = 0;
|
||||
|
||||
for(i=1; i<argc; i++){
|
||||
const char *zFilename = argv[i];
|
||||
if( zFilename[0]=='-' ){
|
||||
if( zFilename[1]=='-' ) zFilename++;
|
||||
if( strcmp(zFilename, "-show-errors")==0 ){
|
||||
mDebug |= FUZZ_SHOW_ERRORS;
|
||||
ossfuzz_set_debug_flags(mDebug);
|
||||
}else
|
||||
if( strcmp(zFilename, "-show-max-delay")==0 ){
|
||||
mDebug |= FUZZ_SHOW_MAX_DELAY;
|
||||
ossfuzz_set_debug_flags(mDebug);
|
||||
}else
|
||||
if( strcmp(zFilename, "-sql-trace")==0 ){
|
||||
mDebug |= FUZZ_SQL_TRACE;
|
||||
ossfuzz_set_debug_flags(mDebug);
|
||||
}else
|
||||
{
|
||||
printf("unknown option \"%s\"\n", argv[i]);
|
||||
printf("should be one of: --show-errors --show-max-delay"
|
||||
" --sql-trace\n");
|
||||
exit(1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
in = fopen(zFilename, "rb");
|
||||
if( in==0 ){
|
||||
fprintf(stderr, "cannot open \"%s\"\n", zFilename);
|
||||
@@ -50,8 +81,10 @@ int main(int argc, char **argv){
|
||||
nErr++;
|
||||
}else{
|
||||
printf("%s... ", zFilename);
|
||||
if( mDebug ) printf("\n");
|
||||
fflush(stdout);
|
||||
(void)LLVMFuzzerTestOneInput(zBuf, sz);
|
||||
if( mDebug ) printf("%s: ", zFilename);
|
||||
printf("ok\n");
|
||||
}
|
||||
fclose(in);
|
||||
|
||||
+18
-16
@@ -247,22 +247,24 @@ test_suite "threads" -prefix "" -description {
|
||||
test_suite "fts3" -prefix "" -description {
|
||||
All FTS3 tests except fts3rnd.test.
|
||||
} -files {
|
||||
fts3aa.test fts3ab.test fts3ac.test fts3ad.test fts3ae.test
|
||||
fts3af.test fts3ag.test fts3ah.test fts3ai.test fts3aj.test
|
||||
fts3ak.test fts3al.test fts3am.test fts3an.test fts3ao.test
|
||||
fts3atoken.test fts3b.test fts3c.test fts3cov.test fts3d.test
|
||||
fts3defer.test fts3defer2.test fts3e.test fts3expr.test fts3expr2.test
|
||||
fts3expr3.test
|
||||
fts3near.test fts3query.test fts3shared.test fts3snippet.test
|
||||
fts3sort.test
|
||||
fts3fault.test fts3malloc.test fts3matchinfo.test
|
||||
fts3aux1.test fts3comp1.test fts3auto.test
|
||||
fts4aa.test fts4content.test
|
||||
fts3conf.test fts3prefix.test fts3fault2.test fts3corrupt.test
|
||||
fts3corrupt2.test fts3first.test fts4langid.test fts4merge.test
|
||||
fts4check.test fts4unicode.test fts4noti.test
|
||||
fts3varint.test
|
||||
fts4growth.test fts4growth2.test
|
||||
fts3aa.test fts3ab.test fts3ac.test fts3ad.test
|
||||
fts3ae.test fts3af.test fts3ag.test fts3ah.test
|
||||
fts3ai.test fts3aj.test fts3ak.test fts3al.test
|
||||
fts3am.test fts3an.test fts3ao.test fts3atoken.test
|
||||
fts3auto.test fts3aux1.test fts3aux2.test fts3b.test
|
||||
fts3comp1.test fts3conf.test fts3corrupt2.test fts3corrupt.test
|
||||
fts3cov.test fts3c.test fts3defer2.test fts3defer3.test
|
||||
fts3defer.test fts3drop.test fts3d.test fts3e.test
|
||||
fts3expr2.test fts3expr3.test fts3expr4.test fts3expr5.test
|
||||
fts3expr.test fts3fault2.test fts3fault.test fts3first.test
|
||||
fts3join.test fts3malloc.test fts3matchinfo.test fts3near.test
|
||||
fts3offsets.test fts3prefix2.test fts3prefix.test fts3query.test
|
||||
fts3shared.test fts3snippet.test fts3sort.test fts3tok1.test
|
||||
fts3tok_err.test fts3varint.test fts4aa.test fts4check.test
|
||||
fts4content.test fts4docid.test fts4growth2.test fts4growth.test
|
||||
fts4incr.test fts4langid.test fts4lastrowid.test fts4merge2.test
|
||||
fts4merge4.test fts4merge.test fts4noti.test fts4onepass.test
|
||||
fts4opt.test fts4unicode.test
|
||||
}
|
||||
|
||||
test_suite "fts5" -prefix "" -description {
|
||||
|
||||
@@ -755,6 +755,9 @@ INSERT INTO t3 VALUES(5,'hello');
|
||||
INSERT INTO t3 VALUES(6,X'807f');
|
||||
COMMIT;}}
|
||||
|
||||
|
||||
ifcapable vtab {
|
||||
|
||||
# The --preserve-rowids option to .dump
|
||||
#
|
||||
do_test shell1-4.1.1 {
|
||||
@@ -868,6 +871,23 @@ INSERT INTO t1 VALUES(12,'',99);
|
||||
INSERT INTO t1 VALUES(23,1,X'b0b1b2');
|
||||
COMMIT;}}
|
||||
|
||||
} else {
|
||||
|
||||
do_test shell1-4.1.6 {
|
||||
db close
|
||||
forcedelete test2.db
|
||||
sqlite3 db test2.db
|
||||
db eval {
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY, y);
|
||||
INSERT INTO t1 VALUES(1,null), (2,''), (3,1),
|
||||
(4,2.25), (5,'hello'), (6,x'807f');
|
||||
}
|
||||
catchcmd test2.db {.dump --preserve-rowids}
|
||||
} {1 {The --preserve-rowids option is not compatible with SQLITE_OMIT_VIRTUALTABLE}}
|
||||
|
||||
}
|
||||
|
||||
|
||||
# Test the output of ".mode insert"
|
||||
#
|
||||
do_test shell1-4.2.1 {
|
||||
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
# 2017 March 16
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
# Specificly, it tests that "PRAGMA synchronous" appears to work.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix sync2
|
||||
|
||||
#
|
||||
# These tests are only applicable when pager pragma are
|
||||
# enabled. Also, since every test uses an ATTACHed database, they
|
||||
# are only run when ATTACH is enabled.
|
||||
#
|
||||
ifcapable !pager_pragmas||!attach {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
if {$::tcl_platform(platform)!="unix"
|
||||
|| [permutation] == "journaltest"
|
||||
|| [permutation] == "inmemory_journal"
|
||||
} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc execsql_sync {sql} {
|
||||
set s $::sqlite_sync_count
|
||||
set res [execsql $sql]
|
||||
concat [expr $::sqlite_sync_count-$s] $res
|
||||
}
|
||||
|
||||
proc do_execsql_sync_test {tn sql res} {
|
||||
uplevel [list do_test $tn [list execsql_sync $sql] [list {*}$res]]
|
||||
}
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests for journal mode.
|
||||
#
|
||||
sqlite3 db test.db
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b);
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
}
|
||||
|
||||
do_execsql_sync_test 1.1 { INSERT INTO t1 VALUES(3, 4) } 4
|
||||
|
||||
# synchronous=normal. So, 1 sync on the directory, 1 on the journal, 1
|
||||
# on the db file. 3 in total.
|
||||
do_execsql_test 1.2.1 { PRAGMA main.synchronous = NORMAL }
|
||||
do_execsql_test 1.2.2 { PRAGMA main.synchronous } 1
|
||||
do_execsql_sync_test 1.2.3 { INSERT INTO t1 VALUES(5, 6) } 3
|
||||
|
||||
# synchronous=off. No syncs.
|
||||
do_execsql_test 1.3.1 { PRAGMA main.synchronous = OFF }
|
||||
do_execsql_test 1.3.2 { PRAGMA main.synchronous } 0
|
||||
do_execsql_sync_test 1.3.3 { INSERT INTO t1 VALUES(7, 8) } 0
|
||||
|
||||
# synchronous=full, journal_mode=delete. So, 1 sync on the directory,
|
||||
# 2 on the journal, 1 on the db file. 4 in total.
|
||||
do_execsql_test 1.4.1 { PRAGMA main.synchronous = FULL }
|
||||
do_execsql_test 1.4.2 { PRAGMA main.synchronous } 2
|
||||
do_execsql_sync_test 1.4.3 { INSERT INTO t1 VALUES(9, 10) } 4
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests for wal mode.
|
||||
#
|
||||
do_execsql_test 1.5 { PRAGMA journal_mode = wal } {wal}
|
||||
|
||||
# sync=full, journal_mode=wal. One sync on the directory, two on the
|
||||
# wal file.
|
||||
do_execsql_sync_test 1.6 { INSERT INTO t1 VALUES(11, 12) } 3
|
||||
|
||||
# One sync on the wal file.
|
||||
do_execsql_sync_test 1.7 { INSERT INTO t1 VALUES(13, 14) } 1
|
||||
|
||||
# No syncs.
|
||||
do_execsql_test 1.8.1 { PRAGMA main.synchronous = NORMAL }
|
||||
do_execsql_test 1.8.2 { PRAGMA main.synchronous } 1
|
||||
do_execsql_sync_test 1.8.3 { INSERT INTO t1 VALUES(15, 16) } 0
|
||||
|
||||
# One sync on wal file, one on the db file.
|
||||
do_execsql_sync_test 1.9 { PRAGMA wal_checkpoint } {2 0 3 3}
|
||||
|
||||
# No syncs.
|
||||
do_execsql_test 1.10.1 { PRAGMA main.synchronous = OFF }
|
||||
do_execsql_test 1.10.2 { PRAGMA main.synchronous } 0
|
||||
do_execsql_sync_test 1.10.3 { INSERT INTO t1 VALUES(17, 18) } 0
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Tests for the compile time settings SQLITE_DEFAULT_SYNCHRONOUS and
|
||||
# SQLITE_DEFAULT_WAL_SYNCHRONOUS. These tests only run if the former
|
||||
# is set to "2" and the latter to "1". This is not the default, but
|
||||
# it is currently the recommended configuration.
|
||||
#
|
||||
# https://sqlite.org/compile.html#recommended_compile_time_options
|
||||
#
|
||||
if {$SQLITE_DEFAULT_SYNCHRONOUS==2 && $SQLITE_DEFAULT_WAL_SYNCHRONOUS==1} {
|
||||
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
|
||||
# Wal mode, sync=normal. The first transaction does one sync on directory,
|
||||
# one on the wal file. The second does no syncs.
|
||||
do_execsql_sync_test 1.11.1 { INSERT INTO t1 VALUES(19, 20) } 2
|
||||
do_execsql_sync_test 1.11.2 { INSERT INTO t1 VALUES(21, 22) } 0
|
||||
do_execsql_test 1.11.3 { PRAGMA main.synchronous } 1
|
||||
|
||||
# One sync on wal file, one on the db file.
|
||||
do_execsql_sync_test 1.12 { PRAGMA wal_checkpoint } {2 0 2 2}
|
||||
|
||||
# First transaction syncs the wal file once, the second not at all.
|
||||
# one on the wal file. The second does no syncs.
|
||||
do_execsql_sync_test 1.13.1 { INSERT INTO t1 VALUES(22, 23) } 1
|
||||
do_execsql_sync_test 1.13.2 { INSERT INTO t1 VALUES(24, 25) } 0
|
||||
|
||||
do_execsql_test 1.14 { PRAGMA journal_mode = delete } {delete}
|
||||
|
||||
# Delete mode, sync=full. The first transaction does one sync on
|
||||
# directory, two on the journal file, one on the db. The second does
|
||||
# the same.
|
||||
do_execsql_sync_test 1.15.1 { INSERT INTO t1 VALUES(26, 27) } 4
|
||||
do_execsql_sync_test 1.15.2 { INSERT INTO t1 VALUES(28, 29) } 4
|
||||
do_execsql_test 1.15.3 { PRAGMA main.synchronous } 2
|
||||
|
||||
# Switch back to wal mode.
|
||||
do_execsql_test 1.16 { PRAGMA journal_mode = wal } {wal}
|
||||
|
||||
do_execsql_sync_test 1.17.1 { INSERT INTO t1 VALUES(30, 31) } 2
|
||||
do_execsql_sync_test 1.17.2 { INSERT INTO t1 VALUES(32, 33) } 0
|
||||
do_execsql_test 1.17.3 { PRAGMA main.synchronous } 1
|
||||
|
||||
# Now set synchronous=off, then switch back to delete mode. Check
|
||||
# that the db handle is still using synchronous=off.
|
||||
do_execsql_test 1.18.3 { PRAGMA main.synchronous=off }
|
||||
do_execsql_test 1.18 { PRAGMA journal_mode = delete } {delete}
|
||||
|
||||
do_execsql_sync_test 1.19.1 { INSERT INTO t1 VALUES(34, 35) } 0
|
||||
do_execsql_sync_test 1.19.2 { INSERT INTO t1 VALUES(36, 37) } 0
|
||||
do_execsql_test 1.19.3 { PRAGMA main.synchronous } 0
|
||||
|
||||
# Close and reopen the db. Back to synchronous=normal.
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
do_execsql_sync_test 1.20.1 { INSERT INTO t1 VALUES(38, 39) } 4
|
||||
do_execsql_sync_test 1.20.2 { INSERT INTO t1 VALUES(40, 41) } 4
|
||||
do_execsql_test 1.20.3 { PRAGMA main.synchronous } 2
|
||||
}
|
||||
|
||||
finish_test
|
||||
@@ -0,0 +1,65 @@
|
||||
# 2017-03-24
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix triggerG
|
||||
ifcapable {!trigger} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# Test cases for ticket
|
||||
# https://www.sqlite.org/src/tktview/06796225f59c057cd120f
|
||||
#
|
||||
# The OP_Once opcode was not working correctly for recursive triggers.
|
||||
#
|
||||
do_execsql_test 100 {
|
||||
PRAGMA recursive_triggers = 1;
|
||||
|
||||
CREATE TABLE t1(a);
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
INSERT INTO t1(a) VALUES(0),(2),(3),(8),(9);
|
||||
CREATE TABLE t2(b);
|
||||
CREATE TABLE t3(c);
|
||||
|
||||
CREATE TRIGGER tr AFTER INSERT ON t3 BEGIN
|
||||
INSERT INTO t3 SELECT new.c+1 WHERE new.c<5;
|
||||
INSERT INTO t2 SELECT new.c*100+a FROM t1 WHERE a IN (1, 2, 3, 4);
|
||||
END;
|
||||
|
||||
INSERT INTO t3 VALUES(2);
|
||||
SELECT c FROM t3 ORDER BY c;;
|
||||
} {2 3 4 5}
|
||||
do_execsql_test 110 {
|
||||
SELECT b FROM t2 ORDER BY b;
|
||||
} {202 203 302 303 402 403 502 503}
|
||||
|
||||
do_execsql_test 200 {
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1(a) VALUES(0),(2),(3),(8),(9);
|
||||
DELETE FROM t2;
|
||||
DELETE FROM t3;
|
||||
DROP TRIGGER tr;
|
||||
CREATE TRIGGER tr AFTER INSERT ON t3 BEGIN
|
||||
INSERT INTO t3 SELECT new.c+1 WHERE new.c<5;
|
||||
INSERT INTO t2 SELECT new.c*10000+xx.a*100+yy.a
|
||||
FROM t1 AS xx, t1 AS yy
|
||||
WHERE xx.a IN (1,2,3,4)
|
||||
AND yy.a IN (2,3,4,5);
|
||||
END;
|
||||
|
||||
INSERT INTO t3 VALUES(2);
|
||||
SELECT b FROM t2 ORDER BY b;
|
||||
} {20202 20203 20302 20303 30202 30203 30302 30303 40202 40203 40302 40303 50202 50203 50302 50303}
|
||||
|
||||
finish_test
|
||||
+1
-1
@@ -535,7 +535,7 @@ static void decodeCell(
|
||||
j = i;
|
||||
nCol = 0;
|
||||
k = nHdr;
|
||||
while( x+j<end && j<nHdr ){
|
||||
while( x+j<=end && j<nHdr ){
|
||||
const char *zTypeName;
|
||||
int sz = 0;
|
||||
char zNm[30];
|
||||
|
||||
Reference in New Issue
Block a user