Merge all changes from the 3.18.0 release.

FossilOrigin-Name: ed28f15e052b34f6642c68711fa3ed765c396262327fd3dd9c520b346a4deb81
This commit is contained in:
drh
2017-03-30 20:26:06 +00:00
54 changed files with 1779 additions and 229 deletions
+6 -1
View File
@@ -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
View File
@@ -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
+56 -14
View File
@@ -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
+1
View File
@@ -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
+2 -2
View File
@@ -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
])
+8
View File
@@ -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.
-2
View File
@@ -1,2 +0,0 @@
Version loadable extensions to SQLite are found in subfolders
of this folder.
+6 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+4 -1
View File
@@ -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;
}
+16
View File
@@ -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
+1 -1
View File
@@ -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;
+40
View File
@@ -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** &mdash; 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** &mdash; 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** &mdash; 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** &mdash; 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** &mdash; 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** &mdash; 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.
+717
View File
@@ -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
View File
@@ -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 },
+4
View File
@@ -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
View File
@@ -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
}
+4
View File
@@ -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
+56 -50
View File
@@ -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
View File
@@ -1 +1 @@
3d04b2cd7a68cf58ae739a5c6813562130e5c50c800c208c82769f76037f8f66
ed28f15e052b34f6642c68711fa3ed765c396262327fd3dd9c520b346a4deb81
+1 -1
View File
@@ -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
View File
@@ -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
+6
View File
@@ -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
View File
@@ -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{
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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}
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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
/*
+2
View File
@@ -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 );
+3
View File
@@ -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
View File
@@ -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);
}
}
+1
View File
@@ -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 */
};
+1
View File
@@ -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 */
+6
View File
@@ -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));
+1 -1
View File
@@ -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
View File
@@ -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
+14
View File
@@ -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
View File
@@ -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;
+130
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+33
View File
@@ -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
View File
@@ -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 {
+20
View File
@@ -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
View File
@@ -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
+65
View File
@@ -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
View File
@@ -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];