Compare commits
171 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b04275121c | |||
| ec2da85412 | |||
| db718d8a3b | |||
| 4d06798e56 | |||
| 9c2552f2e8 | |||
| 705a48758a | |||
| a820c05aa0 | |||
| d0879bad42 | |||
| 729677720d | |||
| abfe034692 | |||
| b68b97789e | |||
| 693e671936 | |||
| 53bed45ecb | |||
| 6ef5e12e1f | |||
| 05d3dc29c5 | |||
| dc3bb0deb2 | |||
| 9e2c7ae1b0 | |||
| 3c2aeae16e | |||
| b090352b5a | |||
| afcf9bd806 | |||
| cfe24586a8 | |||
| edf83d1e3d | |||
| 953dfa4e60 | |||
| aa9ce7078a | |||
| a8a0617e06 | |||
| fe1c6bb9c2 | |||
| 781def29c7 | |||
| 41028151be | |||
| 340309fd69 | |||
| e73f059093 | |||
| 8561c81ed6 | |||
| a4ff825095 | |||
| 7df42aba12 | |||
| c25e2ebc01 | |||
| 7f3068aa83 | |||
| 717c09c4a9 | |||
| 1fe3c4b526 | |||
| 75303a2c68 | |||
| ebbf08a012 | |||
| 7c82932723 | |||
| c59731c4ae | |||
| 98f45e53a7 | |||
| a026b98500 | |||
| 6785bcca58 | |||
| 718569443d | |||
| b290f11775 | |||
| 2d4dc5fc60 | |||
| 65a2aaa633 | |||
| 727a99f1e3 | |||
| f2655fe8b6 | |||
| eae73fbfb9 | |||
| 6ade453cd8 | |||
| 8290c2ad5a | |||
| 7b19f25247 | |||
| 93c36bb399 | |||
| eede6a538d | |||
| c49832c208 | |||
| 60c1a2f0b5 | |||
| 62ba4e418d | |||
| f43fe6e9f6 | |||
| 60e7068d75 | |||
| a379b32f33 | |||
| bfe31e7f80 | |||
| f9db522fee | |||
| 8ce7184bc2 | |||
| 7a429658d7 | |||
| 866b53eb5a | |||
| c3d6ba49c6 | |||
| 859bc542c6 | |||
| a9f5c13d0c | |||
| 4e9119d9e8 | |||
| 7d562dbe02 | |||
| 8b4718636c | |||
| 03e1b1f5ff | |||
| f59b12fbc1 | |||
| ecaa9d399c | |||
| 61f92cd045 | |||
| 898799fa00 | |||
| 144ffe7bfb | |||
| 75593d96be | |||
| c740752470 | |||
| 9871c59a2d | |||
| 1bcbc621df | |||
| b66e21fda5 | |||
| 2e08486a08 | |||
| 1c2c0b776f | |||
| 61019c7883 | |||
| 54e2adb5f3 | |||
| 8c7d4ddd5a | |||
| 69014393f8 | |||
| 42899543f8 | |||
| 5426d80948 | |||
| 759e858811 | |||
| 762c1c4071 | |||
| 991a198511 | |||
| b00d862139 | |||
| fe98081e18 | |||
| 3312348cf8 | |||
| 73d5b8f550 | |||
| 58c960816f | |||
| eaf4f523a5 | |||
| 6c1de308f2 | |||
| 25555506df | |||
| 685e3c481c | |||
| c73d0d9dec | |||
| 849a9d92ba | |||
| ae28d6efc6 | |||
| a47941fe42 | |||
| d42ef839bc | |||
| 4eded604ea | |||
| aed1819875 | |||
| 7e61d18eb4 | |||
| 1001ee8819 | |||
| f6b1a8e1a5 | |||
| a021f121c9 | |||
| edfac3456e | |||
| 46d03fcbfc | |||
| 935c34711b | |||
| 039468ef2d | |||
| 9ac7962ace | |||
| 3a8aec5e13 | |||
| afa5af807c | |||
| fc6ee9df22 | |||
| a5c1416d64 | |||
| 4a8ee3dfe2 | |||
| 5dee6afcac | |||
| 16f9a81125 | |||
| da8a330a03 | |||
| 5d56dd2867 | |||
| 40f22bed06 | |||
| a3cc007df4 | |||
| a5f40593be | |||
| 07c5d0a901 | |||
| a81ad1758c | |||
| 39325bac1b | |||
| 1d8b85bed1 | |||
| a9ab481fca | |||
| 53cd964648 | |||
| 2dc0648a80 | |||
| 024045fe6e | |||
| 3e6c060fac | |||
| b0e7704e9f | |||
| 6f68f1640d | |||
| d22d7b4daa | |||
| a01abc302d | |||
| 038b7bc4ef | |||
| 401387553d | |||
| a2a3028d5f | |||
| 2a8d2261ed | |||
| 999cd08aae | |||
| c65faab2e1 | |||
| a6353a3f64 | |||
| 195134c6c3 | |||
| 7250c547a5 | |||
| 8f518837f9 | |||
| 9bb7c4ff4f | |||
| 29f2bad6f0 | |||
| 7599d4aa44 | |||
| 59bf00cb54 | |||
| 2a24287639 | |||
| 1e98310a14 | |||
| 9dcc7cd527 | |||
| 689156fdbc | |||
| a9c19f935c | |||
| b959a017b6 | |||
| 4e8fe3ff91 | |||
| b8a9bb4fb9 | |||
| 72b8ef6ce3 | |||
| 091a81b91d | |||
| 3fee8a63c8 | |||
| 1b1f30bb5e |
+1
-1
@@ -534,7 +534,7 @@ mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
|
||||
mkdir tsrc
|
||||
cp -f $(SRC) tsrc
|
||||
rm tsrc/sqlite.h.in tsrc/parse.y
|
||||
$(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl <tsrc/vdbe.c >vdbe.new
|
||||
$(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new
|
||||
mv vdbe.new tsrc/vdbe.c
|
||||
touch .target_source
|
||||
|
||||
|
||||
+22
-11
@@ -270,6 +270,17 @@ TCC = $(TCC) -I$(TOP)\ext\rtree
|
||||
RCC = $(RCC) -I$(TOP)\ext\rtree
|
||||
!ENDIF
|
||||
|
||||
# The mksqlite3c.tcl script accepts some options on the command
|
||||
# line. When compiling with debugging enabled, some of these
|
||||
# options are necessary in order to allow debugging symbols to
|
||||
# work correctly with Visual Studio when using the amalgamation.
|
||||
#
|
||||
!IF $(DEBUG)>0
|
||||
MKSQLITE3C_ARGS = --linemacros
|
||||
!ELSE
|
||||
MKSQLITE3C_ARGS =
|
||||
!ENDIF
|
||||
|
||||
# Define -DNDEBUG to compile without debugging (i.e., for production usage)
|
||||
# Omitting the define will cause extra debugging code to be inserted and
|
||||
# includes extra comments when "EXPLAIN stmt" is used.
|
||||
@@ -911,12 +922,12 @@ mptester.exe: $(TOP)\mptest\mptest.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h
|
||||
-mkdir tsrc
|
||||
for %i in ($(SRC)) do copy /Y %i tsrc
|
||||
del /Q tsrc\sqlite.h.in tsrc\parse.y
|
||||
$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl < tsrc\vdbe.c > vdbe.new
|
||||
$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new
|
||||
move vdbe.new tsrc\vdbe.c
|
||||
echo > .target_source
|
||||
|
||||
sqlite3.c: .target_source $(TOP)\tool\mksqlite3c.tcl
|
||||
$(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl
|
||||
$(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl $(MKSQLITE3C_ARGS)
|
||||
copy tsrc\shell.c .
|
||||
copy tsrc\sqlite3ext.h .
|
||||
|
||||
@@ -1334,17 +1345,17 @@ sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
|
||||
$(LTLINK) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
|
||||
|
||||
showdb.exe: $(TOP)\tool\showdb.c sqlite3.c
|
||||
$(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o $@ \
|
||||
$(TOP)\tool\showdb.c sqlite3.c
|
||||
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C)
|
||||
$(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\tool\showdb.c $(SQLITE3C)
|
||||
|
||||
wordcount.exe: $(TOP)\test\wordcount.c sqlite3.c
|
||||
$(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o $@ \
|
||||
$(TOP)\test\wordcount.c sqlite3.c
|
||||
wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C)
|
||||
$(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\test\wordcount.c $(SQLITE3C)
|
||||
|
||||
speedtest1.exe: $(TOP)\test\speedtest1.c sqlite3.c
|
||||
$(LTLINK) -DSQLITE_OMIT_LOAD_EXTENSION -o $@ \
|
||||
$(TOP)\test\speedtest1.c sqlite3.c
|
||||
speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C)
|
||||
$(LTLINK) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
|
||||
$(TOP)\test\speedtest1.c $(SQLITE3C)
|
||||
|
||||
clean:
|
||||
del /Q *.lo *.ilk *.lib *.obj *.pdb sqlite3.exe libsqlite3.lib
|
||||
|
||||
@@ -30,4 +30,5 @@ END {
|
||||
printf "#define TK_%-29s %4d\n", "AGG_COLUMN", ++max
|
||||
printf "#define TK_%-29s %4d\n", "UMINUS", ++max
|
||||
printf "#define TK_%-29s %4d\n", "UPLUS", ++max
|
||||
printf "#define TK_%-29s %4d\n", "REGISTER", ++max
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.62 for sqlite 3.8.2.
|
||||
# Generated by GNU Autoconf 2.62 for sqlite 3.8.3.
|
||||
#
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
@@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.8.2'
|
||||
PACKAGE_STRING='sqlite 3.8.2'
|
||||
PACKAGE_VERSION='3.8.3'
|
||||
PACKAGE_STRING='sqlite 3.8.3'
|
||||
PACKAGE_BUGREPORT=''
|
||||
|
||||
# Factoring default headers for most tests.
|
||||
@@ -1483,7 +1483,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures sqlite 3.8.2 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.8.3 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1548,7 +1548,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.8.2:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.8.3:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1664,7 +1664,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.8.2
|
||||
sqlite configure 3.8.3
|
||||
generated by GNU Autoconf 2.62
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
@@ -1678,7 +1678,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by sqlite $as_me 3.8.2, which was
|
||||
It was created by sqlite $as_me 3.8.3, which was
|
||||
generated by GNU Autoconf 2.62. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -14021,7 +14021,7 @@ exec 6>&1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by sqlite $as_me 3.8.2, which was
|
||||
This file was extended by sqlite $as_me 3.8.3, which was
|
||||
generated by GNU Autoconf 2.62. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -14074,7 +14074,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
||||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_version="\\
|
||||
sqlite config.status 3.8.2
|
||||
sqlite config.status 3.8.3
|
||||
configured by $0, generated by GNU Autoconf 2.62,
|
||||
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
||||
+27
-1
@@ -1472,6 +1472,19 @@ static int fts3CreateMethod(
|
||||
return fts3InitVtab(1, db, pAux, argc, argv, ppVtab, pzErr);
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the pIdxInfo->estimatedRows variable to nRow. Unless this
|
||||
** extension is currently being used by a version of SQLite too old to
|
||||
** support estimatedRows. In that case this function is a no-op.
|
||||
*/
|
||||
static void fts3SetEstimatedRows(sqlite3_index_info *pIdxInfo, i64 nRow){
|
||||
#if SQLITE_VERSION_NUMBER>=3008002
|
||||
if( sqlite3_libversion_number()>=3008002 ){
|
||||
pIdxInfo->estimatedRows = nRow;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the xBestIndex method for FTS3 tables. There
|
||||
** are three possible strategies, in order of preference:
|
||||
@@ -1499,7 +1512,20 @@ static int fts3BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
|
||||
for(i=0; i<pInfo->nConstraint; i++){
|
||||
int bDocid; /* True if this constraint is on docid */
|
||||
struct sqlite3_index_constraint *pCons = &pInfo->aConstraint[i];
|
||||
if( pCons->usable==0 ) continue;
|
||||
if( pCons->usable==0 ){
|
||||
if( pCons->op==SQLITE_INDEX_CONSTRAINT_MATCH ){
|
||||
/* There exists an unusable MATCH constraint. This means that if
|
||||
** the planner does elect to use the results of this call as part
|
||||
** of the overall query plan the user will see an "unable to use
|
||||
** function MATCH in the requested context" error. To discourage
|
||||
** this, return a very high cost here. */
|
||||
pInfo->idxNum = FTS3_FULLSCAN_SEARCH;
|
||||
pInfo->estimatedCost = 1e50;
|
||||
fts3SetEstimatedRows(pInfo, ((sqlite3_int64)1) << 50);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
bDocid = (pCons->iColumn<0 || pCons->iColumn==p->nColumn+1);
|
||||
|
||||
|
||||
@@ -96,13 +96,13 @@ void sqlite3Fts3HashClear(Fts3Hash *pH){
|
||||
*/
|
||||
static int fts3StrHash(const void *pKey, int nKey){
|
||||
const char *z = (const char *)pKey;
|
||||
int h = 0;
|
||||
unsigned h = 0;
|
||||
if( nKey<=0 ) nKey = (int) strlen(z);
|
||||
while( nKey > 0 ){
|
||||
h = (h<<3) ^ h ^ *z++;
|
||||
nKey--;
|
||||
}
|
||||
return h & 0x7fffffff;
|
||||
return (int)(h & 0x7fffffff);
|
||||
}
|
||||
static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
|
||||
if( n1!=n2 ) return 1;
|
||||
|
||||
+45
-29
@@ -403,12 +403,14 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
|
||||
/* Step 2 */
|
||||
switch( z[1] ){
|
||||
case 'a':
|
||||
stem(&z, "lanoita", "ate", m_gt_0) ||
|
||||
stem(&z, "lanoit", "tion", m_gt_0);
|
||||
if( !stem(&z, "lanoita", "ate", m_gt_0) ){
|
||||
stem(&z, "lanoit", "tion", m_gt_0);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
stem(&z, "icne", "ence", m_gt_0) ||
|
||||
stem(&z, "icna", "ance", m_gt_0);
|
||||
if( !stem(&z, "icne", "ence", m_gt_0) ){
|
||||
stem(&z, "icna", "ance", m_gt_0);
|
||||
}
|
||||
break;
|
||||
case 'e':
|
||||
stem(&z, "rezi", "ize", m_gt_0);
|
||||
@@ -417,43 +419,54 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
|
||||
stem(&z, "igol", "log", m_gt_0);
|
||||
break;
|
||||
case 'l':
|
||||
stem(&z, "ilb", "ble", m_gt_0) ||
|
||||
stem(&z, "illa", "al", m_gt_0) ||
|
||||
stem(&z, "iltne", "ent", m_gt_0) ||
|
||||
stem(&z, "ile", "e", m_gt_0) ||
|
||||
stem(&z, "ilsuo", "ous", m_gt_0);
|
||||
if( !stem(&z, "ilb", "ble", m_gt_0)
|
||||
&& !stem(&z, "illa", "al", m_gt_0)
|
||||
&& !stem(&z, "iltne", "ent", m_gt_0)
|
||||
&& !stem(&z, "ile", "e", m_gt_0)
|
||||
){
|
||||
stem(&z, "ilsuo", "ous", m_gt_0);
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
stem(&z, "noitazi", "ize", m_gt_0) ||
|
||||
stem(&z, "noita", "ate", m_gt_0) ||
|
||||
stem(&z, "rota", "ate", m_gt_0);
|
||||
if( !stem(&z, "noitazi", "ize", m_gt_0)
|
||||
&& !stem(&z, "noita", "ate", m_gt_0)
|
||||
){
|
||||
stem(&z, "rota", "ate", m_gt_0);
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
stem(&z, "msila", "al", m_gt_0) ||
|
||||
stem(&z, "ssenevi", "ive", m_gt_0) ||
|
||||
stem(&z, "ssenluf", "ful", m_gt_0) ||
|
||||
stem(&z, "ssensuo", "ous", m_gt_0);
|
||||
if( !stem(&z, "msila", "al", m_gt_0)
|
||||
&& !stem(&z, "ssenevi", "ive", m_gt_0)
|
||||
&& !stem(&z, "ssenluf", "ful", m_gt_0)
|
||||
){
|
||||
stem(&z, "ssensuo", "ous", m_gt_0);
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
stem(&z, "itila", "al", m_gt_0) ||
|
||||
stem(&z, "itivi", "ive", m_gt_0) ||
|
||||
stem(&z, "itilib", "ble", m_gt_0);
|
||||
if( !stem(&z, "itila", "al", m_gt_0)
|
||||
&& !stem(&z, "itivi", "ive", m_gt_0)
|
||||
){
|
||||
stem(&z, "itilib", "ble", m_gt_0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Step 3 */
|
||||
switch( z[0] ){
|
||||
case 'e':
|
||||
stem(&z, "etaci", "ic", m_gt_0) ||
|
||||
stem(&z, "evita", "", m_gt_0) ||
|
||||
stem(&z, "ezila", "al", m_gt_0);
|
||||
if( !stem(&z, "etaci", "ic", m_gt_0)
|
||||
&& !stem(&z, "evita", "", m_gt_0)
|
||||
){
|
||||
stem(&z, "ezila", "al", m_gt_0);
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
stem(&z, "itici", "ic", m_gt_0);
|
||||
break;
|
||||
case 'l':
|
||||
stem(&z, "laci", "ic", m_gt_0) ||
|
||||
stem(&z, "luf", "", m_gt_0);
|
||||
if( !stem(&z, "laci", "ic", m_gt_0) ){
|
||||
stem(&z, "luf", "", m_gt_0);
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
stem(&z, "ssen", "", m_gt_0);
|
||||
@@ -494,9 +507,11 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
|
||||
z += 3;
|
||||
}
|
||||
}else if( z[2]=='e' ){
|
||||
stem(&z, "tneme", "", m_gt_1) ||
|
||||
stem(&z, "tnem", "", m_gt_1) ||
|
||||
stem(&z, "tne", "", m_gt_1);
|
||||
if( !stem(&z, "tneme", "", m_gt_1)
|
||||
&& !stem(&z, "tnem", "", m_gt_1)
|
||||
){
|
||||
stem(&z, "tne", "", m_gt_1);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -515,8 +530,9 @@ static void porter_stemmer(const char *zIn, int nIn, char *zOut, int *pnOut){
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
stem(&z, "eta", "", m_gt_1) ||
|
||||
stem(&z, "iti", "", m_gt_1);
|
||||
if( !stem(&z, "eta", "", m_gt_1) ){
|
||||
stem(&z, "iti", "", m_gt_1);
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
if( z[0]=='s' && z[2]=='o' && m_gt_1(z+3) ){
|
||||
|
||||
+28
-4
@@ -2051,6 +2051,7 @@ static int spellfix1Close(sqlite3_vtab_cursor *cur){
|
||||
** (D) scope = $scope
|
||||
** (E) distance < $distance
|
||||
** (F) distance <= $distance
|
||||
** (G) rowid = $rowid
|
||||
**
|
||||
** The plan number is a bit mask formed with these bits:
|
||||
**
|
||||
@@ -2060,8 +2061,9 @@ static int spellfix1Close(sqlite3_vtab_cursor *cur){
|
||||
** 0x08 (D) is found
|
||||
** 0x10 (E) is found
|
||||
** 0x20 (F) is found
|
||||
** 0x40 (G) is found
|
||||
**
|
||||
** filter.argv[*] values contains $str, $langid, $top, and $scope,
|
||||
** filter.argv[*] values contains $str, $langid, $top, $scope and $rowid
|
||||
** if specified and in that order.
|
||||
*/
|
||||
static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
@@ -2070,6 +2072,7 @@ static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
int iTopTerm = -1;
|
||||
int iScopeTerm = -1;
|
||||
int iDistTerm = -1;
|
||||
int iRowidTerm = -1;
|
||||
int i;
|
||||
const struct sqlite3_index_constraint *pConstraint;
|
||||
pConstraint = pIdxInfo->aConstraint;
|
||||
@@ -2122,6 +2125,15 @@ static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
iPlan |= pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ? 16 : 32;
|
||||
iDistTerm = i;
|
||||
}
|
||||
|
||||
/* Terms of the form: distance < $dist or distance <= $dist */
|
||||
if( (iPlan & 64)==0
|
||||
&& pConstraint->iColumn<0
|
||||
&& pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
|
||||
){
|
||||
iPlan |= 64;
|
||||
iRowidTerm = i;
|
||||
}
|
||||
}
|
||||
if( iPlan&1 ){
|
||||
int idx = 2;
|
||||
@@ -2149,6 +2161,11 @@ static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
pIdxInfo->aConstraintUsage[iDistTerm].omit = 1;
|
||||
}
|
||||
pIdxInfo->estimatedCost = 1e5;
|
||||
}else if( (iPlan & 64) ){
|
||||
pIdxInfo->idxNum = 64;
|
||||
pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1;
|
||||
pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1;
|
||||
pIdxInfo->estimatedCost = 5;
|
||||
}else{
|
||||
pIdxInfo->idxNum = 0;
|
||||
pIdxInfo->estimatedCost = 1e50;
|
||||
@@ -2465,16 +2482,23 @@ static int spellfix1FilterForFullScan(
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
int rc;
|
||||
int rc = SQLITE_OK;
|
||||
char *zSql;
|
||||
spellfix1_vtab *pVTab = pCur->pVTab;
|
||||
spellfix1ResetCursor(pCur);
|
||||
assert( idxNum==0 || idxNum==64 );
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT word, rank, NULL, langid, id FROM \"%w\".\"%w_vocab\"",
|
||||
pVTab->zDbName, pVTab->zTableName);
|
||||
"SELECT word, rank, NULL, langid, id FROM \"%w\".\"%w_vocab\"%s",
|
||||
pVTab->zDbName, pVTab->zTableName,
|
||||
((idxNum & 64) ? " WHERE rowid=?" : "")
|
||||
);
|
||||
if( zSql==0 ) return SQLITE_NOMEM;
|
||||
rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pFullScan, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc==SQLITE_OK && (idxNum & 64) ){
|
||||
assert( argc==1 );
|
||||
rc = sqlite3_bind_value(pCur->pFullScan, 1, argv[0]);
|
||||
}
|
||||
pCur->nRow = pCur->iRow = 0;
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_step(pCur->pFullScan);
|
||||
|
||||
@@ -389,7 +389,7 @@ mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
|
||||
$(TLIBS) $(THREADLIB)
|
||||
|
||||
sqlite3.o: sqlite3.c
|
||||
$(TCCX) -c sqlite3.c
|
||||
$(TCCX) -I. -c sqlite3.c
|
||||
|
||||
# This target creates a directory named "tsrc" and fills it with
|
||||
# copies of all of the C source code and header files needed to
|
||||
@@ -402,7 +402,7 @@ target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl
|
||||
mkdir tsrc
|
||||
cp -f $(SRC) tsrc
|
||||
rm tsrc/sqlite.h.in tsrc/parse.y
|
||||
tclsh $(TOP)/tool/vdbe-compress.tcl <tsrc/vdbe.c >vdbe.new
|
||||
tclsh $(TOP)/tool/vdbe-compress.tcl $(OPTS) <tsrc/vdbe.c >vdbe.new
|
||||
mv vdbe.new tsrc/vdbe.c
|
||||
touch target_source
|
||||
|
||||
@@ -631,7 +631,7 @@ wordcount$(EXE): $(TOP)/test/wordcount.c sqlite3.c
|
||||
$(TOP)/test/wordcount.c sqlite3.c
|
||||
|
||||
speedtest1$(EXE): $(TOP)/test/speedtest1.c sqlite3.o
|
||||
$(TCC) -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.o $(THREADLIB)
|
||||
$(TCC) -I. -o speedtest1$(EXE) $(TOP)/test/speedtest1.c sqlite3.o $(THREADLIB)
|
||||
|
||||
# This target will fail if the SQLite amalgamation contains any exported
|
||||
# symbols that do not begin with "sqlite3_". It is run as part of the
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
C Version\s3.8.2
|
||||
D 2013-12-06T14:53:30.888
|
||||
C Enhance\sthe\sMSVC\smakefile\sfor\sbetter\sdebugging\ssymbol\ssupport.
|
||||
D 2014-01-30T11:12:52.221
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in e1a9b4258bbde53f5636f4e238c65b7e11459e2b
|
||||
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc bb1f271c8ee9773489c89be00f3f8ad7ed7ae8e0
|
||||
F Makefile.msc 6ff3ff2eef45c7dd309a8626ff7947b20bd387e7
|
||||
F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315
|
||||
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
|
||||
F VERSION 52f7e22bfcec71a462e34194b4ae1671380fde59
|
||||
F VERSION 8ed548d87d0a27fd7d7620476f9e25f9fa742d73
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F addopcodes.awk 87ca612393d0f439550634bd2c156ea9ff6195ae
|
||||
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
@@ -38,7 +38,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 0921066a13130082764ab4ab6456f7b5bebe56de
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure f97b17cd80fa428e5df4e70a36ed5b4ed21100c2 x
|
||||
F configure 1673bc402f8fc95015f72c279adc5a9a668ee237 x
|
||||
F configure.ac 4cf9f60785143fa141b10962ccc885d973792e9a
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
|
||||
@@ -78,15 +78,15 @@ 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 1e667eacb3fe4b4ad6f863920da4286f071f6e07
|
||||
F ext/fts3/fts3.c 3fe91e36a0304ad4b35020f0e22ff37e95873166
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h eb5f8029589f3d8f1dc7fd50c773326a640388b1
|
||||
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
|
||||
F ext/fts3/fts3_expr.c 5165c365cb5a035f5be8bb296f7aa3211d43e4ac
|
||||
F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914
|
||||
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
|
||||
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
|
||||
F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
|
||||
F ext/fts3/fts3_porter.c a465b49fcb8249a755792f87516eff182efa42b3
|
||||
F ext/fts3/fts3_porter.c 7f8b4bf5af7c0f20f73b8e87e14fa9298f52e290
|
||||
F ext/fts3/fts3_snippet.c 51beb5c1498176fd9caccaf1c75b55cb803a985a
|
||||
F ext/fts3/fts3_term.c a521f75132f9a495bdca1bdd45949b3191c52763
|
||||
F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038
|
||||
@@ -114,7 +114,7 @@ F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
|
||||
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
|
||||
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
|
||||
F ext/misc/spellfix.c 76578f2c56ceaa23d22032338d90db79c68490fb
|
||||
F ext/misc/spellfix.c adfc569fafef7a1eb8f21528e5277686b358c3ce
|
||||
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
|
||||
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
|
||||
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
|
||||
@@ -142,7 +142,7 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt f439556c5ce01ced70987e5ee86549a45165d9ff
|
||||
F main.mk 82fd90375561d7b66287ae5a8b09e1e027394019
|
||||
F main.mk 3ae543fa446525c1dec55f58de67f41b78651812
|
||||
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
|
||||
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
|
||||
F mkextw.sh d2a981497b404d6498f5ff3e3b1f3816bdfcb338
|
||||
@@ -161,35 +161,35 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
|
||||
F src/analyze.c 581d5c18ce89c6f45d4dca65914d0de5b4dad41f
|
||||
F src/attach.c 0a17c9364895316ca4f52d06a97a72c0af1ae8b3
|
||||
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
|
||||
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 1809a7caa2504233bdddd12f5018422421789537
|
||||
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
|
||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c fe6c95c57fd14ed4b3329f4b5bb08132fe7c322d
|
||||
F src/btree.c 02e1a4e71d8fc37e9fd5216c15d989d148a77c87
|
||||
F src/btree.h a61ddebc78c66795a2b93181321a116746302cc9
|
||||
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
|
||||
F src/build.c 1965c7b596ca6295b7ca59541ad186c57564b8f7
|
||||
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
|
||||
F src/build.c 7e6c275ab1731510d6f793d0f88373ab3e858e69
|
||||
F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98
|
||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
|
||||
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||
F src/delete.c b36db1f79ee50eaca979660c9dd36437f5410b93
|
||||
F src/expr.c 31a2b65339f6c3795d4cfa5e99798cd72f9fdfdf
|
||||
F src/delete.c d784e2ee2c6e90fbbd9dcf88a2030c9e12a9318d
|
||||
F src/expr.c e3e09af908b968305d4efeda8dc3499a087ee7d2
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5
|
||||
F src/func.c ef30d26ae4d79bbc7300c74e77fd117a0ba30235
|
||||
F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5
|
||||
F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486
|
||||
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
|
||||
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
|
||||
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 3cf8012325857d162f74389420b14be7976a538d
|
||||
F src/insert.c a4450f0c46a9f221622e6551ab0953b03c4f8ee8
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
|
||||
F src/main.c 74bdee8f574588868e67c25cd377df7cba80102e
|
||||
F src/malloc.c 543a8eb5508eaf4cadf55a9b503379eba2088128
|
||||
F src/main.c 07225af6a00be0b7f34ac52e60f99cf5cbb2a475
|
||||
F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
|
||||
F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f
|
||||
@@ -202,47 +202,47 @@ F src/mutex_noop.c 7682796b7d8d39bf1c138248858efcd10c9e1553
|
||||
F src/mutex_unix.c c3a4e00f96ba068a8dbef34084465979aaf369cc
|
||||
F src/mutex_w32.c 6108c88e1cb38d8fbb3534b170793815cbedbf97
|
||||
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
|
||||
F src/os.c b4ad71336fd96f97776f75587cd9e8218288f5be
|
||||
F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace
|
||||
F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f
|
||||
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
|
||||
F src/os_unix.c f076587029285554a3a65d30d0e71d50cd61f41f
|
||||
F src/os_win.c 4323dd0bac4f7a7037fc4cf87fb4692d17f0b108
|
||||
F src/pager.c 2aa4444ffe86e9282d03bc349a4a5e49bd77c0e8
|
||||
F src/pager.h f094af9f6ececfaa8a1e93876905a4f34233fb0c
|
||||
F src/parse.y acee1a9958539e21263362b194594c5255ad2fca
|
||||
F src/os_unix.c f3ed0e406cbf9c820565b2118232d0796346130f
|
||||
F src/os_win.c 1b21af72c5fa6f9e519a5fcab33e80d182b1aedb
|
||||
F src/pager.c efa923693e958696eee69b205a20bfbc402c8480
|
||||
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
|
||||
F src/parse.y bd51bc17cbfe7549adb4ca3747b1c3d384645065
|
||||
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
|
||||
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
|
||||
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
|
||||
F src/pragma.c 5ab7279d132143feb77f773688a24ab05da75fd7
|
||||
F src/prepare.c 359d1a1e9c9bd4488e4dd3a1aaaf2d2ebb9bb768
|
||||
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
|
||||
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
|
||||
F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c
|
||||
F src/pragma.c ed409ce4104cf4d9de6ead40ace70974f124853b
|
||||
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
|
||||
F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
|
||||
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
|
||||
F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6
|
||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||
F src/select.c d41381d80a22d3a83352aeca274cccf264ac277a
|
||||
F src/shell.c 936a72ff784efff3832cce274a96ed0b036e6758
|
||||
F src/sqlite.h.in baf55c31c4e15a4b626acfeaa792f2aaa566657f
|
||||
F src/select.c a421f3fb7f52a3c0b37f5caeabd27799e8a9ae58
|
||||
F src/shell.c 24722d24d4ea8ca93db35e44db7308de786767ca
|
||||
F src/sqlite.h.in eed7f7d66a60daaa7b4a597dcd9bad87aad9611b
|
||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h f3a5d663fe9c6c0b2ee7fc2e20a6204eaea5bc7c
|
||||
F src/sqliteInt.h 22c8f7112f2fa8e778bbd9d331cbebff8c645574
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
F src/tclsqlite.c 651b10698c87bbc3ae5772e2491e3444c5bbf153
|
||||
F src/test1.c 760e0419705f712d80595f47199568cd7e3b57a4
|
||||
F src/tclsqlite.c 21ca0043d7c48cde5dabed5c1116eee1be692f62
|
||||
F src/test1.c 2401eee14a4309a7cfe2aeb2f30ad517a1d9c299
|
||||
F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35
|
||||
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
|
||||
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
|
||||
F src/test5.c a6d1ac55ac054d0b2b8f37b5e655b6c92645a013
|
||||
F src/test6.c 4f958b71334695e65746d357dac77709732b28db
|
||||
F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723
|
||||
F src/test7.c 72b732baa5642f795655ba1126ea032af46ecfd2
|
||||
F src/test8.c c7aab1d9fbbf54fc33d43b73aa24aa55f9eaf534
|
||||
F src/test8.c 54ccd7b1df5062f0ecbf50a8f7b618f8b1f13b20
|
||||
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
|
||||
F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
|
||||
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
|
||||
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
|
||||
F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16
|
||||
F src/test_config.c 10d0e00dd6315879a6d9fac20bd063c7bbbfb8f8
|
||||
F src/test_config.c 0336e0bdbe541b4af89d7e3dd0656e8e6b51e585
|
||||
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
|
||||
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
|
||||
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
|
||||
@@ -272,28 +272,28 @@ F src/test_syscall.c 16dbe79fb320fadb5acd7a0a59f49e52ab2d2091
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb
|
||||
F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9
|
||||
F src/test_vfstrace.c 34b544e80ba7fb77be15395a609c669df2e660a2
|
||||
F src/test_vfstrace.c 3a0ab304682fecbceb689e7d9b904211fde11d78
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/tokenize.c ec4c1a62b890bf1dbcdb966399e140b904c700a4
|
||||
F src/trigger.c d84e1f3669e9a217731a14a9d472b1c7b87c87ba
|
||||
F src/update.c d1c2477dcf14d90999d1935af4efb4806553250b
|
||||
F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7
|
||||
F src/trigger.c 5c1c0b899ac0ce284763dcb8fdbaa38ecf15ef98
|
||||
F src/update.c a7df6fffce6bfedc578fda6136dd33e34a63f8ee
|
||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||
F src/util.c 76ed0519296e3f62e97e57dab1999e34184c8e49
|
||||
F src/util.c 15ac2627f548f5481d0d7e6c4eb67be673027695
|
||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||
F src/vdbe.c 54894fde8dc806d259e015ac7c9680145e725835
|
||||
F src/vdbe.h c06f0813f853566457ce9cfb1a4a4bc39a5da644
|
||||
F src/vdbeInt.h 05fbda0e061dbc4aaa2709a8cccf3515c245b263
|
||||
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
|
||||
F src/vdbeaux.c 09b79d475f5af2b3b5068f639609d88e0ced9d95
|
||||
F src/vdbeblob.c 8cd05a5630e6d5563ad017bf82edaf812b28acde
|
||||
F src/vdbemem.c 20e349d2ca928802fc8f2d42a2cc488fd6981d3f
|
||||
F src/vdbe.c 5fe94e13fa56c50edb75263706b6fbcc860a3980
|
||||
F src/vdbe.h e6c4c610fcabad4fa80ebb1efc6822a9367e2b26
|
||||
F src/vdbeInt.h 42db251e9f863401ff847b90d5fe1614c89a6a56
|
||||
F src/vdbeapi.c ce4e68ea4842cc6081046f533d088dcf01d247ad
|
||||
F src/vdbeaux.c a3327afa8cfcc5bb3d38f2b2a599bac5fb63c6be
|
||||
F src/vdbeblob.c bc40f98f256f0b34116d6a44b114da4a81a15d33
|
||||
F src/vdbemem.c 23cdc14ed43e0aafa57bd72b9bf3d5b1641afa91
|
||||
F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147
|
||||
F src/vdbetrace.c e7ec40e1999ff3c6414424365d5941178966dcbc
|
||||
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
|
||||
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
||||
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
|
||||
F src/where.c e6a4e713abe6f995495ea53dd6a5e48f88b53883
|
||||
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
||||
F src/where.c 67ae3b5e97ecff36c70cb61ccc7d74cf228f1596
|
||||
F src/whereInt.h 96a75c61f1d2b9d4a8e4bb17d89deb0cf7cba358
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@@ -324,10 +324,10 @@ F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
|
||||
F test/atof1.test 08a61df9365c341f334a65f4348897312d8f3db7
|
||||
F test/attach.test 0d112b7713611fdf0340260192749737135fda5f
|
||||
F test/attach2.test 0ec5defa340363de6cd50fd595046465e9aaba2d
|
||||
F test/attach3.test d89ccfe4fe6e2b5e368d480fcdfe4b496c54cf4e
|
||||
F test/attach3.test 359eb65d00102cdfcef6fa4e81dc1648f8f80b27
|
||||
F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
|
||||
F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
|
||||
F test/auth.test 9bea29041871807d9f289ee679d05d3ed103642f
|
||||
F test/auth.test 5bdf154eb28c0e4bbc0473f335858c0d96171768
|
||||
F test/auth2.test c3b415b76c033bedb81292118fb7c01f5f10cbcd
|
||||
F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5
|
||||
F test/autoinc.test c58912526998a39e11f66b533e23cfabea7f25b7
|
||||
@@ -364,17 +364,17 @@ F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
|
||||
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
|
||||
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
|
||||
F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738
|
||||
F test/capi3.test 56ab450125ead38846cbae7e5b6a216686c3cffa
|
||||
F test/capi3.test 6cdd49656bd62a296924f4d2fcfd05cd2a298369
|
||||
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
|
||||
F test/capi3c.test 93d24621c9ff84da9da060f30431e0453db1cdb0
|
||||
F test/capi3c.test a21869e4d50d5dbb7e566e328fc0bc7c2efa6a32
|
||||
F test/capi3d.test 6d0fc0a86d73f42dd19a7d8b7761ab9bc02277d0
|
||||
F test/capi3e.test ad90088b18b0367125ff2d4b5400153fd2f99aab
|
||||
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
|
||||
F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763
|
||||
F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815
|
||||
F test/closure01.test dbb28f1ea9eeaf0a53ec5bc0fed352e479def8c7
|
||||
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
|
||||
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
|
||||
F test/collate1.test b709989e6e6ff6e1d2bd64231c2c1d8146846c9e
|
||||
F test/collate1.test 73b91005f264b7c403e2d63a6708d150679ac99a
|
||||
F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621
|
||||
F test/collate3.test 79558a286362cb9ed603c6fa543f1cda7f563f0f
|
||||
F test/collate4.test f04d5168685f2eef637ecfa2d4ddf8ec0d600177
|
||||
@@ -406,6 +406,7 @@ F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
|
||||
F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
|
||||
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
|
||||
F test/corruptG.test c150f156dace653c00a121ad0f5772a0568c41ba
|
||||
F test/corruptH.test 9d8186f6f8751efdfd445d8546fd98f073499039
|
||||
F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5
|
||||
F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62
|
||||
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
|
||||
@@ -438,13 +439,13 @@ F test/e_delete.test d5186e2f5478b659f16a2c8b66c09892823e542a
|
||||
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
|
||||
F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306
|
||||
F test/e_expr.test 5c71d183fbf519a4769fd2e2124afdc70b5b1f42
|
||||
F test/e_fkey.test d83a04478bb9c02d2c513518548a69f818869f41
|
||||
F test/e_fkey.test 630597377549af579d34faaf64c6959a5a68ef76
|
||||
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
|
||||
F test/e_insert.test 1e44f84d2abe44d66e4fbf198be4b20e3cc724a0
|
||||
F test/e_reindex.test 396b7b4f0a66863b4e95116a67d93b227193e589
|
||||
F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
|
||||
F test/e_select.test d3226cb94fae4af3f198e68e71f655e106d0be47
|
||||
F test/e_select2.test 22c660a7becf0712c95e1ca1b2d9e716a1261460
|
||||
F test/e_select.test 51c062a9bda16e0ae1bbeed50806bedbd040b282
|
||||
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
|
||||
F test/e_update.test 312cb8f5ccfe41515a6bb092f8ea562a9bd54d52
|
||||
F test/e_uri.test a2c92d80093a7efdcfbb11093651cbea87097b6b
|
||||
F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
|
||||
@@ -456,7 +457,7 @@ F test/eqp.test 57c6c604c2807fb5531731c5323133453c24afac
|
||||
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
|
||||
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
|
||||
F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
|
||||
F test/exclusive2.test 881193eccec225cfed9d7f744b65e57f26adee25
|
||||
F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308
|
||||
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
||||
F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
|
||||
F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d
|
||||
@@ -509,13 +510,13 @@ F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e
|
||||
F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a
|
||||
F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
|
||||
F test/fts3_common.tcl 99cf6659b87c0f74f55963c2aea03b3a7d66ceb0
|
||||
F test/fts3aa.test ad272d695095a55c16a5091dbdcce7c5f55da605
|
||||
F test/fts3ab.test 09aeaa162aee6513d9ff336b6932211008b9d1f9
|
||||
F test/fts3aa.test edd20ddbbc5b6015ab340abf2ca278ae11ec387d
|
||||
F test/fts3ab.test 7f6cf260ae80dda064023df8e8e503e9a412b91f
|
||||
F test/fts3ac.test 636ed7486043055d4f126a0e385f2d5a82ebbf63
|
||||
F test/fts3ad.test e40570cb6f74f059129ad48bcef3d7cbc20dda49
|
||||
F test/fts3ae.test ce32a13b34b0260928e4213b4481acf801533bda
|
||||
F test/fts3af.test d394978c534eabf22dd0837e718b913fd66b499c
|
||||
F test/fts3ag.test 0b7d303f61ae5d620c4efb5e825713ea34ff9441
|
||||
F test/fts3ag.test c003672a215124df7fc6000036d896f498b26b53
|
||||
F test/fts3ah.test dc9f66c32c296f1bc8bcc4535126bddfeca62894
|
||||
F test/fts3ai.test 24058fdc6e9e5102c1fd8459591b114b6a85d285
|
||||
F test/fts3aj.test 0ed71e1dd9b03b843a857dc3eb9b15630e0104fc
|
||||
@@ -535,7 +536,7 @@ F test/fts3conf.test ee8500c86dd58ec075e8831a1e216a79989436de
|
||||
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
|
||||
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
|
||||
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
|
||||
F test/fts3d.test bf640d79722b720fa1c81834c48cdaa45d531b1a
|
||||
F test/fts3d.test c8a193513a269ec4c205ca09645e26e0bc71b860
|
||||
F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
|
||||
F test/fts3defer2.test a3b6cbeabaf28c9398652a4d101ea224d9358479
|
||||
F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd
|
||||
@@ -547,9 +548,10 @@ F test/fts3expr3.test 9e91b8edbcb197bf2e92161aa7696446d96dce5f
|
||||
F test/fts3fault.test cb72dccb0a3b9f730f16c5240f3fcb9303eb1660
|
||||
F test/fts3fault2.test 3198eef2804deea7cac8403e771d9cbcb752d887
|
||||
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
|
||||
F test/fts3join.test 53e66a0c21eb568580674a43b21c059acb26f499
|
||||
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
|
||||
F test/fts3matchinfo.test ff423e73faab8fc6d7adeefedf74dd8e2b0b14e0
|
||||
F test/fts3near.test 12895557870b0f9af7cc0be81a0171abb2d12f12
|
||||
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
|
||||
F test/fts3prefix.test b36d4f00b128a51e7b386cc013a874246d9d7dc1
|
||||
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
|
||||
F test/fts3query.test 4fefd43ff24993bc2c9b2778f2bec0cc7629e7ed
|
||||
@@ -557,7 +559,7 @@ F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
|
||||
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
|
||||
F test/fts3snippet.test d524af6bcef4714e059ef559113dbdc924cd33d1
|
||||
F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca
|
||||
F test/fts3tok1.test b10d0a12a0ab5f905cea1200b745de233f37443f
|
||||
F test/fts3tok1.test c551043de056b0b1582a54e878991f57bad074bc
|
||||
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
|
||||
F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e
|
||||
F test/fts4aa.test 0c3152322c7f0b548cc942ad763eaba0da87ccca
|
||||
@@ -571,13 +573,13 @@ F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
||||
F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
|
||||
F test/fts4merge4.test c19c85ca1faa7b6d536832b49c12e1867235f584
|
||||
F test/fts4noti.test aed33ba44808852dcb24bf70fa132e7bf530f057
|
||||
F test/fts4unicode.test e28ba1a14181e709dcdf47455f207adf14c7cfe0
|
||||
F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test 00667bbeac044d007f6f021af1b9f6150f0c7ff8
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
F test/func3.test dbccee9133cfef1473c59ec07b5f0262b9d72f9a
|
||||
F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
|
||||
F test/func5.test 1435dd313c0bae70d6af089c97a2a997fc5d0e53
|
||||
F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4
|
||||
F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74
|
||||
F test/fuzz.test 77fd50afc12847af50fcf1941679d90adebadde6
|
||||
F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
|
||||
@@ -642,10 +644,10 @@ F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
|
||||
F test/jrnlmode.test 9ee3a78f53d52cca737db69293d15dc41c0cbd36
|
||||
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
|
||||
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
|
||||
F test/keyword1.test a2400977a2e4fde43bf33754c2929fda34dbca05
|
||||
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
F test/like.test 935fb4f608e3ea126891496a6e99b9468372bf5c
|
||||
F test/like.test e191e536d0fcd722a6b965e7cd1ee0bfd12a5991
|
||||
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
|
||||
F test/limit.test cc0ab63385239b63c72452b0e93700bf5e8f0b99
|
||||
F test/loadext.test 92e6dfefd1229c3ef4aaabd87419efd8fa57a7a5
|
||||
@@ -692,18 +694,18 @@ F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd
|
||||
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
|
||||
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
|
||||
F test/minmax4.test 536a3360470633a177e42fbc19660d146b51daef
|
||||
F test/misc1.test 9bed1bd334065a57dc841cff969d4fc1eeb6d49b
|
||||
F test/misc1.test 441a0fafc7087f841db09fbfca54e7aea9f5a84c
|
||||
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
|
||||
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
|
||||
F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
|
||||
F test/misc5.test 528468b26d03303b1f047146e5eefc941b9069f5
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test 1265eb98c2e22a446a13fdef754118b272716684
|
||||
F test/misuse.test ba4fb5d1a6101d1c171ea38b3c613d0661c83054
|
||||
F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2
|
||||
F test/misuse.test 3c34719944ba045cc6c188a4852ba04680728912
|
||||
F test/mmap1.test 93d167b328255cbe6679fe1e1a23be1b1197d07b
|
||||
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
|
||||
F test/mmap3.test c92273e16eb8d23c1d55c9815b446bb72ef0512e
|
||||
F test/mmapfault.test 97507ee06172df99057dbf1c40294eabd82cbb13
|
||||
F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
|
||||
F test/multiplex.test e08cc7177bd6d85990ee1d71100bb6c684c02256
|
||||
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
|
||||
F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101
|
||||
@@ -726,7 +728,8 @@ F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
|
||||
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
|
||||
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
|
||||
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
|
||||
F test/pagerfault.test 7285379906ab2f1108b8e82bbdf2d386cc8ff3ff
|
||||
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
|
||||
F test/pagerfault.test ae9ee0db5a30aecda9db8290ce3dd12e5f7bbaa1
|
||||
F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
|
||||
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
|
||||
F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6
|
||||
@@ -738,6 +741,7 @@ F test/permutations.test af3278cbea3a19e025d5169be8193ff48dc3f862
|
||||
F test/pragma.test e882183ecd21d064cec5c7aaea174fbd36293429
|
||||
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
|
||||
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
|
||||
F test/printf2.test bed79b4c3e5da08ba88ad637c0bf62586843cfb1
|
||||
F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
|
||||
@@ -771,7 +775,7 @@ F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
|
||||
F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38
|
||||
F test/schema4.test e6a66e20cc69f0e306667c08be7fda3d11707dc5
|
||||
F test/schema5.test 29699b4421f183c8f0e88bd28ce7d75d13ea653e
|
||||
F test/securedel.test 87a2561151af1f1e349071a89fdd77059f50113c
|
||||
F test/securedel.test 21749c32ccc30f1ea9e4b9f33295a6521ec20fa0
|
||||
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
|
||||
F test/select1.test fc2a61f226a649393664ad54bc5376631801517c
|
||||
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
|
||||
@@ -779,7 +783,7 @@ F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
|
||||
F test/select4.test 00179be44e531fe04c1c3f15df216439dff2519d
|
||||
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
|
||||
F test/select6.test e76bd10a56988f15726c097a5d5a7966fe82d3b2
|
||||
F test/select7.test dad6f00f0d49728a879d6eb6451d4752db0b0abe
|
||||
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
|
||||
F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
|
||||
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
|
||||
F test/selectA.test 99cf21df033b93033ea4f34aba14a500f48f04fe
|
||||
@@ -800,14 +804,14 @@ F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
|
||||
F test/shared_err.test 0079c05c97d88cfa03989b7c20a8b266983087aa
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test e7c0b9ebda25d5e78f0a3ea0dc4e31bb6d8098c0
|
||||
F test/shell2.test e1d3790f064e50b2f973502f45750012667486df
|
||||
F test/shell2.test c57da3a381c099b02c813ba156298d5c2f5c93a3
|
||||
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
|
||||
F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9
|
||||
F test/shell5.test 46c8c18d62732415c4fe084816c13d559831705e
|
||||
F test/shell5.test cee83b4385f842fec1f2a0bec9ea811f35386edf
|
||||
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
|
||||
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
|
||||
F test/skipscan1.test 6bb4891c2cc5efd5690a9da9e7508e53d4a68e10
|
||||
F test/skipscan1.test 8c777ffd9dad6ee6d2568160cb2158f0b5cd9dd2
|
||||
F test/skipscan2.test 5a4db0799c338ddbacb154aaa5589c0254b36a8d
|
||||
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
|
||||
F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
|
||||
@@ -820,10 +824,10 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/speedtest1.c 4f1e34b6af9af0b59ca11b57d62c3cd851990fba
|
||||
F test/spellfix.test 8c40b169b104086d8795781f670ba3c786d6d8be
|
||||
F test/speedtest1.c 7130d2cb6db45baa553a4ab2f715116c71c2d9f4
|
||||
F test/spellfix.test 61309f5efbec53603b3f86457d34a504f80abafe
|
||||
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
|
||||
F test/stat.test c8eccfe8fcd3f3cfc864ce22d5b9e803a3c69940
|
||||
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
|
||||
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
|
||||
F test/subquery.test 666fdecceac258f5fd84bed09a64e49d9f37edd9
|
||||
F test/subquery2.test 91e1e364072aeff431d1f9689b15147e421d88c7
|
||||
@@ -840,7 +844,7 @@ F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
|
||||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
|
||||
F test/tester.tcl 2a7cce4abf404557c09323a84a2444b189835d0f
|
||||
F test/tester.tcl 9bd04481b8b0ef1f2049ad01f28e175ee9a14f7b
|
||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -880,7 +884,7 @@ F test/tkt-80e031a00f.test 9a154173461a4dbe2de49cda73963e04842d52f7
|
||||
F test/tkt-8454a207b9.test c583a9f814a82a2b5ba95207f55001c9f0cd816c
|
||||
F test/tkt-868145d012.test a5f941107ece6a64410ca4755c6329b7eb57a356
|
||||
F test/tkt-91e2e8ba6f.test 08c4f94ae07696b05c9b822da0b4e5337a2f54c5
|
||||
F test/tkt-94c04eaadb.test fa9c71192f7e2ea2d51bf078bc34e8da6088bf71
|
||||
F test/tkt-94c04eaadb.test f738c57c7f68ab8be1c054415af7774617cb6223
|
||||
F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67
|
||||
F test/tkt-9f2eb3abac.test 85bc63e749f050e6a61c8f9207f1eee65c9d3395
|
||||
F test/tkt-a7b7803e.test 159ef554234fa1f9fb318c751b284bd1cf858da4
|
||||
@@ -1023,7 +1027,7 @@ F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
|
||||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
F test/view.test 4057630287bfa5955628fe90a13d4c225d1c7352
|
||||
F test/vtab1.test 45ddde57764659c0ec90874bcb6c4831f1004c06
|
||||
F test/vtab1.test b631d147b198cfd7903ab5fed028eb2a3d321dc6
|
||||
F test/vtab2.test 7bcffc050da5c68f4f312e49e443063e2d391c0d
|
||||
F test/vtab3.test baad99fd27217f5d6db10660522e0b7192446de1
|
||||
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
|
||||
@@ -1040,9 +1044,9 @@ F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61
|
||||
F test/vtabF.test fd5ad376f5a34fe0891df1f3cddb4fe7c3eb077e
|
||||
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
|
||||
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
|
||||
F test/vtab_shared.test 82f463886e18d7f8395a4b6167c91815efe54839
|
||||
F test/wal.test a59d00eaa0901e42b8a2ef21f2a4c972ee1f1bd4
|
||||
F test/wal2.test d4b470f13c87f6d8268b004380afa04c3c67cb90
|
||||
F test/vtab_shared.test 6acafaae7126c9f49be72c2f57eb8bef3024f1cb
|
||||
F test/wal.test 40073e54359d43354925b2b700b7eebd5e207285
|
||||
F test/wal2.test a8e3963abf6b232cf0b852b09b53665ef34007af
|
||||
F test/wal3.test b22eb662bcbc148c5f6d956eaf94b047f7afe9c0
|
||||
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
|
||||
F test/wal5.test 8f888b50f66b78821e61ed0e233ded5de378224b
|
||||
@@ -1057,7 +1061,7 @@ F test/walcksum.test 9afeb96240296c08c72fc524d199c912cfe34daa
|
||||
F test/walcrash.test 451d79e528add5c42764cea74aa2750754171b25
|
||||
F test/walcrash2.test a0edab4e5390f03b99a790de89aad15d6ec70b36
|
||||
F test/walcrash3.test e426aa58122d20f2b9fbe9a507f9eb8cab85b8af
|
||||
F test/walfault.test 54ad6e849c727f4da463964b9eb8c8e8e155cf82
|
||||
F test/walfault.test 1f8389f7709877e9b4cc679033d71d6fe529056b
|
||||
F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
|
||||
F test/walmode.test 4022fe03ae6e830583672caa101f046438a0473c
|
||||
F test/walnoshm.test 84ca10c544632a756467336b7c3b864d493ee496
|
||||
@@ -1087,7 +1091,10 @@ F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
|
||||
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
||||
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
||||
F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
|
||||
F test/win32longpath.test e2aafc07e6990fe86c69be22a3d1a0e210cd329b
|
||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||
F test/with1.test ce15d69d34a2576b0e47d78c244d1ba2a31679d1
|
||||
F test/with2.test 2fe78fcd8deef2a0f9cfc49bfc755911d0b3fd64
|
||||
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
|
||||
F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8
|
||||
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
|
||||
F test/without_rowid3.test eac3d5c8a1924725b58503a368f2cbd24fd6c8a0
|
||||
@@ -1106,11 +1113,11 @@ F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
|
||||
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
|
||||
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/lemon.c 796930d5fc2036c7636f3f1ee12f9ae03719a2eb
|
||||
F tool/lemon.c 07aba6270d5a5016ba8107b09e431eea4ecdc123
|
||||
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
|
||||
F tool/logest.c 7ad625cac3d54012b27d468b7af6612f78b9ba75
|
||||
F tool/mkautoconfamal.sh f8d8dbf7d62f409ebed5134998bf5b51d7266383
|
||||
F tool/mkkeywordhash.c 189d76644e373c7d0864c628deb8ce7b4f403591
|
||||
F tool/mkkeywordhash.c c9e05e4a7bcab8fab9f583d5b321fb72f565ad97
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl 78a77b2c554d534c6f2dc903130186ed15715460
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
@@ -1120,12 +1127,12 @@ F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12
|
||||
F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795
|
||||
F tool/mkvsix.tcl 6477fb9dab838b7eea1eed50658ff1cda04850b5
|
||||
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
|
||||
F tool/omittest.tcl 4665982e95a6e5c1bd806cf7bc3dea95be422d77
|
||||
F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97
|
||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
|
||||
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
F tool/showdb.c 525ecc443578647703051308ad50a93de6ba2c4b
|
||||
F tool/showdb.c 1f3fe634d6f690b8d39ab1b9fd34583d468921e1
|
||||
F tool/showjournal.c b62cecaab86a4053d944c276bb5232e4d17ece02
|
||||
F tool/showwal.c 3f7f7da5ec0cba51b1449a75f700493377da57b5
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
@@ -1141,14 +1148,14 @@ F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
||||
F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
|
||||
F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
|
||||
F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
||||
F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||
P c632567063d81c4be404ce58cbac0eff7412f565
|
||||
R 39f74301df16683d1c19ab7ca83b6451
|
||||
T +bgcolor * #d0c0ff
|
||||
T +sym-release *
|
||||
T +sym-version-3.8.2 *
|
||||
U dan
|
||||
Z bddf39b758268961698f9899546a37dd
|
||||
P 5bb29b82109224a2ad02920658fabd8fb0f27b3f
|
||||
R e0401798681e1755ee5c5e2fa367c3e2
|
||||
T *branch * msvcDebug
|
||||
T *sym-msvcDebug *
|
||||
T -sym-trunk *
|
||||
U mistachkin
|
||||
Z 7b0fb43b6887cb799be56b64c1e1c153
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
27392118af4c38c5203a04b8013e1afdb1cebd0d
|
||||
c723ec2784d6b60c9781a435c84800b2bc7818d5
|
||||
@@ -38,10 +38,6 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
|
||||
if( pExpr ){
|
||||
if( pExpr->op!=TK_ID ){
|
||||
rc = sqlite3ResolveExprNames(pName, pExpr);
|
||||
if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){
|
||||
sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->u.zToken);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
}else{
|
||||
pExpr->op = TK_STRING;
|
||||
}
|
||||
|
||||
+4
-4
@@ -526,7 +526,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
|
||||
|
||||
/* Sync the database file to disk. */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3PagerSync(pDestPager);
|
||||
rc = sqlite3PagerSync(pDestPager, 0);
|
||||
}
|
||||
}else{
|
||||
sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
|
||||
@@ -601,10 +601,10 @@ int sqlite3_backup_finish(sqlite3_backup *p){
|
||||
|
||||
/* Set the error code of the destination database handle. */
|
||||
rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
|
||||
sqlite3Error(p->pDestDb, rc, 0);
|
||||
|
||||
/* Exit the mutexes and free the backup context structure. */
|
||||
if( p->pDestDb ){
|
||||
sqlite3Error(p->pDestDb, rc, 0);
|
||||
|
||||
/* Exit the mutexes and free the backup context structure. */
|
||||
sqlite3LeaveMutexAndCloseZombie(p->pDestDb);
|
||||
}
|
||||
sqlite3BtreeLeave(p->pSrc);
|
||||
|
||||
+47
-99
@@ -1652,7 +1652,7 @@ static int getAndInitPage(
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
rc = btreeGetPage(pBt, pgno, ppPage, bReadonly);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){
|
||||
rc = btreeInitPage(*ppPage);
|
||||
if( rc!=SQLITE_OK ){
|
||||
releasePage(*ppPage);
|
||||
@@ -1673,10 +1673,11 @@ static void releasePage(MemPage *pPage){
|
||||
if( pPage ){
|
||||
assert( pPage->aData );
|
||||
assert( pPage->pBt );
|
||||
assert( pPage->pDbPage!=0 );
|
||||
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
|
||||
assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData );
|
||||
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||
sqlite3PagerUnref(pPage->pDbPage);
|
||||
sqlite3PagerUnrefNotNull(pPage->pDbPage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3753,7 +3754,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
|
||||
int iPage = pCur->iPage;
|
||||
memset(&info, 0, sizeof(info));
|
||||
btreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info);
|
||||
assert( memcmp(&info, &pCur->info, sizeof(info))==0 );
|
||||
assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 );
|
||||
}
|
||||
#else
|
||||
#define assertCellInfo(x)
|
||||
@@ -4192,10 +4193,10 @@ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
|
||||
/*
|
||||
** Return a pointer to payload information from the entry that the
|
||||
** pCur cursor is pointing to. The pointer is to the beginning of
|
||||
** the key if skipKey==0 and it points to the beginning of data if
|
||||
** skipKey==1. The number of bytes of available key/data is written
|
||||
** into *pAmt. If *pAmt==0, then the value returned will not be
|
||||
** a valid pointer.
|
||||
** the key if index btrees (pPage->intKey==0) and is the data for
|
||||
** table btrees (pPage->intKey==1). The number of bytes of available
|
||||
** key/data is written into *pAmt. If *pAmt==0, then the value
|
||||
** returned will not be a valid pointer.
|
||||
**
|
||||
** This routine is an optimization. It is common for the entire key
|
||||
** and data to fit on the local page and for there to be no overflow
|
||||
@@ -4208,41 +4209,21 @@ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
|
||||
** page of the database. The data might change or move the next time
|
||||
** any btree routine is called.
|
||||
*/
|
||||
static const unsigned char *fetchPayload(
|
||||
static const void *fetchPayload(
|
||||
BtCursor *pCur, /* Cursor pointing to entry to read from */
|
||||
u32 *pAmt, /* Write the number of available bytes here */
|
||||
int skipKey /* read beginning at data if this is true */
|
||||
u32 *pAmt /* Write the number of available bytes here */
|
||||
){
|
||||
unsigned char *aPayload;
|
||||
MemPage *pPage;
|
||||
u32 nKey;
|
||||
u32 nLocal;
|
||||
|
||||
assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
pPage = pCur->apPage[pCur->iPage];
|
||||
assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
|
||||
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
|
||||
if( pCur->info.nSize==0 ){
|
||||
btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage],
|
||||
&pCur->info);
|
||||
}
|
||||
aPayload = pCur->info.pCell;
|
||||
aPayload += pCur->info.nHeader;
|
||||
if( pPage->intKey ){
|
||||
nKey = 0;
|
||||
}else{
|
||||
nKey = (int)pCur->info.nKey;
|
||||
}
|
||||
if( skipKey ){
|
||||
aPayload += nKey;
|
||||
nLocal = pCur->info.nLocal - nKey;
|
||||
}else{
|
||||
nLocal = pCur->info.nLocal;
|
||||
assert( nLocal<=nKey );
|
||||
}
|
||||
*pAmt = nLocal;
|
||||
return aPayload;
|
||||
*pAmt = pCur->info.nLocal;
|
||||
return (void*)(pCur->info.pCell + pCur->info.nHeader);
|
||||
}
|
||||
|
||||
|
||||
@@ -4261,22 +4242,10 @@ static const unsigned char *fetchPayload(
|
||||
** in the common case where no overflow pages are used.
|
||||
*/
|
||||
const void *sqlite3BtreeKeyFetch(BtCursor *pCur, u32 *pAmt){
|
||||
const void *p = 0;
|
||||
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
if( ALWAYS(pCur->eState==CURSOR_VALID) ){
|
||||
p = (const void*)fetchPayload(pCur, pAmt, 0);
|
||||
}
|
||||
return p;
|
||||
return fetchPayload(pCur, pAmt);
|
||||
}
|
||||
const void *sqlite3BtreeDataFetch(BtCursor *pCur, u32 *pAmt){
|
||||
const void *p = 0;
|
||||
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
if( ALWAYS(pCur->eState==CURSOR_VALID) ){
|
||||
p = (const void*)fetchPayload(pCur, pAmt, 1);
|
||||
}
|
||||
return p;
|
||||
return fetchPayload(pCur, pAmt);
|
||||
}
|
||||
|
||||
|
||||
@@ -4395,8 +4364,6 @@ static void moveToParent(BtCursor *pCur){
|
||||
static int moveToRoot(BtCursor *pCur){
|
||||
MemPage *pRoot;
|
||||
int rc = SQLITE_OK;
|
||||
Btree *p = pCur->pBtree;
|
||||
BtShared *pBt = p->pBt;
|
||||
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
|
||||
@@ -4411,56 +4378,52 @@ static int moveToRoot(BtCursor *pCur){
|
||||
}
|
||||
|
||||
if( pCur->iPage>=0 ){
|
||||
int i;
|
||||
for(i=1; i<=pCur->iPage; i++){
|
||||
releasePage(pCur->apPage[i]);
|
||||
}
|
||||
pCur->iPage = 0;
|
||||
while( pCur->iPage ) releasePage(pCur->apPage[pCur->iPage--]);
|
||||
}else if( pCur->pgnoRoot==0 ){
|
||||
pCur->eState = CURSOR_INVALID;
|
||||
return SQLITE_OK;
|
||||
}else{
|
||||
rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0],
|
||||
rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
|
||||
pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
pCur->eState = CURSOR_INVALID;
|
||||
return rc;
|
||||
}
|
||||
pCur->iPage = 0;
|
||||
|
||||
/* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
|
||||
** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
|
||||
** NULL, the caller expects a table b-tree. If this is not the case,
|
||||
** return an SQLITE_CORRUPT error. */
|
||||
assert( pCur->apPage[0]->intKey==1 || pCur->apPage[0]->intKey==0 );
|
||||
if( (pCur->pKeyInfo==0)!=pCur->apPage[0]->intKey ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assert that the root page is of the correct type. This must be the
|
||||
** case as the call to this function that loaded the root-page (either
|
||||
** this call or a previous invocation) would have detected corruption
|
||||
** if the assumption were not true, and it is not possible for the flags
|
||||
** byte to have been modified while this cursor is holding a reference
|
||||
** to the page. */
|
||||
pRoot = pCur->apPage[0];
|
||||
assert( pRoot->pgno==pCur->pgnoRoot );
|
||||
assert( pRoot->isInit && (pCur->pKeyInfo==0)==pRoot->intKey );
|
||||
|
||||
/* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor
|
||||
** expected to open it on an index b-tree. Otherwise, if pKeyInfo is
|
||||
** NULL, the caller expects a table b-tree. If this is not the case,
|
||||
** return an SQLITE_CORRUPT error.
|
||||
**
|
||||
** Earlier versions of SQLite assumed that this test could not fail
|
||||
** if the root page was already loaded when this function was called (i.e.
|
||||
** if pCur->iPage>=0). But this is not so if the database is corrupted
|
||||
** in such a way that page pRoot is linked into a second b-tree table
|
||||
** (or the freelist). */
|
||||
assert( pRoot->intKey==1 || pRoot->intKey==0 );
|
||||
if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
|
||||
pCur->aiIdx[0] = 0;
|
||||
pCur->info.nSize = 0;
|
||||
pCur->atLast = 0;
|
||||
pCur->validNKey = 0;
|
||||
|
||||
if( pRoot->nCell==0 && !pRoot->leaf ){
|
||||
if( pRoot->nCell>0 ){
|
||||
pCur->eState = CURSOR_VALID;
|
||||
}else if( !pRoot->leaf ){
|
||||
Pgno subpage;
|
||||
if( pRoot->pgno!=1 ) return SQLITE_CORRUPT_BKPT;
|
||||
subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
|
||||
pCur->eState = CURSOR_VALID;
|
||||
rc = moveToChild(pCur, subpage);
|
||||
}else{
|
||||
pCur->eState = ((pRoot->nCell>0)?CURSOR_VALID:CURSOR_INVALID);
|
||||
pCur->eState = CURSOR_INVALID;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -4716,9 +4679,7 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
** 2 bytes of the cell.
|
||||
*/
|
||||
nCell = pCell[0];
|
||||
if( nCell<=pPage->max1bytePayload
|
||||
/* && (pCell+nCell)<pPage->aDataEnd */
|
||||
){
|
||||
if( nCell<=pPage->max1bytePayload ){
|
||||
/* This branch runs if the record-size field of the cell is a
|
||||
** single byte varint and the record fits entirely on the main
|
||||
** b-tree page. */
|
||||
@@ -4726,7 +4687,6 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
c = sqlite3VdbeRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
|
||||
}else if( !(pCell[1] & 0x80)
|
||||
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
|
||||
/* && (pCell+nCell+2)<=pPage->aDataEnd */
|
||||
){
|
||||
/* The record-size field is a 2 byte varint and the record
|
||||
** fits entirely on the main b-tree page. */
|
||||
@@ -5289,6 +5249,7 @@ end_allocate_page:
|
||||
if( rc==SQLITE_OK ){
|
||||
if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){
|
||||
releasePage(*ppPage);
|
||||
*ppPage = 0;
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
(*ppPage)->isInit = 0;
|
||||
@@ -5550,7 +5511,7 @@ static int fillInCell(
|
||||
nHeader += 4;
|
||||
}
|
||||
if( pPage->hasData ){
|
||||
nHeader += putVarint(&pCell[nHeader], nData+nZero);
|
||||
nHeader += putVarint32(&pCell[nHeader], nData+nZero);
|
||||
}else{
|
||||
nData = nZero = 0;
|
||||
}
|
||||
@@ -5678,7 +5639,6 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
|
||||
u32 pc; /* Offset to cell content of cell being deleted */
|
||||
u8 *data; /* pPage->aData */
|
||||
u8 *ptr; /* Used to move bytes around within data[] */
|
||||
u8 *endPtr; /* End of loop */
|
||||
int rc; /* The return code */
|
||||
int hdr; /* Beginning of the header. 0 most pages. 100 page 1 */
|
||||
|
||||
@@ -5703,13 +5663,8 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
|
||||
*pRC = rc;
|
||||
return;
|
||||
}
|
||||
endPtr = &pPage->aCellIdx[2*pPage->nCell - 2];
|
||||
assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */
|
||||
while( ptr<endPtr ){
|
||||
*(u16*)ptr = *(u16*)&ptr[2];
|
||||
ptr += 2;
|
||||
}
|
||||
pPage->nCell--;
|
||||
memmove(ptr, ptr+2, 2*(pPage->nCell - idx));
|
||||
put2byte(&data[hdr+3], pPage->nCell);
|
||||
pPage->nFree += 2;
|
||||
}
|
||||
@@ -5746,9 +5701,6 @@ static void insertCell(
|
||||
int ins; /* Index in data[] where new cell pointer is inserted */
|
||||
int cellOffset; /* Address of first cell pointer in data[] */
|
||||
u8 *data; /* The content of the whole page */
|
||||
u8 *ptr; /* Used for moving information around in data[] */
|
||||
u8 *endPtr; /* End of the loop */
|
||||
|
||||
int nSkip = (iChild ? 4 : 0);
|
||||
|
||||
if( *pRC ) return;
|
||||
@@ -5799,13 +5751,7 @@ static void insertCell(
|
||||
if( iChild ){
|
||||
put4byte(&data[idx], iChild);
|
||||
}
|
||||
ptr = &data[end];
|
||||
endPtr = &data[ins];
|
||||
assert( (SQLITE_PTR_TO_INT(ptr)&1)==0 ); /* ptr is always 2-byte aligned */
|
||||
while( ptr>endPtr ){
|
||||
*(u16*)ptr = *(u16*)&ptr[-2];
|
||||
ptr -= 2;
|
||||
}
|
||||
memmove(&data[ins+2], &data[ins], end-ins);
|
||||
put2byte(&data[ins], idx);
|
||||
put2byte(&data[pPage->hdrOffset+3], pPage->nCell);
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
@@ -7403,6 +7349,7 @@ static int clearDatabasePage(
|
||||
int rc;
|
||||
unsigned char *pCell;
|
||||
int i;
|
||||
int hdr;
|
||||
|
||||
assert( sqlite3_mutex_held(pBt->mutex) );
|
||||
if( pgno>btreePagecount(pBt) ){
|
||||
@@ -7411,6 +7358,7 @@ static int clearDatabasePage(
|
||||
|
||||
rc = getAndInitPage(pBt, pgno, &pPage, 0);
|
||||
if( rc ) return rc;
|
||||
hdr = pPage->hdrOffset;
|
||||
for(i=0; i<pPage->nCell; i++){
|
||||
pCell = findCell(pPage, i);
|
||||
if( !pPage->leaf ){
|
||||
@@ -7421,7 +7369,7 @@ static int clearDatabasePage(
|
||||
if( rc ) goto cleardatabasepage_out;
|
||||
}
|
||||
if( !pPage->leaf ){
|
||||
rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), 1, pnChange);
|
||||
rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange);
|
||||
if( rc ) goto cleardatabasepage_out;
|
||||
}else if( pnChange ){
|
||||
assert( pPage->intKey );
|
||||
@@ -7430,7 +7378,7 @@ static int clearDatabasePage(
|
||||
if( freePageFlag ){
|
||||
freePage(pPage, &rc);
|
||||
}else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
|
||||
zeroPage(pPage, pPage->aData[0] | PTF_LEAF);
|
||||
zeroPage(pPage, pPage->aData[hdr] | PTF_LEAF);
|
||||
}
|
||||
|
||||
cleardatabasepage_out:
|
||||
@@ -7767,7 +7715,7 @@ static void checkAppendMsg(
|
||||
sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1);
|
||||
}
|
||||
if( zMsg1 ){
|
||||
sqlite3StrAccumAppend(&pCheck->errMsg, zMsg1, -1);
|
||||
sqlite3StrAccumAppendAll(&pCheck->errMsg, zMsg1);
|
||||
}
|
||||
sqlite3VXPrintf(&pCheck->errMsg, 1, zFormat, ap);
|
||||
va_end(ap);
|
||||
|
||||
+81
-9
@@ -140,6 +140,7 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
assert( !pParse->isMultiWrite
|
||||
|| sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
|
||||
if( v ){
|
||||
while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){}
|
||||
sqlite3VdbeAddOp0(v, OP_Halt);
|
||||
|
||||
/* The cookie mask contains one bit for each database file open.
|
||||
@@ -1451,10 +1452,10 @@ static void identPut(char *z, int *pIdx, char *zSignedIdent){
|
||||
for(j=0; zIdent[j]; j++){
|
||||
if( !sqlite3Isalnum(zIdent[j]) && zIdent[j]!='_' ) break;
|
||||
}
|
||||
needQuote = sqlite3Isdigit(zIdent[0]) || sqlite3KeywordCode(zIdent, j)!=TK_ID;
|
||||
if( !needQuote ){
|
||||
needQuote = zIdent[j];
|
||||
}
|
||||
needQuote = sqlite3Isdigit(zIdent[0])
|
||||
|| sqlite3KeywordCode(zIdent, j)!=TK_ID
|
||||
|| zIdent[j]!=0
|
||||
|| j==0;
|
||||
|
||||
if( needQuote ) z[i++] = '"';
|
||||
for(j=0; zIdent[j]; j++){
|
||||
@@ -2677,7 +2678,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
|
||||
regRecord = sqlite3GetTempReg(pParse);
|
||||
|
||||
sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 0, &iPartIdxLabel);
|
||||
sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0);
|
||||
sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
|
||||
sqlite3VdbeResolveLabel(v, iPartIdxLabel);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
|
||||
@@ -3989,9 +3990,9 @@ void sqlite3UniqueConstraint(
|
||||
for(j=0; j<pIdx->nKeyCol; j++){
|
||||
char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
|
||||
if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2);
|
||||
sqlite3StrAccumAppend(&errMsg, pTab->zName, -1);
|
||||
sqlite3StrAccumAppendAll(&errMsg, pTab->zName);
|
||||
sqlite3StrAccumAppend(&errMsg, ".", 1);
|
||||
sqlite3StrAccumAppend(&errMsg, zCol, -1);
|
||||
sqlite3StrAccumAppendAll(&errMsg, zCol);
|
||||
}
|
||||
zErr = sqlite3StrAccumFinish(&errMsg);
|
||||
sqlite3HaltConstraint(pParse,
|
||||
@@ -4183,8 +4184,9 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
|
||||
assert( sqlite3KeyInfoIsWriteable(pKey) );
|
||||
for(i=0; i<nCol; i++){
|
||||
char *zColl = pIdx->azColl[i];
|
||||
if( NEVER(zColl==0) ) zColl = "BINARY";
|
||||
pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl);
|
||||
assert( zColl!=0 );
|
||||
pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 :
|
||||
sqlite3LocateCollSeq(pParse, zColl);
|
||||
pKey->aSortOrder[i] = pIdx->aSortOrder[i];
|
||||
}
|
||||
if( pParse->nErr ){
|
||||
@@ -4196,3 +4198,73 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
|
||||
}
|
||||
return sqlite3KeyInfoRef(pIdx->pKeyInfo);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_CTE
|
||||
/*
|
||||
** This routine is invoked once per CTE by the parser while parsing a
|
||||
** WITH clause.
|
||||
*/
|
||||
With *sqlite3WithAdd(
|
||||
Parse *pParse, /* Parsing context */
|
||||
With *pWith, /* Existing WITH clause, or NULL */
|
||||
Token *pName, /* Name of the common-table */
|
||||
ExprList *pArglist, /* Optional column name list for the table */
|
||||
Select *pQuery /* Query used to initialize the table */
|
||||
){
|
||||
sqlite3 *db = pParse->db;
|
||||
With *pNew;
|
||||
char *zName;
|
||||
|
||||
/* Check that the CTE name is unique within this WITH clause. If
|
||||
** not, store an error in the Parse structure. */
|
||||
zName = sqlite3NameFromToken(pParse->db, pName);
|
||||
if( zName && pWith ){
|
||||
int i;
|
||||
for(i=0; i<pWith->nCte; i++){
|
||||
if( sqlite3StrICmp(zName, pWith->a[i].zName)==0 ){
|
||||
sqlite3ErrorMsg(pParse, "duplicate WITH table name: %s", zName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( pWith ){
|
||||
int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
|
||||
pNew = sqlite3DbRealloc(db, pWith, nByte);
|
||||
}else{
|
||||
pNew = sqlite3DbMallocZero(db, sizeof(*pWith));
|
||||
}
|
||||
assert( zName!=0 || pNew==0 );
|
||||
assert( db->mallocFailed==0 || pNew==0 );
|
||||
|
||||
if( pNew==0 ){
|
||||
sqlite3ExprListDelete(db, pArglist);
|
||||
sqlite3SelectDelete(db, pQuery);
|
||||
sqlite3DbFree(db, zName);
|
||||
pNew = pWith;
|
||||
}else{
|
||||
pNew->a[pNew->nCte].pSelect = pQuery;
|
||||
pNew->a[pNew->nCte].pCols = pArglist;
|
||||
pNew->a[pNew->nCte].zName = zName;
|
||||
pNew->a[pNew->nCte].zErr = 0;
|
||||
pNew->nCte++;
|
||||
}
|
||||
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/*
|
||||
** Free the contents of the With object passed as the second argument.
|
||||
*/
|
||||
void sqlite3WithDelete(sqlite3 *db, With *pWith){
|
||||
if( pWith ){
|
||||
int i;
|
||||
for(i=0; i<pWith->nCte; i++){
|
||||
struct Cte *pCte = &pWith->a[i];
|
||||
sqlite3ExprListDelete(db, pCte->pCols);
|
||||
sqlite3SelectDelete(db, pCte->pSelect);
|
||||
sqlite3DbFree(db, pCte->zName);
|
||||
}
|
||||
sqlite3DbFree(db, pWith);
|
||||
}
|
||||
}
|
||||
#endif /* !defined(SQLITE_OMIT_CTE) */
|
||||
|
||||
@@ -357,7 +357,6 @@ FuncDef *sqlite3FindFunction(
|
||||
|
||||
assert( nArg>=(-2) );
|
||||
assert( nArg>=(-1) || createFlag==0 );
|
||||
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
|
||||
h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db->aFunc.a);
|
||||
|
||||
/* First search for a match amongst the application-defined functions.
|
||||
|
||||
+33
-23
@@ -636,7 +636,9 @@ void sqlite3GenerateRowDelete(
|
||||
** used by any BEFORE and AFTER triggers that exist. */
|
||||
sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
|
||||
for(iCol=0; iCol<pTab->nCol; iCol++){
|
||||
if( mask==0xffffffff || mask&(1<<iCol) ){
|
||||
testcase( mask!=0xffffffff && iCol==31 );
|
||||
testcase( mask!=0xffffffff && iCol==32 );
|
||||
if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
|
||||
}
|
||||
}
|
||||
@@ -716,9 +718,10 @@ void sqlite3GenerateRowIndexDelete(
|
||||
int *aRegIdx /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
|
||||
){
|
||||
int i; /* Index loop counter */
|
||||
int r1; /* Register holding an index key */
|
||||
int r1 = -1; /* Register holding an index key */
|
||||
int iPartIdxLabel; /* Jump destination for skipping partial index entries */
|
||||
Index *pIdx; /* Current index */
|
||||
Index *pPrior = 0; /* Prior index */
|
||||
Vdbe *v; /* The prepared statement under construction */
|
||||
Index *pPk; /* PRIMARY KEY index, or NULL for rowid tables */
|
||||
|
||||
@@ -729,10 +732,12 @@ void sqlite3GenerateRowIndexDelete(
|
||||
if( aRegIdx!=0 && aRegIdx[i]==0 ) continue;
|
||||
if( pIdx==pPk ) continue;
|
||||
VdbeModuleComment((v, "GenRowIdxDel for %s", pIdx->zName));
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1, &iPartIdxLabel);
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 1,
|
||||
&iPartIdxLabel, pPrior, r1);
|
||||
sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
|
||||
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
|
||||
sqlite3VdbeResolveLabel(v, iPartIdxLabel);
|
||||
pPrior = pIdx;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -754,6 +759,17 @@ void sqlite3GenerateRowIndexDelete(
|
||||
** to false or null. If pIdx is not a partial index, *piPartIdxLabel
|
||||
** will be set to zero which is an empty label that is ignored by
|
||||
** sqlite3VdbeResolveLabel().
|
||||
**
|
||||
** The pPrior and regPrior parameters are used to implement a cache to
|
||||
** avoid unnecessary register loads. If pPrior is not NULL, then it is
|
||||
** a pointer to a different index for which an index key has just been
|
||||
** computed into register regPrior. If the current pIdx index is generating
|
||||
** its key into the same sequence of registers and if pPrior and pIdx share
|
||||
** a column in common, then the register corresponding to that column already
|
||||
** holds the correct value and the loading of that register is skipped.
|
||||
** This optimization is helpful when doing a DELETE or an INTEGRITY_CHECK
|
||||
** on a table with multiple indices, and especially with the ROWID or
|
||||
** PRIMARY KEY columns of the index.
|
||||
*/
|
||||
int sqlite3GenerateIndexKey(
|
||||
Parse *pParse, /* Parsing context */
|
||||
@@ -761,14 +777,15 @@ int sqlite3GenerateIndexKey(
|
||||
int iDataCur, /* Cursor number from which to take column data */
|
||||
int regOut, /* Put the new key into this register if not 0 */
|
||||
int prefixOnly, /* Compute only a unique prefix of the key */
|
||||
int *piPartIdxLabel /* OUT: Jump to this label to skip partial index */
|
||||
int *piPartIdxLabel, /* OUT: Jump to this label to skip partial index */
|
||||
Index *pPrior, /* Previously generated index key */
|
||||
int regPrior /* Register holding previous generated key */
|
||||
){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int j;
|
||||
Table *pTab = pIdx->pTable;
|
||||
int regBase;
|
||||
int nCol;
|
||||
Index *pPk;
|
||||
|
||||
if( piPartIdxLabel ){
|
||||
if( pIdx->pPartIdxWhere ){
|
||||
@@ -782,28 +799,21 @@ int sqlite3GenerateIndexKey(
|
||||
}
|
||||
nCol = (prefixOnly && pIdx->uniqNotNull) ? pIdx->nKeyCol : pIdx->nColumn;
|
||||
regBase = sqlite3GetTempRange(pParse, nCol);
|
||||
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||
if( pPrior && (regBase!=regPrior || pPrior->pPartIdxWhere) ) pPrior = 0;
|
||||
for(j=0; j<nCol; j++){
|
||||
i16 idx = pIdx->aiColumn[j];
|
||||
if( pPk ) idx = sqlite3ColumnOfIndex(pPk, idx);
|
||||
if( idx<0 || idx==pTab->iPKey ){
|
||||
sqlite3VdbeAddOp2(v, OP_Rowid, iDataCur, regBase+j);
|
||||
}else{
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, idx, regBase+j);
|
||||
sqlite3ColumnDefault(v, pTab, pIdx->aiColumn[j], -1);
|
||||
}
|
||||
if( pPrior && pPrior->aiColumn[j]==pIdx->aiColumn[j] ) continue;
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, pIdx->aiColumn[j],
|
||||
regBase+j);
|
||||
/* If the column affinity is REAL but the number is an integer, then it
|
||||
** might be stored in the table as an integer (using a compact
|
||||
** representation) then converted to REAL by an OP_RealAffinity opcode.
|
||||
** But we are getting ready to store this value back into an index, where
|
||||
** it should be converted by to INTEGER again. So omit the OP_RealAffinity
|
||||
** opcode if it is present */
|
||||
sqlite3VdbeDeletePriorOpcode(v, OP_RealAffinity);
|
||||
}
|
||||
if( regOut ){
|
||||
const char *zAff;
|
||||
if( pTab->pSelect
|
||||
|| OptimizationDisabled(pParse->db, SQLITE_IdxRealAsInt)
|
||||
){
|
||||
zAff = 0;
|
||||
}else{
|
||||
zAff = sqlite3IndexAffinityStr(v, pIdx);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regOut);
|
||||
sqlite3VdbeChangeP4(v, -1, zAff, P4_TRANSIENT);
|
||||
}
|
||||
sqlite3ReleaseTempRange(pParse, regBase, nCol);
|
||||
return regBase;
|
||||
|
||||
+99
-18
@@ -523,16 +523,25 @@ Expr *sqlite3PExpr(
|
||||
}
|
||||
|
||||
/*
|
||||
** Return 1 if an expression must be FALSE in all cases and 0 if the
|
||||
** expression might be true. This is an optimization. If is OK to
|
||||
** return 0 here even if the expression really is always false (a
|
||||
** false negative). But it is a bug to return 1 if the expression
|
||||
** might be true in some rare circumstances (a false positive.)
|
||||
** If the expression is always either TRUE or FALSE (respectively),
|
||||
** then return 1. If one cannot determine the truth value of the
|
||||
** expression at compile-time return 0.
|
||||
**
|
||||
** This is an optimization. If is OK to return 0 here even if
|
||||
** the expression really is always false or false (a false negative).
|
||||
** But it is a bug to return 1 if the expression might have different
|
||||
** boolean values in different circumstances (a false positive.)
|
||||
**
|
||||
** Note that if the expression is part of conditional for a
|
||||
** LEFT JOIN, then we cannot determine at compile-time whether or not
|
||||
** is it true or false, so always return 0.
|
||||
*/
|
||||
static int exprAlwaysTrue(Expr *p){
|
||||
int v = 0;
|
||||
if( ExprHasProperty(p, EP_FromJoin) ) return 0;
|
||||
if( !sqlite3ExprIsInteger(p, &v) ) return 0;
|
||||
return v!=0;
|
||||
}
|
||||
static int exprAlwaysFalse(Expr *p){
|
||||
int v = 0;
|
||||
if( ExprHasProperty(p, EP_FromJoin) ) return 0;
|
||||
@@ -886,6 +895,33 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/*
|
||||
** Create and return a deep copy of the object passed as the second
|
||||
** argument. If an OOM condition is encountered, NULL is returned
|
||||
** and the db->mallocFailed flag set.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_CTE
|
||||
static With *withDup(sqlite3 *db, With *p){
|
||||
With *pRet = 0;
|
||||
if( p ){
|
||||
int nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1);
|
||||
pRet = sqlite3DbMallocZero(db, nByte);
|
||||
if( pRet ){
|
||||
int i;
|
||||
pRet->nCte = p->nCte;
|
||||
for(i=0; i<p->nCte; i++){
|
||||
pRet->a[i].pSelect = sqlite3SelectDup(db, p->a[i].pSelect, 0);
|
||||
pRet->a[i].pCols = sqlite3ExprListDup(db, p->a[i].pCols, 0);
|
||||
pRet->a[i].zName = sqlite3DbStrDup(db, p->a[i].zName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pRet;
|
||||
}
|
||||
#else
|
||||
# define withDup(x,y) 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The following group of routines make deep copies of expressions,
|
||||
** expression lists, ID lists, and select statements. The copies can
|
||||
@@ -966,6 +1002,7 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
|
||||
pNewItem->regReturn = pOldItem->regReturn;
|
||||
pNewItem->isCorrelated = pOldItem->isCorrelated;
|
||||
pNewItem->viaCoroutine = pOldItem->viaCoroutine;
|
||||
pNewItem->isRecursive = pOldItem->isRecursive;
|
||||
pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
|
||||
pNewItem->notIndexed = pOldItem->notIndexed;
|
||||
pNewItem->pIndex = pOldItem->pIndex;
|
||||
@@ -1027,6 +1064,8 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
|
||||
pNew->addrOpenEphm[0] = -1;
|
||||
pNew->addrOpenEphm[1] = -1;
|
||||
pNew->addrOpenEphm[2] = -1;
|
||||
pNew->nSelectRow = p->nSelectRow;
|
||||
pNew->pWith = withDup(db, p->pWith);
|
||||
return pNew;
|
||||
}
|
||||
#else
|
||||
@@ -2170,6 +2209,11 @@ void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
|
||||
*/
|
||||
void sqlite3ExprCachePush(Parse *pParse){
|
||||
pParse->iCacheLevel++;
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
|
||||
printf("PUSH to %d\n", pParse->iCacheLevel);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2183,6 +2227,11 @@ void sqlite3ExprCachePop(Parse *pParse, int N){
|
||||
assert( N>0 );
|
||||
assert( pParse->iCacheLevel>=N );
|
||||
pParse->iCacheLevel -= N;
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
|
||||
printf("POP to %d\n", pParse->iCacheLevel);
|
||||
}
|
||||
#endif
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->iReg && p->iLevel>pParse->iCacheLevel ){
|
||||
cacheEntryClear(pParse, p);
|
||||
@@ -2277,6 +2326,11 @@ void sqlite3ExprCacheClear(Parse *pParse){
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
|
||||
#if SQLITE_DEBUG
|
||||
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
|
||||
printf("CLEAR\n");
|
||||
}
|
||||
#endif
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->iReg ){
|
||||
cacheEntryClear(pParse, p);
|
||||
@@ -2632,7 +2686,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
FuncDef *pDef; /* The function definition object */
|
||||
int nId; /* Length of the function name in bytes */
|
||||
const char *zId; /* The function name */
|
||||
int constMask = 0; /* Mask of function arguments that are constant */
|
||||
u32 constMask = 0; /* Mask of function arguments that are constant */
|
||||
int i; /* Loop counter */
|
||||
u8 enc = ENC(db); /* The text encoding used by this database */
|
||||
CollSeq *pColl = 0; /* A collating sequence */
|
||||
@@ -2683,7 +2737,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
|
||||
for(i=0; i<nFarg; i++){
|
||||
if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
|
||||
constMask |= (1<<i);
|
||||
testcase( i==31 );
|
||||
constMask |= MASKBIT32(i);
|
||||
}
|
||||
if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
|
||||
pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
|
||||
@@ -3413,7 +3468,17 @@ int sqlite3ExprCodeExprList(
|
||||
}else{
|
||||
int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
|
||||
if( inReg!=target+i ){
|
||||
sqlite3VdbeAddOp2(pParse->pVdbe, copyOp, inReg, target+i);
|
||||
VdbeOp *pOp;
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
if( copyOp==OP_Copy
|
||||
&& (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy
|
||||
&& pOp->p1+pOp->p3+1==inReg
|
||||
&& pOp->p2+pOp->p3+1==target+i
|
||||
){
|
||||
pOp->p3++;
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, copyOp, inReg, target+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3504,8 +3569,8 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
case TK_AND: {
|
||||
int d2 = sqlite3VdbeMakeLabel(v);
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprCachePush(pParse);
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2,jumpIfNull^SQLITE_JUMPIFNULL);
|
||||
sqlite3ExprCachePush(pParse);
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
sqlite3VdbeResolveLabel(v, d2);
|
||||
sqlite3ExprCachePop(pParse, 1);
|
||||
@@ -3514,7 +3579,9 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
case TK_OR: {
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
|
||||
sqlite3ExprCachePush(pParse);
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
sqlite3ExprCachePop(pParse, 1);
|
||||
break;
|
||||
}
|
||||
case TK_NOT: {
|
||||
@@ -3589,10 +3656,16 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
}
|
||||
#endif
|
||||
default: {
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1);
|
||||
sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0);
|
||||
testcase( regFree1==0 );
|
||||
testcase( jumpIfNull==0 );
|
||||
if( exprAlwaysTrue(pExpr) ){
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, dest);
|
||||
}else if( exprAlwaysFalse(pExpr) ){
|
||||
/* No-op */
|
||||
}else{
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1);
|
||||
sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull!=0);
|
||||
testcase( regFree1==0 );
|
||||
testcase( jumpIfNull==0 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3655,14 +3728,16 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
case TK_AND: {
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
|
||||
sqlite3ExprCachePush(pParse);
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
sqlite3ExprCachePop(pParse, 1);
|
||||
break;
|
||||
}
|
||||
case TK_OR: {
|
||||
int d2 = sqlite3VdbeMakeLabel(v);
|
||||
testcase( jumpIfNull==0 );
|
||||
sqlite3ExprCachePush(pParse);
|
||||
sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, jumpIfNull^SQLITE_JUMPIFNULL);
|
||||
sqlite3ExprCachePush(pParse);
|
||||
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
|
||||
sqlite3VdbeResolveLabel(v, d2);
|
||||
sqlite3ExprCachePop(pParse, 1);
|
||||
@@ -3734,10 +3809,16 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
||||
}
|
||||
#endif
|
||||
default: {
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1);
|
||||
sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0);
|
||||
testcase( regFree1==0 );
|
||||
testcase( jumpIfNull==0 );
|
||||
if( exprAlwaysFalse(pExpr) ){
|
||||
sqlite3VdbeAddOp2(v, OP_Goto, 0, dest);
|
||||
}else if( exprAlwaysTrue(pExpr) ){
|
||||
/* no-op */
|
||||
}else{
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr, ®Free1);
|
||||
sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull!=0);
|
||||
testcase( regFree1==0 );
|
||||
testcase( jumpIfNull==0 );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+30
-3
@@ -137,7 +137,7 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
|
||||
case SQLITE_INTEGER: {
|
||||
i64 iVal = sqlite3_value_int64(argv[0]);
|
||||
if( iVal<0 ){
|
||||
if( (iVal<<1)==0 ){
|
||||
if( iVal==SMALLEST_INT64 ){
|
||||
/* IMP: R-31676-45509 If X is the integer -9223372036854775808
|
||||
** then abs(X) throws an integer overflow error since there is no
|
||||
** equivalent positive 64-bit two complement value. */
|
||||
@@ -218,6 +218,32 @@ static void instrFunc(
|
||||
sqlite3_result_int(context, N);
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the printf() function.
|
||||
*/
|
||||
static void printfFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
PrintfArguments x;
|
||||
StrAccum str;
|
||||
const char *zFormat;
|
||||
int n;
|
||||
|
||||
if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){
|
||||
x.nArg = argc-1;
|
||||
x.nUsed = 0;
|
||||
x.apArg = argv+1;
|
||||
sqlite3StrAccumInit(&str, 0, 0, SQLITE_MAX_LENGTH);
|
||||
str.db = sqlite3_context_db_handle(context);
|
||||
sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x);
|
||||
n = str.nChar;
|
||||
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
|
||||
SQLITE_DYNAMIC);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the substr() function.
|
||||
**
|
||||
@@ -1511,11 +1537,11 @@ static void groupConcatStep(
|
||||
zSep = ",";
|
||||
nSep = 1;
|
||||
}
|
||||
sqlite3StrAccumAppend(pAccum, zSep, nSep);
|
||||
if( nSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep);
|
||||
}
|
||||
zVal = (char*)sqlite3_value_text(argv[0]);
|
||||
nVal = sqlite3_value_bytes(argv[0]);
|
||||
sqlite3StrAccumAppend(pAccum, zVal, nVal);
|
||||
if( nVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal);
|
||||
}
|
||||
}
|
||||
static void groupConcatFinalize(sqlite3_context *context){
|
||||
@@ -1648,6 +1674,7 @@ void sqlite3RegisterGlobalFunctions(void){
|
||||
FUNCTION(instr, 2, 0, 0, instrFunc ),
|
||||
FUNCTION(substr, 2, 0, 0, substrFunc ),
|
||||
FUNCTION(substr, 3, 0, 0, substrFunc ),
|
||||
FUNCTION(printf, -1, 0, 0, printfFunc ),
|
||||
FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
|
||||
FUNCTION(char, -1, 0, 0, charFunc ),
|
||||
FUNCTION(abs, 1, 0, 0, absFunc ),
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ void sqlite3HashClear(Hash *pH){
|
||||
** The hashing function.
|
||||
*/
|
||||
static unsigned int strHash(const char *z, int nKey){
|
||||
int h = 0;
|
||||
unsigned int h = 0;
|
||||
assert( nKey>=0 );
|
||||
while( nKey > 0 ){
|
||||
h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
|
||||
|
||||
+62
-40
@@ -540,7 +540,6 @@ static int xferOptimization(
|
||||
void sqlite3Insert(
|
||||
Parse *pParse, /* Parser context */
|
||||
SrcList *pTabList, /* Name of table into which we are inserting */
|
||||
ExprList *pList, /* List of values to be inserted */
|
||||
Select *pSelect, /* A SELECT statement to use as the data source */
|
||||
IdList *pColumn, /* Column names corresponding to IDLIST. */
|
||||
int onError /* How to handle constraint errors */
|
||||
@@ -568,6 +567,7 @@ void sqlite3Insert(
|
||||
Db *pDb; /* The database containing table being inserted into */
|
||||
int appendFlag = 0; /* True if the insert is likely to be an append */
|
||||
int withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */
|
||||
ExprList *pList = 0; /* List of VALUES() to be inserted */
|
||||
|
||||
/* Register allocations */
|
||||
int regFromSelect = 0;/* Base register for data coming from SELECT */
|
||||
@@ -591,6 +591,17 @@ void sqlite3Insert(
|
||||
goto insert_cleanup;
|
||||
}
|
||||
|
||||
/* If the Select object is really just a simple VALUES() list with a
|
||||
** single row values (the common case) then keep that one row of values
|
||||
** and go ahead and discard the Select object
|
||||
*/
|
||||
if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){
|
||||
pList = pSelect->pEList;
|
||||
pSelect->pEList = 0;
|
||||
sqlite3SelectDelete(db, pSelect);
|
||||
pSelect = 0;
|
||||
}
|
||||
|
||||
/* Locate the table into which we will be inserting new information.
|
||||
*/
|
||||
assert( pTabList->nSrc==1 );
|
||||
@@ -1233,6 +1244,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
int ipkTop = 0; /* Top of the rowid change constraint check */
|
||||
int ipkBottom = 0; /* Bottom of the rowid change constraint check */
|
||||
u8 isUpdate; /* True if this is an UPDATE operation */
|
||||
int regRowid = -1; /* Register holding ROWID value */
|
||||
|
||||
isUpdate = regOldData!=0;
|
||||
db = pParse->db;
|
||||
@@ -1463,7 +1475,9 @@ void sqlite3GenerateConstraintChecks(
|
||||
int iField = pIdx->aiColumn[i];
|
||||
int x;
|
||||
if( iField<0 || iField==pTab->iPKey ){
|
||||
if( regRowid==regIdx+i ) continue; /* ROWID already in regIdx+i */
|
||||
x = regNewData;
|
||||
regRowid = pIdx->pPartIdxWhere ? -1 : regIdx+i;
|
||||
}else{
|
||||
x = iField + regNewData + 1;
|
||||
}
|
||||
@@ -1503,47 +1517,49 @@ void sqlite3GenerateConstraintChecks(
|
||||
|
||||
/* Generate code to handle collisions */
|
||||
regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField);
|
||||
if( HasRowid(pTab) ){
|
||||
sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR);
|
||||
/* Conflict only if the rowid of the existing index entry
|
||||
** is different from old-rowid */
|
||||
if( isUpdate ){
|
||||
sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData);
|
||||
}
|
||||
}else{
|
||||
int x;
|
||||
/* Extract the PRIMARY KEY from the end of the index entry and
|
||||
** store it in registers regR..regR+nPk-1 */
|
||||
if( (isUpdate || onError==OE_Replace) && pIdx!=pPk ){
|
||||
for(i=0; i<pPk->nKeyCol; i++){
|
||||
x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
|
||||
VdbeComment((v, "%s.%s", pTab->zName,
|
||||
pTab->aCol[pPk->aiColumn[i]].zName));
|
||||
if( isUpdate || onError==OE_Replace ){
|
||||
if( HasRowid(pTab) ){
|
||||
sqlite3VdbeAddOp2(v, OP_IdxRowid, iThisCur, regR);
|
||||
/* Conflict only if the rowid of the existing index entry
|
||||
** is different from old-rowid */
|
||||
if( isUpdate ){
|
||||
sqlite3VdbeAddOp3(v, OP_Eq, regR, addrUniqueOk, regOldData);
|
||||
}
|
||||
}
|
||||
if( isUpdate ){
|
||||
/* If currently processing the PRIMARY KEY of a WITHOUT ROWID
|
||||
** table, only conflict if the new PRIMARY KEY values are actually
|
||||
** different from the old.
|
||||
**
|
||||
** For a UNIQUE index, only conflict if the PRIMARY KEY values
|
||||
** of the matched index row are different from the original PRIMARY
|
||||
** KEY values of this row before the update. */
|
||||
int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
|
||||
int op = OP_Ne;
|
||||
int regCmp = (pIdx->autoIndex==2 ? regIdx : regR);
|
||||
|
||||
for(i=0; i<pPk->nKeyCol; i++){
|
||||
char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]);
|
||||
x = pPk->aiColumn[i];
|
||||
if( i==(pPk->nKeyCol-1) ){
|
||||
addrJump = addrUniqueOk;
|
||||
op = OP_Eq;
|
||||
}else{
|
||||
int x;
|
||||
/* Extract the PRIMARY KEY from the end of the index entry and
|
||||
** store it in registers regR..regR+nPk-1 */
|
||||
if( pIdx!=pPk ){
|
||||
for(i=0; i<pPk->nKeyCol; i++){
|
||||
x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
|
||||
VdbeComment((v, "%s.%s", pTab->zName,
|
||||
pTab->aCol[pPk->aiColumn[i]].zName));
|
||||
}
|
||||
}
|
||||
if( isUpdate ){
|
||||
/* If currently processing the PRIMARY KEY of a WITHOUT ROWID
|
||||
** table, only conflict if the new PRIMARY KEY values are actually
|
||||
** different from the old.
|
||||
**
|
||||
** For a UNIQUE index, only conflict if the PRIMARY KEY values
|
||||
** of the matched index row are different from the original PRIMARY
|
||||
** KEY values of this row before the update. */
|
||||
int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
|
||||
int op = OP_Ne;
|
||||
int regCmp = (pIdx->autoIndex==2 ? regIdx : regR);
|
||||
|
||||
for(i=0; i<pPk->nKeyCol; i++){
|
||||
char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]);
|
||||
x = pPk->aiColumn[i];
|
||||
if( i==(pPk->nKeyCol-1) ){
|
||||
addrJump = addrUniqueOk;
|
||||
op = OP_Eq;
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, op,
|
||||
regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ
|
||||
);
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, op,
|
||||
regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1842,6 +1858,12 @@ static int xferOptimization(
|
||||
if( pSelect==0 ){
|
||||
return 0; /* Must be of the form INSERT INTO ... SELECT ... */
|
||||
}
|
||||
if( pParse->pWith || pSelect->pWith ){
|
||||
/* Do not attempt to process this query if there are an WITH clauses
|
||||
** attached to it. Proceeding may generate a false "no such table: xxx"
|
||||
** error if pSelect reads from a CTE named "xxx". */
|
||||
return 0;
|
||||
}
|
||||
if( sqlite3TriggerList(pParse, pDest) ){
|
||||
return 0; /* tab1 must not have triggers */
|
||||
}
|
||||
|
||||
+20
-22
@@ -135,13 +135,6 @@ int sqlite3_initialize(void){
|
||||
*/
|
||||
if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
|
||||
|
||||
#ifdef SQLITE_ENABLE_SQLLOG
|
||||
{
|
||||
extern void sqlite3_init_sqllog(void);
|
||||
sqlite3_init_sqllog();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Make sure the mutex subsystem is initialized. If unable to
|
||||
** initialize the mutex subsystem, return early with the error.
|
||||
** If the system is so sick that we are unable to allocate a mutex,
|
||||
@@ -588,7 +581,8 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
|
||||
db->lookaside.bEnabled = 1;
|
||||
db->lookaside.bMalloced = pBuf==0 ?1:0;
|
||||
}else{
|
||||
db->lookaside.pEnd = 0;
|
||||
db->lookaside.pStart = db;
|
||||
db->lookaside.pEnd = db;
|
||||
db->lookaside.bEnabled = 0;
|
||||
db->lookaside.bMalloced = 0;
|
||||
}
|
||||
@@ -986,9 +980,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
|
||||
#endif
|
||||
|
||||
sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
|
||||
if( db->pErr ){
|
||||
sqlite3ValueFree(db->pErr);
|
||||
}
|
||||
sqlite3ValueFree(db->pErr);
|
||||
sqlite3CloseExtensions(db);
|
||||
|
||||
db->magic = SQLITE_MAGIC_ERROR;
|
||||
@@ -1063,8 +1055,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
|
||||
** Return a static string containing the name corresponding to the error code
|
||||
** specified in the argument.
|
||||
*/
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) || \
|
||||
defined(SQLITE_DEBUG_OS_TRACE)
|
||||
#if defined(SQLITE_TEST)
|
||||
const char *sqlite3ErrName(int rc){
|
||||
const char *zName = 0;
|
||||
int i, origRc = rc;
|
||||
@@ -1086,6 +1077,7 @@ const char *sqlite3ErrName(int rc){
|
||||
case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break;
|
||||
case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break;
|
||||
case SQLITE_READONLY_ROLLBACK: zName = "SQLITE_READONLY_ROLLBACK"; break;
|
||||
case SQLITE_READONLY_DBMOVED: zName = "SQLITE_READONLY_DBMOVED"; break;
|
||||
case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
|
||||
case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
|
||||
case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break;
|
||||
@@ -1370,6 +1362,7 @@ int sqlite3CreateFunc(
|
||||
){
|
||||
FuncDef *p;
|
||||
int nName;
|
||||
int extraFlags;
|
||||
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
if( zFunctionName==0 ||
|
||||
@@ -1380,6 +1373,10 @@ int sqlite3CreateFunc(
|
||||
(255<(nName = sqlite3Strlen30( zFunctionName))) ){
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
|
||||
assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
|
||||
extraFlags = enc & SQLITE_DETERMINISTIC;
|
||||
enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
|
||||
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
/* If SQLITE_UTF16 is specified as the encoding type, transform this
|
||||
@@ -1393,10 +1390,10 @@ int sqlite3CreateFunc(
|
||||
enc = SQLITE_UTF16NATIVE;
|
||||
}else if( enc==SQLITE_ANY ){
|
||||
int rc;
|
||||
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8,
|
||||
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags,
|
||||
pUserData, xFunc, xStep, xFinal, pDestructor);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE,
|
||||
rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags,
|
||||
pUserData, xFunc, xStep, xFinal, pDestructor);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
@@ -1439,7 +1436,8 @@ int sqlite3CreateFunc(
|
||||
pDestructor->nRef++;
|
||||
}
|
||||
p->pDestructor = pDestructor;
|
||||
p->funcFlags &= SQLITE_FUNC_ENCMASK;
|
||||
p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags;
|
||||
testcase( p->funcFlags & SQLITE_DETERMINISTIC );
|
||||
p->xFunc = xFunc;
|
||||
p->xStep = xStep;
|
||||
p->xFinalize = xFinal;
|
||||
@@ -1869,6 +1867,7 @@ const char *sqlite3_errmsg(sqlite3 *db){
|
||||
if( db->mallocFailed ){
|
||||
z = sqlite3ErrStr(SQLITE_NOMEM);
|
||||
}else{
|
||||
testcase( db->pErr==0 );
|
||||
z = (char*)sqlite3_value_text(db->pErr);
|
||||
assert( !db->mallocFailed );
|
||||
if( z==0 ){
|
||||
@@ -1910,8 +1909,7 @@ const void *sqlite3_errmsg16(sqlite3 *db){
|
||||
}else{
|
||||
z = sqlite3_value_text16(db->pErr);
|
||||
if( z==0 ){
|
||||
sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode),
|
||||
SQLITE_UTF8, SQLITE_STATIC);
|
||||
sqlite3Error(db, db->errCode, sqlite3ErrStr(db->errCode));
|
||||
z = sqlite3_value_text16(db->pErr);
|
||||
}
|
||||
/* A malloc() may have failed within the call to sqlite3_value_text16()
|
||||
@@ -2625,8 +2623,6 @@ static int openDatabase(
|
||||
}
|
||||
#endif
|
||||
|
||||
sqlite3Error(db, rc, 0);
|
||||
|
||||
/* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
|
||||
** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking
|
||||
** mode. Doing nothing at all also makes NORMAL the default.
|
||||
@@ -2637,6 +2633,8 @@ static int openDatabase(
|
||||
SQLITE_DEFAULT_LOCKING_MODE);
|
||||
#endif
|
||||
|
||||
if( rc ) sqlite3Error(db, rc, 0);
|
||||
|
||||
/* Enable the lookaside-malloc subsystem */
|
||||
setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside,
|
||||
sqlite3GlobalConfig.nLookaside);
|
||||
@@ -3096,7 +3094,7 @@ int sqlite3_test_control(int op, ...){
|
||||
** to the xRandomness method of the default VFS.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_PRNG_RESET: {
|
||||
sqlite3PrngResetState();
|
||||
sqlite3_randomness(0,0);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3305,7 +3303,7 @@ int sqlite3_test_control(int op, ...){
|
||||
** that demonstrat invariants on well-formed database files.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_NEVER_CORRUPT: {
|
||||
sqlite3Config.neverCorrupt = va_arg(ap, int);
|
||||
sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -433,7 +433,7 @@ void sqlite3ScratchFree(void *p){
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_LOOKASIDE
|
||||
static int isLookaside(sqlite3 *db, void *p){
|
||||
return p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
|
||||
return p>=db->lookaside.pStart && p<db->lookaside.pEnd;
|
||||
}
|
||||
#else
|
||||
#define isLookaside(A,B) 0
|
||||
@@ -449,8 +449,9 @@ int sqlite3MallocSize(void *p){
|
||||
return sqlite3GlobalConfig.m.xSize(p);
|
||||
}
|
||||
int sqlite3DbMallocSize(sqlite3 *db, void *p){
|
||||
assert( db==0 || sqlite3_mutex_held(db->mutex) );
|
||||
if( db && isLookaside(db, p) ){
|
||||
assert( db!=0 );
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
if( isLookaside(db, p) ){
|
||||
return db->lookaside.sz;
|
||||
}else{
|
||||
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
|
||||
|
||||
@@ -107,7 +107,21 @@ int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
|
||||
** routine has no return value since the return value would be meaningless.
|
||||
*/
|
||||
int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
DO_OS_MALLOC_TEST(id);
|
||||
#ifdef SQLITE_TEST
|
||||
if( op!=SQLITE_FCNTL_COMMIT_PHASETWO ){
|
||||
/* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
|
||||
** is using a regular VFS, it is called after the corresponding
|
||||
** transaction has been committed. Injecting a fault at this point
|
||||
** confuses the test scripts - the COMMIT comand returns SQLITE_NOMEM
|
||||
** but the transaction is committed anyway.
|
||||
**
|
||||
** The core must call OsFileControl() though, not OsFileControlHint(),
|
||||
** as if a custom VFS (e.g. zipvfs) returns an error here, it probably
|
||||
** means the commit really has failed and an error should be returned
|
||||
** to the user. */
|
||||
DO_OS_MALLOC_TEST(id);
|
||||
}
|
||||
#endif
|
||||
return id->pMethods->xFileControl(id, op, pArg);
|
||||
}
|
||||
void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
|
||||
|
||||
+41
-11
@@ -260,6 +260,12 @@ struct unixFile {
|
||||
#endif
|
||||
};
|
||||
|
||||
/* This variable holds the process id (pid) from when the xRandomness()
|
||||
** method was called. If xOpen() is called from a different process id,
|
||||
** indicating that a fork() has occurred, the PRNG will be reset.
|
||||
*/
|
||||
static int randomnessPid = 0;
|
||||
|
||||
/*
|
||||
** Allowed values for the unixFile.ctrlFlags bitmask:
|
||||
*/
|
||||
@@ -1315,6 +1321,15 @@ static int findInodeInfo(
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if pFile has been renamed or unlinked since it was first opened.
|
||||
*/
|
||||
static int fileHasMoved(unixFile *pFile){
|
||||
struct stat buf;
|
||||
return pFile->pInode!=0 &&
|
||||
(osStat(pFile->zPath, &buf)!=0 || buf.st_ino!=pFile->pInode->fileId.ino);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Check a unixFile that is a database. Verify the following:
|
||||
@@ -1349,10 +1364,7 @@ static void verifyDbFile(unixFile *pFile){
|
||||
pFile->ctrlFlags |= UNIXFILE_WARNED;
|
||||
return;
|
||||
}
|
||||
if( pFile->pInode!=0
|
||||
&& ((rc = osStat(pFile->zPath, &buf))!=0
|
||||
|| buf.st_ino!=pFile->pInode->fileId.ino)
|
||||
){
|
||||
if( fileHasMoved(pFile) ){
|
||||
sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
|
||||
pFile->ctrlFlags |= UNIXFILE_WARNED;
|
||||
return;
|
||||
@@ -3801,6 +3813,10 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_HAS_MOVED: {
|
||||
*(int*)pArg = fileHasMoved(pFile);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
case SQLITE_FCNTL_MMAP_SIZE: {
|
||||
i64 newLimit = *(i64*)pArg;
|
||||
@@ -4081,7 +4097,7 @@ static int unixShmSystemLock(
|
||||
#ifdef SQLITE_DEBUG
|
||||
{ u16 mask;
|
||||
OSTRACE(("SHM-LOCK "));
|
||||
mask = ofst>31 ? 0xffffffff : (1<<(ofst+n)) - (1<<ofst);
|
||||
mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<<ofst);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( lockType==F_UNLCK ){
|
||||
OSTRACE(("unlock %d ok", ofst));
|
||||
@@ -4832,10 +4848,10 @@ static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
|
||||
** may now be invalid and should be unmapped.
|
||||
*/
|
||||
static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
unixFile *pFd = (unixFile *)fd; /* The underlying database file */
|
||||
UNUSED_PARAMETER(iOff);
|
||||
|
||||
#if SQLITE_MAX_MMAP_SIZE>0
|
||||
/* If p==0 (unmap the entire file) then there must be no outstanding
|
||||
** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
|
||||
** then there must be at least one outstanding. */
|
||||
@@ -4851,6 +4867,10 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
|
||||
}
|
||||
|
||||
assert( pFd->nFetchOut>=0 );
|
||||
#else
|
||||
UNUSED_PARAMETER(fd);
|
||||
UNUSED_PARAMETER(p);
|
||||
UNUSED_PARAMETER(iOff);
|
||||
#endif
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -5641,6 +5661,16 @@ static int unixOpen(
|
||||
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
|
||||
);
|
||||
|
||||
/* Detect a pid change and reset the PRNG. There is a race condition
|
||||
** here such that two or more threads all trying to open databases at
|
||||
** the same instant might all reset the PRNG. But multiple resets
|
||||
** are harmless.
|
||||
*/
|
||||
if( randomnessPid!=getpid() ){
|
||||
randomnessPid = getpid();
|
||||
sqlite3_randomness(0,0);
|
||||
}
|
||||
|
||||
memset(p, 0, sizeof(unixFile));
|
||||
|
||||
if( eType==SQLITE_OPEN_MAIN_DB ){
|
||||
@@ -6028,18 +6058,18 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
|
||||
** tests repeatable.
|
||||
*/
|
||||
memset(zBuf, 0, nBuf);
|
||||
randomnessPid = getpid();
|
||||
#if !defined(SQLITE_TEST)
|
||||
{
|
||||
int pid, fd, got;
|
||||
int fd, got;
|
||||
fd = robust_open("/dev/urandom", O_RDONLY, 0);
|
||||
if( fd<0 ){
|
||||
time_t t;
|
||||
time(&t);
|
||||
memcpy(zBuf, &t, sizeof(t));
|
||||
pid = getpid();
|
||||
memcpy(&zBuf[sizeof(t)], &pid, sizeof(pid));
|
||||
assert( sizeof(t)+sizeof(pid)<=(size_t)nBuf );
|
||||
nBuf = sizeof(t) + sizeof(pid);
|
||||
memcpy(&zBuf[sizeof(t)], &randomnessPid, sizeof(randomnessPid));
|
||||
assert( sizeof(t)+sizeof(randomnessPid)<=(size_t)nBuf );
|
||||
nBuf = sizeof(t) + sizeof(randomnessPid);
|
||||
}else{
|
||||
do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR );
|
||||
robust_close(0, fd, __LINE__);
|
||||
|
||||
+2
-2
@@ -3119,7 +3119,7 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case SQLITE_FCNTL_VFSNAME: {
|
||||
*(char**)pArg = sqlite3_mprintf("win32");
|
||||
*(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
|
||||
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -3224,7 +3224,7 @@ static void winShmEnterMutex(void){
|
||||
static void winShmLeaveMutex(void){
|
||||
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
#ifndef NDEBUG
|
||||
static int winShmMutexHeld(void) {
|
||||
return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
|
||||
}
|
||||
|
||||
+95
-62
@@ -1024,15 +1024,12 @@ static char *print_pager_state(Pager *p){
|
||||
static int subjRequiresPage(PgHdr *pPg){
|
||||
Pager *pPager = pPg->pPager;
|
||||
PagerSavepoint *p;
|
||||
Pgno pgno;
|
||||
Pgno pgno = pPg->pgno;
|
||||
int i;
|
||||
if( pPager->nSavepoint ){
|
||||
pgno = pPg->pgno;
|
||||
for(i=0; i<pPager->nSavepoint; i++){
|
||||
p = &pPager->aSavepoint[i];
|
||||
if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
|
||||
return 1;
|
||||
}
|
||||
for(i=0; i<pPager->nSavepoint; i++){
|
||||
p = &pPager->aSavepoint[i];
|
||||
if( p->nOrig>=pgno && 0==sqlite3BitvecTest(p->pInSavepoint, pgno) ){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -1041,8 +1038,8 @@ static int subjRequiresPage(PgHdr *pPg){
|
||||
/*
|
||||
** Return true if the page is already in the journal file.
|
||||
*/
|
||||
static int pageInJournal(PgHdr *pPg){
|
||||
return sqlite3BitvecTest(pPg->pPager->pInJournal, pPg->pgno);
|
||||
static int pageInJournal(Pager *pPager, PgHdr *pPg){
|
||||
return sqlite3BitvecTest(pPager->pInJournal, pPg->pgno);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1249,6 +1246,7 @@ static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
|
||||
|| szJ<16
|
||||
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
|
||||
|| len>=nMaster
|
||||
|| len==0
|
||||
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|
||||
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
|
||||
|| memcmp(aMagic, aJournalMagic, 8)
|
||||
@@ -1989,7 +1987,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
|
||||
PgHdr *p = pager_lookup(pPager, 1);
|
||||
if( p ){
|
||||
p->pageHash = 0;
|
||||
sqlite3PagerUnref(p);
|
||||
sqlite3PagerUnrefNotNull(p);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -2018,6 +2016,11 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
|
||||
rc = pager_truncate(pPager, pPager->dbSize);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && bCommit && isOpen(pPager->fd) ){
|
||||
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0);
|
||||
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
if( !pPager->exclusiveMode
|
||||
&& (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
|
||||
){
|
||||
@@ -2831,7 +2834,7 @@ end_playback:
|
||||
if( rc==SQLITE_OK
|
||||
&& (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
|
||||
){
|
||||
rc = sqlite3PagerSync(pPager);
|
||||
rc = sqlite3PagerSync(pPager, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
|
||||
@@ -2977,7 +2980,7 @@ static int pagerUndoCallback(void *pCtx, Pgno iPg){
|
||||
if( rc==SQLITE_OK ){
|
||||
pPager->xReiniter(pPg);
|
||||
}
|
||||
sqlite3PagerUnref(pPg);
|
||||
sqlite3PagerUnrefNotNull(pPg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4332,7 +4335,7 @@ static int subjournalPage(PgHdr *pPg){
|
||||
assert( isOpen(pPager->jfd) || pagerUseWal(pPager) );
|
||||
assert( isOpen(pPager->sjfd) || pPager->nSubRec==0 );
|
||||
assert( pagerUseWal(pPager)
|
||||
|| pageInJournal(pPg)
|
||||
|| pageInJournal(pPager, pPg)
|
||||
|| pPg->pgno>pPager->dbOrigSize
|
||||
);
|
||||
rc = openSubJournal(pPager);
|
||||
@@ -4797,6 +4800,30 @@ int sqlite3PagerOpen(
|
||||
}
|
||||
|
||||
|
||||
/* Verify that the database file has not be deleted or renamed out from
|
||||
** under the pager. Return SQLITE_OK if the database is still were it ought
|
||||
** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error
|
||||
** code from sqlite3OsAccess()) if the database has gone missing.
|
||||
*/
|
||||
static int databaseIsUnmoved(Pager *pPager){
|
||||
int bHasMoved = 0;
|
||||
int rc;
|
||||
|
||||
if( pPager->tempFile ) return SQLITE_OK;
|
||||
if( pPager->dbSize==0 ) return SQLITE_OK;
|
||||
assert( pPager->zFilename && pPager->zFilename[0] );
|
||||
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved);
|
||||
if( rc==SQLITE_NOTFOUND ){
|
||||
/* If the HAS_MOVED file-control is unimplemented, assume that the file
|
||||
** has not been moved. That is the historical behavior of SQLite: prior to
|
||||
** version 3.8.3, it never checked */
|
||||
rc = SQLITE_OK;
|
||||
}else if( rc==SQLITE_OK && bHasMoved ){
|
||||
rc = SQLITE_READONLY_DBMOVED;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This function is called after transitioning from PAGER_UNLOCK to
|
||||
@@ -5268,7 +5295,7 @@ int sqlite3PagerAcquire(
|
||||
if( rc!=SQLITE_OK ) goto pager_acquire_err;
|
||||
}
|
||||
|
||||
if( iFrame==0 && bMmapOk ){
|
||||
if( bMmapOk && iFrame==0 ){
|
||||
void *pData = 0;
|
||||
|
||||
rc = sqlite3OsFetch(pPager->fd,
|
||||
@@ -5409,16 +5436,19 @@ DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){
|
||||
** are released, a rollback occurs and the lock on the database is
|
||||
** removed.
|
||||
*/
|
||||
void sqlite3PagerUnref(DbPage *pPg){
|
||||
if( pPg ){
|
||||
Pager *pPager = pPg->pPager;
|
||||
if( pPg->flags & PGHDR_MMAP ){
|
||||
pagerReleaseMapPage(pPg);
|
||||
}else{
|
||||
sqlite3PcacheRelease(pPg);
|
||||
}
|
||||
pagerUnlockIfUnused(pPager);
|
||||
void sqlite3PagerUnrefNotNull(DbPage *pPg){
|
||||
Pager *pPager;
|
||||
assert( pPg!=0 );
|
||||
pPager = pPg->pPager;
|
||||
if( pPg->flags & PGHDR_MMAP ){
|
||||
pagerReleaseMapPage(pPg);
|
||||
}else{
|
||||
sqlite3PcacheRelease(pPg);
|
||||
}
|
||||
pagerUnlockIfUnused(pPager);
|
||||
}
|
||||
void sqlite3PagerUnref(DbPage *pPg){
|
||||
if( pPg ) sqlite3PagerUnrefNotNull(pPg);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5473,13 +5503,19 @@ static int pager_open_journal(Pager *pPager){
|
||||
(SQLITE_OPEN_DELETEONCLOSE|SQLITE_OPEN_TEMP_JOURNAL):
|
||||
(SQLITE_OPEN_MAIN_JOURNAL)
|
||||
);
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
rc = sqlite3JournalOpen(
|
||||
pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
|
||||
);
|
||||
#else
|
||||
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
|
||||
#endif
|
||||
|
||||
/* Verify that the database still has the same name as it did when
|
||||
** it was originally opened. */
|
||||
rc = databaseIsUnmoved(pPager);
|
||||
if( rc==SQLITE_OK ){
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
rc = sqlite3JournalOpen(
|
||||
pVfs, pPager->zJournal, pPager->jfd, flags, jrnlBufferSize(pPager)
|
||||
);
|
||||
#else
|
||||
rc = sqlite3OsOpen(pVfs, pPager->zJournal, pPager->jfd, flags, 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
assert( rc!=SQLITE_OK || isOpen(pPager->jfd) );
|
||||
}
|
||||
@@ -5600,9 +5636,9 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
|
||||
** of any open savepoints as appropriate.
|
||||
*/
|
||||
static int pager_write(PgHdr *pPg){
|
||||
void *pData = pPg->pData;
|
||||
Pager *pPager = pPg->pPager;
|
||||
int rc = SQLITE_OK;
|
||||
int inJournal;
|
||||
|
||||
/* This routine is not called unless a write-transaction has already
|
||||
** been started. The journal file may or may not be open at this point.
|
||||
@@ -5613,14 +5649,8 @@ static int pager_write(PgHdr *pPg){
|
||||
|| pPager->eState==PAGER_WRITER_DBMOD
|
||||
);
|
||||
assert( assert_pager_state(pPager) );
|
||||
|
||||
/* If an error has been previously detected, report the same error
|
||||
** again. This should not happen, but the check provides robustness. */
|
||||
if( NEVER(pPager->errCode) ) return pPager->errCode;
|
||||
|
||||
/* Higher-level routines never call this function if database is not
|
||||
** writable. But check anyway, just for robustness. */
|
||||
if( NEVER(pPager->readOnly) ) return SQLITE_PERM;
|
||||
assert( pPager->errCode==0 );
|
||||
assert( pPager->readOnly==0 );
|
||||
|
||||
CHECK_PAGE(pPg);
|
||||
|
||||
@@ -5644,7 +5674,8 @@ static int pager_write(PgHdr *pPg){
|
||||
** to the journal then we can return right away.
|
||||
*/
|
||||
sqlite3PcacheMakeDirty(pPg);
|
||||
if( pageInJournal(pPg) && !subjRequiresPage(pPg) ){
|
||||
inJournal = pageInJournal(pPager, pPg);
|
||||
if( inJournal && (pPager->nSavepoint==0 || !subjRequiresPage(pPg)) ){
|
||||
assert( !pagerUseWal(pPager) );
|
||||
}else{
|
||||
|
||||
@@ -5652,7 +5683,7 @@ static int pager_write(PgHdr *pPg){
|
||||
** EXCLUSIVE lock on the main database file. Write the current page to
|
||||
** the transaction journal if it is not there already.
|
||||
*/
|
||||
if( !pageInJournal(pPg) && !pagerUseWal(pPager) ){
|
||||
if( !inJournal && !pagerUseWal(pPager) ){
|
||||
assert( pagerUseWal(pPager)==0 );
|
||||
if( pPg->pgno<=pPager->dbOrigSize && isOpen(pPager->jfd) ){
|
||||
u32 cksum;
|
||||
@@ -5665,7 +5696,7 @@ static int pager_write(PgHdr *pPg){
|
||||
assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
|
||||
|
||||
assert( pPager->journalHdr<=pPager->journalOff );
|
||||
CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
|
||||
CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM, pData2);
|
||||
cksum = pager_cksum(pPager, (u8*)pData2);
|
||||
|
||||
/* Even if an IO or diskfull error occurs while journalling the
|
||||
@@ -5717,7 +5748,7 @@ static int pager_write(PgHdr *pPg){
|
||||
** the statement journal format differs from the standard journal format
|
||||
** in that it omits the checksums and the header.
|
||||
*/
|
||||
if( subjRequiresPage(pPg) ){
|
||||
if( pPager->nSavepoint>0 && subjRequiresPage(pPg) ){
|
||||
rc = subjournalPage(pPg);
|
||||
}
|
||||
}
|
||||
@@ -5749,19 +5780,19 @@ int sqlite3PagerWrite(DbPage *pDbPage){
|
||||
|
||||
PgHdr *pPg = pDbPage;
|
||||
Pager *pPager = pPg->pPager;
|
||||
Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
|
||||
|
||||
assert( (pPg->flags & PGHDR_MMAP)==0 );
|
||||
assert( pPager->eState>=PAGER_WRITER_LOCKED );
|
||||
assert( pPager->eState!=PAGER_ERROR );
|
||||
assert( assert_pager_state(pPager) );
|
||||
|
||||
if( nPagePerSector>1 ){
|
||||
if( pPager->sectorSize > (u32)pPager->pageSize ){
|
||||
Pgno nPageCount; /* Total number of pages in database file */
|
||||
Pgno pg1; /* First page of the sector pPg is located on. */
|
||||
int nPage = 0; /* Number of pages starting at pg1 to journal */
|
||||
int ii; /* Loop counter */
|
||||
int needSync = 0; /* True if any page has PGHDR_NEED_SYNC */
|
||||
Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize);
|
||||
|
||||
/* Set the doNotSpill NOSYNC bit to 1. This is because we cannot allow
|
||||
** a journal header to be written between the pages journaled by
|
||||
@@ -5800,14 +5831,14 @@ int sqlite3PagerWrite(DbPage *pDbPage){
|
||||
if( pPage->flags&PGHDR_NEED_SYNC ){
|
||||
needSync = 1;
|
||||
}
|
||||
sqlite3PagerUnref(pPage);
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
}else if( (pPage = pager_lookup(pPager, pg))!=0 ){
|
||||
if( pPage->flags&PGHDR_NEED_SYNC ){
|
||||
needSync = 1;
|
||||
}
|
||||
sqlite3PagerUnref(pPage);
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5823,7 +5854,7 @@ int sqlite3PagerWrite(DbPage *pDbPage){
|
||||
PgHdr *pPage = pager_lookup(pPager, pg1+ii);
|
||||
if( pPage ){
|
||||
pPage->flags |= PGHDR_NEED_SYNC;
|
||||
sqlite3PagerUnref(pPage);
|
||||
sqlite3PagerUnrefNotNull(pPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5976,17 +6007,17 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
|
||||
** If successful, or if called on a pager for which it is a no-op, this
|
||||
** function returns SQLITE_OK. Otherwise, an IO error code is returned.
|
||||
*/
|
||||
int sqlite3PagerSync(Pager *pPager){
|
||||
int sqlite3PagerSync(Pager *pPager, const char *zMaster){
|
||||
int rc = SQLITE_OK;
|
||||
if( !pPager->noSync ){
|
||||
|
||||
if( isOpen(pPager->fd) ){
|
||||
void *pArg = (void*)zMaster;
|
||||
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg);
|
||||
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
|
||||
}
|
||||
if( rc==SQLITE_OK && !pPager->noSync ){
|
||||
assert( !MEMDB );
|
||||
rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
|
||||
}else if( isOpen(pPager->fd) ){
|
||||
assert( !MEMDB );
|
||||
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC_OMITTED, 0);
|
||||
if( rc==SQLITE_NOTFOUND ){
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -6185,7 +6216,7 @@ int sqlite3PagerCommitPhaseOne(
|
||||
|
||||
/* Finally, sync the database file. */
|
||||
if( !noSync ){
|
||||
rc = sqlite3PagerSync(pPager);
|
||||
rc = sqlite3PagerSync(pPager, zMaster);
|
||||
}
|
||||
IOTRACE(("DBSYNC %p\n", pPager))
|
||||
}
|
||||
@@ -6314,7 +6345,9 @@ int sqlite3PagerRollback(Pager *pPager){
|
||||
|
||||
assert( pPager->eState==PAGER_READER || rc!=SQLITE_OK );
|
||||
assert( rc==SQLITE_OK || rc==SQLITE_FULL || rc==SQLITE_CORRUPT
|
||||
|| rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR );
|
||||
|| rc==SQLITE_NOMEM || (rc&0xFF)==SQLITE_IOERR
|
||||
|| rc==SQLITE_CANTOPEN
|
||||
);
|
||||
|
||||
/* If an error occurs during a ROLLBACK, we can no longer trust the pager
|
||||
** cache. So call pager_error() on the way out to make any error persistent.
|
||||
@@ -6717,7 +6750,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
||||
if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
|
||||
needSyncPgno = pPg->pgno;
|
||||
assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
|
||||
pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
|
||||
pageInJournal(pPager, pPg) || pPg->pgno>pPager->dbOrigSize );
|
||||
assert( pPg->flags&PGHDR_DIRTY );
|
||||
}
|
||||
|
||||
@@ -6751,7 +6784,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
||||
if( MEMDB ){
|
||||
assert( pPgOld );
|
||||
sqlite3PcacheMove(pPgOld, origPgno);
|
||||
sqlite3PagerUnref(pPgOld);
|
||||
sqlite3PagerUnrefNotNull(pPgOld);
|
||||
}
|
||||
|
||||
if( needSyncPgno ){
|
||||
@@ -6780,7 +6813,7 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
|
||||
}
|
||||
pPgHdr->flags |= PGHDR_NEED_SYNC;
|
||||
sqlite3PcacheMakeDirty(pPgHdr);
|
||||
sqlite3PagerUnref(pPgHdr);
|
||||
sqlite3PagerUnrefNotNull(pPgHdr);
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
|
||||
+2
-1
@@ -136,6 +136,7 @@ int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
|
||||
DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
|
||||
void sqlite3PagerRef(DbPage*);
|
||||
void sqlite3PagerUnref(DbPage*);
|
||||
void sqlite3PagerUnrefNotNull(DbPage*);
|
||||
|
||||
/* Operations on page references. */
|
||||
int sqlite3PagerWrite(DbPage*);
|
||||
@@ -150,7 +151,7 @@ void sqlite3PagerPagecount(Pager*, int*);
|
||||
int sqlite3PagerBegin(Pager*, int exFlag, int);
|
||||
int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int);
|
||||
int sqlite3PagerExclusiveLock(Pager*);
|
||||
int sqlite3PagerSync(Pager *pPager);
|
||||
int sqlite3PagerSync(Pager *pPager, const char *zMaster);
|
||||
int sqlite3PagerCommitPhaseTwo(Pager*);
|
||||
int sqlite3PagerRollback(Pager*);
|
||||
int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
|
||||
|
||||
+94
-98
@@ -94,14 +94,6 @@ struct TrigEvent { int a; IdList * b; };
|
||||
*/
|
||||
struct AttachKey { int type; Token key; };
|
||||
|
||||
/*
|
||||
** One or more VALUES claues
|
||||
*/
|
||||
struct ValueList {
|
||||
ExprList *pList;
|
||||
Select *pSelect;
|
||||
};
|
||||
|
||||
} // end %include
|
||||
|
||||
// Input is a single SQL command
|
||||
@@ -202,9 +194,7 @@ columnid(A) ::= nm(X). {
|
||||
// An IDENTIFIER can be a generic identifier, or one of several
|
||||
// keywords. Any non-standard keyword can also be an identifier.
|
||||
//
|
||||
%type id {Token}
|
||||
id(A) ::= ID(X). {A = X;}
|
||||
id(A) ::= INDEXED(X). {A = X;}
|
||||
%token_class id ID|INDEXED.
|
||||
|
||||
// The following directive causes tokens ABORT, AFTER, ASC, etc. to
|
||||
// fallback to ID if they will not parse as their original value.
|
||||
@@ -214,8 +204,8 @@ id(A) ::= INDEXED(X). {A = X;}
|
||||
ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW
|
||||
CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
|
||||
IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
|
||||
QUERY KEY OF OFFSET PRAGMA RAISE RELEASE REPLACE RESTRICT ROW ROLLBACK
|
||||
SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITHOUT
|
||||
QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW
|
||||
ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
|
||||
%ifdef SQLITE_OMIT_COMPOUND_SELECT
|
||||
EXCEPT INTERSECT UNION
|
||||
%endif SQLITE_OMIT_COMPOUND_SELECT
|
||||
@@ -249,8 +239,7 @@ id(A) ::= INDEXED(X). {A = X;}
|
||||
|
||||
// And "ids" is an identifer-or-string.
|
||||
//
|
||||
%type ids {Token}
|
||||
ids(A) ::= ID|STRING(X). {A = X;}
|
||||
%token_class ids ID|STRING.
|
||||
|
||||
// The name of a column or table can be any of the following:
|
||||
//
|
||||
@@ -408,7 +397,7 @@ cmd ::= DROP VIEW ifexists(E) fullname(X). {
|
||||
//////////////////////// The SELECT statement /////////////////////////////////
|
||||
//
|
||||
cmd ::= select(X). {
|
||||
SelectDest dest = {SRT_Output, 0, 0, 0, 0};
|
||||
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
|
||||
sqlite3Select(pParse, X, &dest);
|
||||
sqlite3ExplainBegin(pParse->pVdbe);
|
||||
sqlite3ExplainSelect(pParse->pVdbe, X);
|
||||
@@ -418,12 +407,23 @@ cmd ::= select(X). {
|
||||
|
||||
%type select {Select*}
|
||||
%destructor select {sqlite3SelectDelete(pParse->db, $$);}
|
||||
%type selectnowith {Select*}
|
||||
%destructor selectnowith {sqlite3SelectDelete(pParse->db, $$);}
|
||||
%type oneselect {Select*}
|
||||
%destructor oneselect {sqlite3SelectDelete(pParse->db, $$);}
|
||||
|
||||
select(A) ::= oneselect(X). {A = X;}
|
||||
select(A) ::= with(W) selectnowith(X). {
|
||||
if( X ){
|
||||
X->pWith = W;
|
||||
}else{
|
||||
sqlite3WithDelete(pParse->db, W);
|
||||
}
|
||||
A = X;
|
||||
}
|
||||
|
||||
selectnowith(A) ::= oneselect(X). {A = X;}
|
||||
%ifndef SQLITE_OMIT_COMPOUND_SELECT
|
||||
select(A) ::= select(X) multiselect_op(Y) oneselect(Z). {
|
||||
selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z). {
|
||||
if( Z ){
|
||||
Z->op = (u8)Y;
|
||||
Z->pPrior = X;
|
||||
@@ -442,6 +442,23 @@ oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
|
||||
groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). {
|
||||
A = sqlite3SelectNew(pParse,W,X,Y,P,Q,Z,D,L.pLimit,L.pOffset);
|
||||
}
|
||||
oneselect(A) ::= values(X). {A = X;}
|
||||
|
||||
%type values {Select*}
|
||||
%destructor values {sqlite3SelectDelete(pParse->db, $$);}
|
||||
values(A) ::= VALUES LP nexprlist(X) RP. {
|
||||
A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0,0);
|
||||
}
|
||||
values(A) ::= values(X) COMMA LP exprlist(Y) RP. {
|
||||
Select *pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values,0,0);
|
||||
if( pRight ){
|
||||
pRight->op = TK_ALL;
|
||||
pRight->pPrior = X;
|
||||
A = pRight;
|
||||
}else{
|
||||
A = X;
|
||||
}
|
||||
}
|
||||
|
||||
// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
|
||||
// present and false (0) if it is not.
|
||||
@@ -642,15 +659,17 @@ limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y).
|
||||
/////////////////////////// The DELETE statement /////////////////////////////
|
||||
//
|
||||
%ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
||||
cmd ::= DELETE FROM fullname(X) indexed_opt(I) where_opt(W)
|
||||
cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W)
|
||||
orderby_opt(O) limit_opt(L). {
|
||||
sqlite3WithPush(pParse, C, 1);
|
||||
sqlite3SrcListIndexedBy(pParse, X, &I);
|
||||
W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "DELETE");
|
||||
sqlite3DeleteFrom(pParse,X,W);
|
||||
}
|
||||
%endif
|
||||
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
||||
cmd ::= DELETE FROM fullname(X) indexed_opt(I) where_opt(W). {
|
||||
cmd ::= with(C) DELETE FROM fullname(X) indexed_opt(I) where_opt(W). {
|
||||
sqlite3WithPush(pParse, C, 1);
|
||||
sqlite3SrcListIndexedBy(pParse, X, &I);
|
||||
sqlite3DeleteFrom(pParse,X,W);
|
||||
}
|
||||
@@ -665,8 +684,9 @@ where_opt(A) ::= WHERE expr(X). {A = X.pExpr;}
|
||||
////////////////////////// The UPDATE command ////////////////////////////////
|
||||
//
|
||||
%ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
||||
cmd ::= UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) where_opt(W)
|
||||
orderby_opt(O) limit_opt(L). {
|
||||
cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y)
|
||||
where_opt(W) orderby_opt(O) limit_opt(L). {
|
||||
sqlite3WithPush(pParse, C, 1);
|
||||
sqlite3SrcListIndexedBy(pParse, X, &I);
|
||||
sqlite3ExprListCheckLength(pParse,Y,"set list");
|
||||
W = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset, "UPDATE");
|
||||
@@ -674,8 +694,9 @@ cmd ::= UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) where_opt(W)
|
||||
}
|
||||
%endif
|
||||
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
||||
cmd ::= UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y)
|
||||
cmd ::= with(C) UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y)
|
||||
where_opt(W). {
|
||||
sqlite3WithPush(pParse, C, 1);
|
||||
sqlite3SrcListIndexedBy(pParse, X, &I);
|
||||
sqlite3ExprListCheckLength(pParse,Y,"set list");
|
||||
sqlite3Update(pParse,X,Y,W,R);
|
||||
@@ -696,58 +717,20 @@ setlist(A) ::= nm(X) EQ expr(Y). {
|
||||
|
||||
////////////////////////// The INSERT command /////////////////////////////////
|
||||
//
|
||||
cmd ::= insert_cmd(R) INTO fullname(X) inscollist_opt(F) valuelist(Y).
|
||||
{sqlite3Insert(pParse, X, Y.pList, Y.pSelect, F, R);}
|
||||
cmd ::= insert_cmd(R) INTO fullname(X) inscollist_opt(F) select(S).
|
||||
{sqlite3Insert(pParse, X, 0, S, F, R);}
|
||||
cmd ::= insert_cmd(R) INTO fullname(X) inscollist_opt(F) DEFAULT VALUES.
|
||||
{sqlite3Insert(pParse, X, 0, 0, F, R);}
|
||||
cmd ::= with(W) insert_cmd(R) INTO fullname(X) inscollist_opt(F) select(S). {
|
||||
sqlite3WithPush(pParse, W, 1);
|
||||
sqlite3Insert(pParse, X, S, F, R);
|
||||
}
|
||||
cmd ::= with(W) insert_cmd(R) INTO fullname(X) inscollist_opt(F) DEFAULT VALUES.
|
||||
{
|
||||
sqlite3WithPush(pParse, W, 1);
|
||||
sqlite3Insert(pParse, X, 0, F, R);
|
||||
}
|
||||
|
||||
%type insert_cmd {u8}
|
||||
insert_cmd(A) ::= INSERT orconf(R). {A = R;}
|
||||
insert_cmd(A) ::= REPLACE. {A = OE_Replace;}
|
||||
|
||||
// A ValueList is either a single VALUES clause or a comma-separated list
|
||||
// of VALUES clauses. If it is a single VALUES clause then the
|
||||
// ValueList.pList field points to the expression list of that clause.
|
||||
// If it is a list of VALUES clauses, then those clauses are transformed
|
||||
// into a set of SELECT statements without FROM clauses and connected by
|
||||
// UNION ALL and the ValueList.pSelect points to the right-most SELECT in
|
||||
// that compound.
|
||||
%type valuelist {struct ValueList}
|
||||
%destructor valuelist {
|
||||
sqlite3ExprListDelete(pParse->db, $$.pList);
|
||||
sqlite3SelectDelete(pParse->db, $$.pSelect);
|
||||
}
|
||||
valuelist(A) ::= VALUES LP nexprlist(X) RP. {
|
||||
A.pList = X;
|
||||
A.pSelect = 0;
|
||||
}
|
||||
|
||||
// Since a list of VALUEs is inplemented as a compound SELECT, we have
|
||||
// to disable the value list option if compound SELECTs are disabled.
|
||||
%ifndef SQLITE_OMIT_COMPOUND_SELECT
|
||||
valuelist(A) ::= valuelist(X) COMMA LP exprlist(Y) RP. {
|
||||
Select *pRight = sqlite3SelectNew(pParse, Y, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
if( X.pList ){
|
||||
X.pSelect = sqlite3SelectNew(pParse, X.pList, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
X.pList = 0;
|
||||
}
|
||||
A.pList = 0;
|
||||
if( X.pSelect==0 || pRight==0 ){
|
||||
sqlite3SelectDelete(pParse->db, pRight);
|
||||
sqlite3SelectDelete(pParse->db, X.pSelect);
|
||||
A.pSelect = 0;
|
||||
}else{
|
||||
pRight->op = TK_ALL;
|
||||
pRight->pPrior = X.pSelect;
|
||||
pRight->selFlags |= SF_Values;
|
||||
pRight->pPrior->selFlags |= SF_Values;
|
||||
A.pSelect = pRight;
|
||||
}
|
||||
}
|
||||
%endif SQLITE_OMIT_COMPOUND_SELECT
|
||||
|
||||
%type inscollist_opt {IdList*}
|
||||
%destructor inscollist_opt {sqlite3IdListDelete(pParse->db, $$);}
|
||||
%type idlist {IdList*}
|
||||
@@ -810,22 +793,22 @@ expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
|
||||
}
|
||||
term(A) ::= INTEGER|FLOAT|BLOB(X). {spanExpr(&A, pParse, @X, &X);}
|
||||
term(A) ::= STRING(X). {spanExpr(&A, pParse, @X, &X);}
|
||||
expr(A) ::= REGISTER(X). {
|
||||
/* When doing a nested parse, one can include terms in an expression
|
||||
** that look like this: #1 #2 ... These terms refer to registers
|
||||
** in the virtual machine. #N is the N-th register. */
|
||||
if( pParse->nested==0 ){
|
||||
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &X);
|
||||
A.pExpr = 0;
|
||||
}else{
|
||||
A.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &X);
|
||||
if( A.pExpr ) sqlite3GetInt32(&X.z[1], &A.pExpr->iTable);
|
||||
}
|
||||
spanSet(&A, &X, &X);
|
||||
}
|
||||
expr(A) ::= VARIABLE(X). {
|
||||
spanExpr(&A, pParse, TK_VARIABLE, &X);
|
||||
sqlite3ExprAssignVarNumber(pParse, A.pExpr);
|
||||
if( X.n>=2 && X.z[0]=='#' && sqlite3Isdigit(X.z[1]) ){
|
||||
/* When doing a nested parse, one can include terms in an expression
|
||||
** that look like this: #1 #2 ... These terms refer to registers
|
||||
** in the virtual machine. #N is the N-th register. */
|
||||
if( pParse->nested==0 ){
|
||||
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &X);
|
||||
A.pExpr = 0;
|
||||
}else{
|
||||
A.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &X);
|
||||
if( A.pExpr ) sqlite3GetInt32(&X.z[1], &A.pExpr->iTable);
|
||||
}
|
||||
}else{
|
||||
spanExpr(&A, pParse, TK_VARIABLE, &X);
|
||||
sqlite3ExprAssignVarNumber(pParse, A.pExpr);
|
||||
}
|
||||
spanSet(&A, &X, &X);
|
||||
}
|
||||
expr(A) ::= expr(E) COLLATE ids(C). {
|
||||
@@ -839,7 +822,7 @@ expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). {
|
||||
spanSet(&A,&X,&Y);
|
||||
}
|
||||
%endif SQLITE_OMIT_CAST
|
||||
expr(A) ::= ID(X) LP distinct(D) exprlist(Y) RP(E). {
|
||||
expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP(E). {
|
||||
if( Y && Y->nExpr>pParse->db->aLimit[SQLITE_LIMIT_FUNCTION_ARG] ){
|
||||
sqlite3ErrorMsg(pParse, "too many arguments on function %T", &X);
|
||||
}
|
||||
@@ -849,7 +832,7 @@ expr(A) ::= ID(X) LP distinct(D) exprlist(Y) RP(E). {
|
||||
A.pExpr->flags |= EP_Distinct;
|
||||
}
|
||||
}
|
||||
expr(A) ::= ID(X) LP STAR RP(E). {
|
||||
expr(A) ::= id(X) LP STAR RP(E). {
|
||||
A.pExpr = sqlite3ExprFunction(pParse, 0, &X);
|
||||
spanSet(&A,&X,&E);
|
||||
}
|
||||
@@ -888,10 +871,8 @@ expr(A) ::= expr(X) STAR|SLASH|REM(OP) expr(Y).
|
||||
{spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
|
||||
expr(A) ::= expr(X) CONCAT(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);}
|
||||
%type likeop {struct LikeOp}
|
||||
likeop(A) ::= LIKE_KW(X). {A.eOperator = X; A.bNot = 0;}
|
||||
likeop(A) ::= NOT LIKE_KW(X). {A.eOperator = X; A.bNot = 1;}
|
||||
likeop(A) ::= MATCH(X). {A.eOperator = X; A.bNot = 0;}
|
||||
likeop(A) ::= NOT MATCH(X). {A.eOperator = X; A.bNot = 1;}
|
||||
likeop(A) ::= LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 0;}
|
||||
likeop(A) ::= NOT LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 1;}
|
||||
expr(A) ::= expr(X) likeop(OP) expr(Y). [LIKE_KW] {
|
||||
ExprList *pList;
|
||||
pList = sqlite3ExprListAppend(pParse,0, Y.pExpr);
|
||||
@@ -1199,11 +1180,10 @@ nmnum(A) ::= ON(X). {A = X;}
|
||||
nmnum(A) ::= DELETE(X). {A = X;}
|
||||
nmnum(A) ::= DEFAULT(X). {A = X;}
|
||||
%endif SQLITE_OMIT_PRAGMA
|
||||
%token_class number INTEGER|FLOAT.
|
||||
plus_num(A) ::= PLUS number(X). {A = X;}
|
||||
plus_num(A) ::= number(X). {A = X;}
|
||||
minus_num(A) ::= MINUS number(X). {A = X;}
|
||||
number(A) ::= INTEGER|FLOAT(X). {A = X;}
|
||||
|
||||
//////////////////////////// The CREATE TRIGGER command /////////////////////
|
||||
|
||||
%ifndef SQLITE_OMIT_TRIGGER
|
||||
@@ -1295,12 +1275,8 @@ trigger_cmd(A) ::=
|
||||
{ A = sqlite3TriggerUpdateStep(pParse->db, &X, Y, Z, R); }
|
||||
|
||||
// INSERT
|
||||
trigger_cmd(A) ::=
|
||||
insert_cmd(R) INTO trnm(X) inscollist_opt(F) valuelist(Y).
|
||||
{A = sqlite3TriggerInsertStep(pParse->db, &X, F, Y.pList, Y.pSelect, R);}
|
||||
|
||||
trigger_cmd(A) ::= insert_cmd(R) INTO trnm(X) inscollist_opt(F) select(S).
|
||||
{A = sqlite3TriggerInsertStep(pParse->db, &X, F, 0, S, R);}
|
||||
{A = sqlite3TriggerInsertStep(pParse->db, &X, F, S, R);}
|
||||
|
||||
// DELETE
|
||||
trigger_cmd(A) ::= DELETE FROM trnm(X) tridxby where_opt(Y).
|
||||
@@ -1406,3 +1382,23 @@ anylist ::= .
|
||||
anylist ::= anylist LP anylist RP.
|
||||
anylist ::= anylist ANY.
|
||||
%endif SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
|
||||
//////////////////////// COMMON TABLE EXPRESSIONS ////////////////////////////
|
||||
%type with {With*}
|
||||
%type wqlist {With*}
|
||||
%destructor with {sqlite3WithDelete(pParse->db, $$);}
|
||||
%destructor wqlist {sqlite3WithDelete(pParse->db, $$);}
|
||||
|
||||
with(A) ::= . {A = 0;}
|
||||
%ifndef SQLITE_OMIT_CTE
|
||||
with(A) ::= WITH wqlist(W). { A = W; }
|
||||
with(A) ::= WITH RECURSIVE wqlist(W). { A = W; }
|
||||
|
||||
wqlist(A) ::= nm(X) idxlist_opt(Y) AS LP select(Z) RP. {
|
||||
A = sqlite3WithAdd(pParse, 0, &X, Y, Z);
|
||||
}
|
||||
wqlist(A) ::= wqlist(W) COMMA nm(X) idxlist_opt(Y) AS LP select(Z) RP. {
|
||||
A = sqlite3WithAdd(pParse, W, &X, Y, Z);
|
||||
}
|
||||
%endif SQLITE_OMIT_CTE
|
||||
|
||||
+33
-23
@@ -96,6 +96,7 @@ struct PCache1 {
|
||||
struct PgHdr1 {
|
||||
sqlite3_pcache_page page;
|
||||
unsigned int iKey; /* Key value (page number) */
|
||||
u8 isPinned; /* Page in use, not on the LRU list */
|
||||
PgHdr1 *pNext; /* Next in hash table chain */
|
||||
PCache1 *pCache; /* Cache that currently owns this page */
|
||||
PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
|
||||
@@ -424,34 +425,32 @@ static int pcache1ResizeHash(PCache1 *p){
|
||||
** LRU list, then this function is a no-op.
|
||||
**
|
||||
** The PGroup mutex must be held when this function is called.
|
||||
**
|
||||
** If pPage is NULL then this routine is a no-op.
|
||||
*/
|
||||
static void pcache1PinPage(PgHdr1 *pPage){
|
||||
PCache1 *pCache;
|
||||
PGroup *pGroup;
|
||||
|
||||
if( pPage==0 ) return;
|
||||
assert( pPage!=0 );
|
||||
assert( pPage->isPinned==0 );
|
||||
pCache = pPage->pCache;
|
||||
pGroup = pCache->pGroup;
|
||||
assert( pPage->pLruNext || pPage==pGroup->pLruTail );
|
||||
assert( pPage->pLruPrev || pPage==pGroup->pLruHead );
|
||||
assert( sqlite3_mutex_held(pGroup->mutex) );
|
||||
if( pPage->pLruNext || pPage==pGroup->pLruTail ){
|
||||
if( pPage->pLruPrev ){
|
||||
pPage->pLruPrev->pLruNext = pPage->pLruNext;
|
||||
}
|
||||
if( pPage->pLruNext ){
|
||||
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
|
||||
}
|
||||
if( pGroup->pLruHead==pPage ){
|
||||
pGroup->pLruHead = pPage->pLruNext;
|
||||
}
|
||||
if( pGroup->pLruTail==pPage ){
|
||||
pGroup->pLruTail = pPage->pLruPrev;
|
||||
}
|
||||
pPage->pLruNext = 0;
|
||||
pPage->pLruPrev = 0;
|
||||
pPage->pCache->nRecyclable--;
|
||||
if( pPage->pLruPrev ){
|
||||
pPage->pLruPrev->pLruNext = pPage->pLruNext;
|
||||
}else{
|
||||
pGroup->pLruHead = pPage->pLruNext;
|
||||
}
|
||||
if( pPage->pLruNext ){
|
||||
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
|
||||
}else{
|
||||
pGroup->pLruTail = pPage->pLruPrev;
|
||||
}
|
||||
pPage->pLruNext = 0;
|
||||
pPage->pLruPrev = 0;
|
||||
pPage->isPinned = 1;
|
||||
pCache->nRecyclable--;
|
||||
}
|
||||
|
||||
|
||||
@@ -483,6 +482,7 @@ static void pcache1EnforceMaxPage(PGroup *pGroup){
|
||||
while( pGroup->nCurrentPage>pGroup->nMaxPage && pGroup->pLruTail ){
|
||||
PgHdr1 *p = pGroup->pLruTail;
|
||||
assert( p->pCache->pGroup==pGroup );
|
||||
assert( p->isPinned==0 );
|
||||
pcache1PinPage(p);
|
||||
pcache1RemoveFromHash(p);
|
||||
pcache1FreePage(p);
|
||||
@@ -510,7 +510,7 @@ static void pcache1TruncateUnsafe(
|
||||
if( pPage->iKey>=iLimit ){
|
||||
pCache->nPage--;
|
||||
*pp = pPage->pNext;
|
||||
pcache1PinPage(pPage);
|
||||
if( !pPage->isPinned ) pcache1PinPage(pPage);
|
||||
pcache1FreePage(pPage);
|
||||
}else{
|
||||
pp = &pPage->pNext;
|
||||
@@ -720,6 +720,7 @@ static sqlite3_pcache_page *pcache1Fetch(
|
||||
PGroup *pGroup;
|
||||
PgHdr1 *pPage = 0;
|
||||
|
||||
assert( offsetof(PgHdr1,page)==0 );
|
||||
assert( pCache->bPurgeable || createFlag!=1 );
|
||||
assert( pCache->bPurgeable || pCache->nMin==0 );
|
||||
assert( pCache->bPurgeable==0 || pCache->nMin==10 );
|
||||
@@ -733,8 +734,11 @@ static sqlite3_pcache_page *pcache1Fetch(
|
||||
}
|
||||
|
||||
/* Step 2: Abort if no existing page is found and createFlag is 0 */
|
||||
if( pPage || createFlag==0 ){
|
||||
pcache1PinPage(pPage);
|
||||
if( pPage ){
|
||||
if( !pPage->isPinned ) pcache1PinPage(pPage);
|
||||
goto fetch_out;
|
||||
}
|
||||
if( createFlag==0 ){
|
||||
goto fetch_out;
|
||||
}
|
||||
|
||||
@@ -775,6 +779,7 @@ static sqlite3_pcache_page *pcache1Fetch(
|
||||
)){
|
||||
PCache1 *pOther;
|
||||
pPage = pGroup->pLruTail;
|
||||
assert( pPage->isPinned==0 );
|
||||
pcache1RemoveFromHash(pPage);
|
||||
pcache1PinPage(pPage);
|
||||
pOther = pPage->pCache;
|
||||
@@ -811,6 +816,7 @@ static sqlite3_pcache_page *pcache1Fetch(
|
||||
pPage->pCache = pCache;
|
||||
pPage->pLruPrev = 0;
|
||||
pPage->pLruNext = 0;
|
||||
pPage->isPinned = 1;
|
||||
*(void **)pPage->page.pExtra = 0;
|
||||
pCache->apHash[h] = pPage;
|
||||
}
|
||||
@@ -820,7 +826,7 @@ fetch_out:
|
||||
pCache->iMaxKey = iKey;
|
||||
}
|
||||
pcache1LeaveMutex(pGroup);
|
||||
return &pPage->page;
|
||||
return (sqlite3_pcache_page*)pPage;
|
||||
}
|
||||
|
||||
|
||||
@@ -846,6 +852,7 @@ static void pcache1Unpin(
|
||||
*/
|
||||
assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
|
||||
assert( pGroup->pLruHead!=pPage && pGroup->pLruTail!=pPage );
|
||||
assert( pPage->isPinned==1 );
|
||||
|
||||
if( reuseUnlikely || pGroup->nCurrentPage>pGroup->nMaxPage ){
|
||||
pcache1RemoveFromHash(pPage);
|
||||
@@ -861,6 +868,7 @@ static void pcache1Unpin(
|
||||
pGroup->pLruHead = pPage;
|
||||
}
|
||||
pCache->nRecyclable++;
|
||||
pPage->isPinned = 0;
|
||||
}
|
||||
|
||||
pcache1LeaveMutex(pCache->pGroup);
|
||||
@@ -987,6 +995,7 @@ int sqlite3PcacheReleaseMemory(int nReq){
|
||||
#ifdef SQLITE_PCACHE_SEPARATE_HEADER
|
||||
nFree += sqlite3MemSize(p);
|
||||
#endif
|
||||
assert( p->isPinned==0 );
|
||||
pcache1PinPage(p);
|
||||
pcache1RemoveFromHash(p);
|
||||
pcache1FreePage(p);
|
||||
@@ -1011,6 +1020,7 @@ void sqlite3PcacheStats(
|
||||
PgHdr1 *p;
|
||||
int nRecyclable = 0;
|
||||
for(p=pcache1.grp.pLruHead; p; p=p->pLruNext){
|
||||
assert( p->isPinned==0 );
|
||||
nRecyclable++;
|
||||
}
|
||||
*pnCurrent = pcache1.grp.nCurrentPage;
|
||||
|
||||
+5
-2
@@ -1881,8 +1881,10 @@ void sqlite3Pragma(
|
||||
for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){
|
||||
Table *pTab = sqliteHashData(x);
|
||||
Index *pIdx, *pPk;
|
||||
Index *pPrior = 0;
|
||||
int loopTop;
|
||||
int iDataCur, iIdxCur;
|
||||
int r1 = -1;
|
||||
|
||||
if( pTab->pIndex==0 ) continue;
|
||||
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||
@@ -1901,9 +1903,10 @@ void sqlite3Pragma(
|
||||
loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
int jmp2, jmp3, jmp4;
|
||||
int r1;
|
||||
if( pPk==pIdx ) continue;
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3);
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
|
||||
pPrior, r1);
|
||||
pPrior = pIdx;
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */
|
||||
jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, 0, r1,
|
||||
pIdx->nColumn);
|
||||
|
||||
+5
-1
@@ -528,7 +528,11 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
|
||||
** Free all memory allocations in the pParse object
|
||||
*/
|
||||
void sqlite3ParserReset(Parse *pParse){
|
||||
if( pParse ) sqlite3ExprListDelete(pParse->db, pParse->pConstExpr);
|
||||
if( pParse ){
|
||||
sqlite3 *db = pParse->db;
|
||||
sqlite3DbFree(db, pParse->aLabel);
|
||||
sqlite3ExprListDelete(db, pParse->pConstExpr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+117
-42
@@ -148,6 +148,31 @@ void sqlite3AppendSpace(StrAccum *pAccum, int N){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the StrAccum object to an error mode.
|
||||
*/
|
||||
static void setStrAccumError(StrAccum *p, u8 eError){
|
||||
p->accError = eError;
|
||||
p->nAlloc = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Extra argument values from a PrintfArguments object
|
||||
*/
|
||||
static sqlite3_int64 getIntArg(PrintfArguments *p){
|
||||
if( p->nArg<=p->nUsed ) return 0;
|
||||
return sqlite3_value_int64(p->apArg[p->nUsed++]);
|
||||
}
|
||||
static double getDoubleArg(PrintfArguments *p){
|
||||
if( p->nArg<=p->nUsed ) return 0.0;
|
||||
return sqlite3_value_double(p->apArg[p->nUsed++]);
|
||||
}
|
||||
static char *getTextArg(PrintfArguments *p){
|
||||
if( p->nArg<=p->nUsed ) return 0;
|
||||
return (char*)sqlite3_value_text(p->apArg[p->nUsed++]);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** On machines with a small stack size, you can redefine the
|
||||
** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
|
||||
@@ -161,10 +186,10 @@ void sqlite3AppendSpace(StrAccum *pAccum, int N){
|
||||
** Render a string given by "fmt" into the StrAccum object.
|
||||
*/
|
||||
void sqlite3VXPrintf(
|
||||
StrAccum *pAccum, /* Accumulate results here */
|
||||
int useExtended, /* Allow extended %-conversions */
|
||||
const char *fmt, /* Format string */
|
||||
va_list ap /* arguments */
|
||||
StrAccum *pAccum, /* Accumulate results here */
|
||||
u32 bFlags, /* SQLITE_PRINTF_* flags */
|
||||
const char *fmt, /* Format string */
|
||||
va_list ap /* arguments */
|
||||
){
|
||||
int c; /* Next character in the format string */
|
||||
char *bufpt; /* Pointer to the conversion buffer */
|
||||
@@ -182,6 +207,8 @@ void sqlite3VXPrintf(
|
||||
etByte flag_longlong; /* True if the "ll" flag is present */
|
||||
etByte done; /* Loop termination flag */
|
||||
etByte xtype = 0; /* Conversion paradigm */
|
||||
u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */
|
||||
u8 useIntern; /* Ok to use internal conversions (ex: %T) */
|
||||
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
|
||||
sqlite_uint64 longvalue; /* Value for integer types */
|
||||
LONGDOUBLE_TYPE realvalue; /* Value for real types */
|
||||
@@ -196,9 +223,18 @@ void sqlite3VXPrintf(
|
||||
etByte flag_dp; /* True if decimal point should be shown */
|
||||
etByte flag_rtz; /* True if trailing zeros should be removed */
|
||||
#endif
|
||||
PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
|
||||
char buf[etBUFSIZE]; /* Conversion buffer */
|
||||
|
||||
bufpt = 0;
|
||||
if( bFlags ){
|
||||
if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){
|
||||
pArgList = va_arg(ap, PrintfArguments*);
|
||||
}
|
||||
useIntern = bFlags & SQLITE_PRINTF_INTERNAL;
|
||||
}else{
|
||||
bArgList = useIntern = 0;
|
||||
}
|
||||
for(; (c=(*fmt))!=0; ++fmt){
|
||||
if( c!='%' ){
|
||||
int amt;
|
||||
@@ -230,7 +266,11 @@ void sqlite3VXPrintf(
|
||||
/* Get the field width */
|
||||
width = 0;
|
||||
if( c=='*' ){
|
||||
width = va_arg(ap,int);
|
||||
if( bArgList ){
|
||||
width = (int)getIntArg(pArgList);
|
||||
}else{
|
||||
width = va_arg(ap,int);
|
||||
}
|
||||
if( width<0 ){
|
||||
flag_leftjustify = 1;
|
||||
width = -width;
|
||||
@@ -247,7 +287,11 @@ void sqlite3VXPrintf(
|
||||
precision = 0;
|
||||
c = *++fmt;
|
||||
if( c=='*' ){
|
||||
precision = va_arg(ap,int);
|
||||
if( bArgList ){
|
||||
precision = (int)getIntArg(pArgList);
|
||||
}else{
|
||||
precision = va_arg(ap,int);
|
||||
}
|
||||
if( precision<0 ) precision = -precision;
|
||||
c = *++fmt;
|
||||
}else{
|
||||
@@ -278,7 +322,7 @@ void sqlite3VXPrintf(
|
||||
for(idx=0; idx<ArraySize(fmtinfo); idx++){
|
||||
if( c==fmtinfo[idx].fmttype ){
|
||||
infop = &fmtinfo[idx];
|
||||
if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
|
||||
if( useIntern || (infop->flags & FLAG_INTERN)==0 ){
|
||||
xtype = infop->type;
|
||||
}else{
|
||||
return;
|
||||
@@ -318,7 +362,9 @@ void sqlite3VXPrintf(
|
||||
case etRADIX:
|
||||
if( infop->flags & FLAG_SIGNED ){
|
||||
i64 v;
|
||||
if( flag_longlong ){
|
||||
if( bArgList ){
|
||||
v = getIntArg(pArgList);
|
||||
}else if( flag_longlong ){
|
||||
v = va_arg(ap,i64);
|
||||
}else if( flag_long ){
|
||||
v = va_arg(ap,long int);
|
||||
@@ -339,7 +385,9 @@ void sqlite3VXPrintf(
|
||||
else prefix = 0;
|
||||
}
|
||||
}else{
|
||||
if( flag_longlong ){
|
||||
if( bArgList ){
|
||||
longvalue = (u64)getIntArg(pArgList);
|
||||
}else if( flag_longlong ){
|
||||
longvalue = va_arg(ap,u64);
|
||||
}else if( flag_long ){
|
||||
longvalue = va_arg(ap,unsigned long int);
|
||||
@@ -359,7 +407,7 @@ void sqlite3VXPrintf(
|
||||
nOut = precision + 10;
|
||||
zOut = zExtra = sqlite3Malloc( nOut );
|
||||
if( zOut==0 ){
|
||||
pAccum->accError = STRACCUM_NOMEM;
|
||||
setStrAccumError(pAccum, STRACCUM_NOMEM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -399,7 +447,11 @@ void sqlite3VXPrintf(
|
||||
case etFLOAT:
|
||||
case etEXP:
|
||||
case etGENERIC:
|
||||
realvalue = va_arg(ap,double);
|
||||
if( bArgList ){
|
||||
realvalue = getDoubleArg(pArgList);
|
||||
}else{
|
||||
realvalue = va_arg(ap,double);
|
||||
}
|
||||
#ifdef SQLITE_OMIT_FLOATING_POINT
|
||||
length = 0;
|
||||
#else
|
||||
@@ -471,7 +523,7 @@ void sqlite3VXPrintf(
|
||||
if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){
|
||||
bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 );
|
||||
if( bufpt==0 ){
|
||||
pAccum->accError = STRACCUM_NOMEM;
|
||||
setStrAccumError(pAccum, STRACCUM_NOMEM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -554,7 +606,9 @@ void sqlite3VXPrintf(
|
||||
#endif /* !defined(SQLITE_OMIT_FLOATING_POINT) */
|
||||
break;
|
||||
case etSIZE:
|
||||
*(va_arg(ap,int*)) = pAccum->nChar;
|
||||
if( !bArgList ){
|
||||
*(va_arg(ap,int*)) = pAccum->nChar;
|
||||
}
|
||||
length = width = 0;
|
||||
break;
|
||||
case etPERCENT:
|
||||
@@ -563,7 +617,12 @@ void sqlite3VXPrintf(
|
||||
length = 1;
|
||||
break;
|
||||
case etCHARX:
|
||||
c = va_arg(ap,int);
|
||||
if( bArgList ){
|
||||
bufpt = getTextArg(pArgList);
|
||||
c = bufpt ? bufpt[0] : 0;
|
||||
}else{
|
||||
c = va_arg(ap,int);
|
||||
}
|
||||
buf[0] = (char)c;
|
||||
if( precision>=0 ){
|
||||
for(idx=1; idx<precision; idx++) buf[idx] = (char)c;
|
||||
@@ -575,10 +634,14 @@ void sqlite3VXPrintf(
|
||||
break;
|
||||
case etSTRING:
|
||||
case etDYNSTRING:
|
||||
bufpt = va_arg(ap,char*);
|
||||
if( bArgList ){
|
||||
bufpt = getTextArg(pArgList);
|
||||
}else{
|
||||
bufpt = va_arg(ap,char*);
|
||||
}
|
||||
if( bufpt==0 ){
|
||||
bufpt = "";
|
||||
}else if( xtype==etDYNSTRING ){
|
||||
}else if( xtype==etDYNSTRING && !bArgList ){
|
||||
zExtra = bufpt;
|
||||
}
|
||||
if( precision>=0 ){
|
||||
@@ -594,7 +657,13 @@ void sqlite3VXPrintf(
|
||||
int needQuote;
|
||||
char ch;
|
||||
char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
|
||||
char *escarg = va_arg(ap,char*);
|
||||
char *escarg;
|
||||
|
||||
if( bArgList ){
|
||||
escarg = getTextArg(pArgList);
|
||||
}else{
|
||||
escarg = va_arg(ap,char*);
|
||||
}
|
||||
isnull = escarg==0;
|
||||
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
|
||||
k = precision;
|
||||
@@ -606,7 +675,7 @@ void sqlite3VXPrintf(
|
||||
if( n>etBUFSIZE ){
|
||||
bufpt = zExtra = sqlite3Malloc( n );
|
||||
if( bufpt==0 ){
|
||||
pAccum->accError = STRACCUM_NOMEM;
|
||||
setStrAccumError(pAccum, STRACCUM_NOMEM);
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
@@ -629,7 +698,8 @@ void sqlite3VXPrintf(
|
||||
}
|
||||
case etTOKEN: {
|
||||
Token *pToken = va_arg(ap, Token*);
|
||||
if( pToken ){
|
||||
assert( bArgList==0 );
|
||||
if( pToken && pToken->n ){
|
||||
sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
|
||||
}
|
||||
length = width = 0;
|
||||
@@ -639,12 +709,13 @@ void sqlite3VXPrintf(
|
||||
SrcList *pSrc = va_arg(ap, SrcList*);
|
||||
int k = va_arg(ap, int);
|
||||
struct SrcList_item *pItem = &pSrc->a[k];
|
||||
assert( bArgList==0 );
|
||||
assert( k>=0 && k<pSrc->nSrc );
|
||||
if( pItem->zDatabase ){
|
||||
sqlite3StrAccumAppend(pAccum, pItem->zDatabase, -1);
|
||||
sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase);
|
||||
sqlite3StrAccumAppend(pAccum, ".", 1);
|
||||
}
|
||||
sqlite3StrAccumAppend(pAccum, pItem->zName, -1);
|
||||
sqlite3StrAccumAppendAll(pAccum, pItem->zName);
|
||||
length = width = 0;
|
||||
break;
|
||||
}
|
||||
@@ -675,7 +746,7 @@ void sqlite3VXPrintf(
|
||||
sqlite3AppendSpace(pAccum, nspace);
|
||||
}
|
||||
}
|
||||
sqlite3_free(zExtra);
|
||||
if( zExtra ) sqlite3_free(zExtra);
|
||||
}/* End for loop over the format string */
|
||||
} /* End of function */
|
||||
|
||||
@@ -683,22 +754,20 @@ void sqlite3VXPrintf(
|
||||
** Append N bytes of text from z to the StrAccum object.
|
||||
*/
|
||||
void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
|
||||
assert( z!=0 || N==0 );
|
||||
if( p->accError ){
|
||||
testcase(p->accError==STRACCUM_TOOBIG);
|
||||
testcase(p->accError==STRACCUM_NOMEM);
|
||||
return;
|
||||
}
|
||||
assert( p->zText!=0 || p->nChar==0 );
|
||||
if( N<=0 ){
|
||||
if( N==0 || z[0]==0 ) return;
|
||||
N = sqlite3Strlen30(z);
|
||||
}
|
||||
assert( z!=0 );
|
||||
assert( p->zText!=0 || p->nChar==0 || p->accError );
|
||||
assert( N>=0 );
|
||||
assert( p->accError==0 || p->nAlloc==0 );
|
||||
if( p->nChar+N >= p->nAlloc ){
|
||||
char *zNew;
|
||||
if( p->accError ){
|
||||
testcase(p->accError==STRACCUM_TOOBIG);
|
||||
testcase(p->accError==STRACCUM_NOMEM);
|
||||
return;
|
||||
}
|
||||
if( !p->useMalloc ){
|
||||
p->accError = STRACCUM_TOOBIG;
|
||||
N = p->nAlloc - p->nChar - 1;
|
||||
setStrAccumError(p, STRACCUM_TOOBIG);
|
||||
if( N<=0 ){
|
||||
return;
|
||||
}
|
||||
@@ -708,7 +777,7 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
|
||||
szNew += N + 1;
|
||||
if( szNew > p->mxAlloc ){
|
||||
sqlite3StrAccumReset(p);
|
||||
p->accError = STRACCUM_TOOBIG;
|
||||
setStrAccumError(p, STRACCUM_TOOBIG);
|
||||
return;
|
||||
}else{
|
||||
p->nAlloc = (int)szNew;
|
||||
@@ -722,8 +791,8 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
|
||||
if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
|
||||
p->zText = zNew;
|
||||
}else{
|
||||
p->accError = STRACCUM_NOMEM;
|
||||
sqlite3StrAccumReset(p);
|
||||
setStrAccumError(p, STRACCUM_NOMEM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -733,6 +802,14 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
|
||||
p->nChar += N;
|
||||
}
|
||||
|
||||
/*
|
||||
** Append the complete text of zero-terminated string z[] to the p string.
|
||||
*/
|
||||
void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){
|
||||
sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Finish off a string by making sure it is zero-terminated.
|
||||
** Return a pointer to the resulting string. Return a NULL
|
||||
@@ -750,7 +827,7 @@ char *sqlite3StrAccumFinish(StrAccum *p){
|
||||
if( p->zText ){
|
||||
memcpy(p->zText, p->zBase, p->nChar+1);
|
||||
}else{
|
||||
p->accError = STRACCUM_NOMEM;
|
||||
setStrAccumError(p, STRACCUM_NOMEM);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -796,7 +873,7 @@ char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
|
||||
sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
|
||||
db->aLimit[SQLITE_LIMIT_LENGTH]);
|
||||
acc.db = db;
|
||||
sqlite3VXPrintf(&acc, 1, zFormat, ap);
|
||||
sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap);
|
||||
z = sqlite3StrAccumFinish(&acc);
|
||||
if( acc.accError==STRACCUM_NOMEM ){
|
||||
db->mallocFailed = 1;
|
||||
@@ -952,14 +1029,12 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
/*
|
||||
** variable-argument wrapper around sqlite3VXPrintf().
|
||||
*/
|
||||
void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){
|
||||
void sqlite3XPrintf(StrAccum *p, u32 bFlags, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
va_start(ap,zFormat);
|
||||
sqlite3VXPrintf(p, 1, zFormat, ap);
|
||||
sqlite3VXPrintf(p, bFlags, zFormat, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#endif
|
||||
|
||||
+9
-5
@@ -52,6 +52,12 @@ void sqlite3_randomness(int N, void *pBuf){
|
||||
sqlite3_mutex_enter(mutex);
|
||||
#endif
|
||||
|
||||
if( N<=0 ){
|
||||
wsdPrng.isInit = 0;
|
||||
sqlite3_mutex_leave(mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize the state of the random number generator once,
|
||||
** the first time this routine is called. The seed value does
|
||||
** not need to contain a lot of randomness since we are not
|
||||
@@ -79,7 +85,8 @@ void sqlite3_randomness(int N, void *pBuf){
|
||||
wsdPrng.isInit = 1;
|
||||
}
|
||||
|
||||
while( N-- ){
|
||||
assert( N>0 );
|
||||
do{
|
||||
wsdPrng.i++;
|
||||
t = wsdPrng.s[wsdPrng.i];
|
||||
wsdPrng.j += t;
|
||||
@@ -87,7 +94,7 @@ void sqlite3_randomness(int N, void *pBuf){
|
||||
wsdPrng.s[wsdPrng.j] = t;
|
||||
t += wsdPrng.s[wsdPrng.i];
|
||||
*(zBuf++) = wsdPrng.s[t];
|
||||
}
|
||||
}while( --N );
|
||||
sqlite3_mutex_leave(mutex);
|
||||
}
|
||||
|
||||
@@ -116,7 +123,4 @@ void sqlite3PrngRestoreState(void){
|
||||
sizeof(sqlite3Prng)
|
||||
);
|
||||
}
|
||||
void sqlite3PrngResetState(void){
|
||||
GLOBAL(struct sqlite3PrngType, sqlite3Prng).isInit = 0;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_BUILTIN_TEST */
|
||||
|
||||
+561
-140
File diff suppressed because it is too large
Load Diff
+13
-7
@@ -597,6 +597,7 @@ static void output_c_string(FILE *out, const char *z){
|
||||
*/
|
||||
static void output_html_string(FILE *out, const char *z){
|
||||
int i;
|
||||
if( z==0 ) z = "";
|
||||
while( *z ){
|
||||
for(i=0; z[i]
|
||||
&& z[i]!='<'
|
||||
@@ -1176,7 +1177,7 @@ static int str_in_array(const char *zStr, const char **azArray){
|
||||
**
|
||||
** * For each "Goto", if the jump destination is earlier in the program
|
||||
** and ends on one of:
|
||||
** Yield SeekGt SeekLt RowSetRead
|
||||
** Yield SeekGt SeekLt RowSetRead Rewind
|
||||
** then indent all opcodes between the earlier instruction
|
||||
** and "Goto" by 2 spaces.
|
||||
*/
|
||||
@@ -1188,7 +1189,7 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
|
||||
int iOp; /* Index of operation in p->aiIndent[] */
|
||||
|
||||
const char *azNext[] = { "Next", "Prev", "VPrev", "VNext", "SorterNext", 0 };
|
||||
const char *azYield[] = { "Yield", "SeekLt", "SeekGt", "RowSetRead", 0 };
|
||||
const char *azYield[] = { "Yield", "SeekLt", "SeekGt", "RowSetRead", "Rewind", 0 };
|
||||
const char *azGoto[] = { "Goto", 0 };
|
||||
|
||||
/* Try to figure out if this is really an EXPLAIN statement. If this
|
||||
@@ -1225,7 +1226,7 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){
|
||||
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
|
||||
}
|
||||
if( str_in_array(zOp, azGoto) && p2op<p->nIndent && abYield[p2op] ){
|
||||
for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2;
|
||||
for(i=p2op+1; i<iOp; i++) p->aiIndent[i] += 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1836,7 +1837,7 @@ static void csv_append_char(CSVReader *p, int c){
|
||||
** + Report syntax errors on stderr
|
||||
*/
|
||||
static char *csv_read_one_field(CSVReader *p){
|
||||
int c, pc;
|
||||
int c, pc, ppc;
|
||||
int cSep = p->cSeparator;
|
||||
p->n = 0;
|
||||
c = fgetc(p->in);
|
||||
@@ -1847,7 +1848,7 @@ static char *csv_read_one_field(CSVReader *p){
|
||||
if( c=='"' ){
|
||||
int startLine = p->nLine;
|
||||
int cQuote = c;
|
||||
pc = 0;
|
||||
pc = ppc = 0;
|
||||
while( 1 ){
|
||||
c = fgetc(p->in);
|
||||
if( c=='\n' ) p->nLine++;
|
||||
@@ -1859,7 +1860,7 @@ static char *csv_read_one_field(CSVReader *p){
|
||||
}
|
||||
if( (c==cSep && pc==cQuote)
|
||||
|| (c=='\n' && pc==cQuote)
|
||||
|| (c=='\n' && pc=='\r' && p->n>=2 && p->z[p->n-2]==cQuote)
|
||||
|| (c=='\n' && pc=='\r' && ppc==cQuote)
|
||||
|| (c==EOF && pc==cQuote)
|
||||
){
|
||||
do{ p->n--; }while( p->z[p->n]!=cQuote );
|
||||
@@ -1877,6 +1878,7 @@ static char *csv_read_one_field(CSVReader *p){
|
||||
break;
|
||||
}
|
||||
csv_append_char(p, c);
|
||||
ppc = pc;
|
||||
pc = c;
|
||||
}
|
||||
}else{
|
||||
@@ -3037,7 +3039,10 @@ static int process_input(struct callback_data *p, FILE *in){
|
||||
seenInterrupt = 0;
|
||||
}
|
||||
lineno++;
|
||||
if( nSql==0 && _all_whitespace(zLine) ) continue;
|
||||
if( nSql==0 && _all_whitespace(zLine) ){
|
||||
if( p->echoOn ) printf("%s\n", zLine);
|
||||
continue;
|
||||
}
|
||||
if( zLine && zLine[0]=='.' && nSql==0 ){
|
||||
if( p->echoOn ) printf("%s\n", zLine);
|
||||
rc = do_meta_command(zLine, p);
|
||||
@@ -3099,6 +3104,7 @@ static int process_input(struct callback_data *p, FILE *in){
|
||||
}
|
||||
nSql = 0;
|
||||
}else if( nSql && _all_whitespace(zSql) ){
|
||||
if( p->echoOn ) printf("%s\n", zSql);
|
||||
nSql = 0;
|
||||
}
|
||||
}
|
||||
|
||||
+69
-22
@@ -486,6 +486,7 @@ int sqlite3_exec(
|
||||
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
|
||||
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
|
||||
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
|
||||
#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
|
||||
#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
|
||||
#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8))
|
||||
#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8))
|
||||
@@ -553,7 +554,8 @@ int sqlite3_exec(
|
||||
** after reboot following a crash or power loss, the only bytes in a
|
||||
** file that were written at the application level might have changed
|
||||
** and that adjacent bytes, even bytes within the same sector are
|
||||
** guaranteed to be unchanged.
|
||||
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
|
||||
** flag indicate that a file cannot be deleted when open.
|
||||
*/
|
||||
#define SQLITE_IOCAP_ATOMIC 0x00000001
|
||||
#define SQLITE_IOCAP_ATOMIC512 0x00000002
|
||||
@@ -784,15 +786,29 @@ struct sqlite3_io_methods {
|
||||
** additional information.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
|
||||
** ^(The [SQLITE_FCNTL_SYNC_OMITTED] opcode is generated internally by
|
||||
** SQLite and sent to all VFSes in place of a call to the xSync method
|
||||
** when the database connection has [PRAGMA synchronous] set to OFF.)^
|
||||
** Some specialized VFSes need this signal in order to operate correctly
|
||||
** when [PRAGMA synchronous | PRAGMA synchronous=OFF] is set, but most
|
||||
** VFSes do not need this signal and should silently ignore this opcode.
|
||||
** Applications should not call [sqlite3_file_control()] with this
|
||||
** opcode as doing so may disrupt the operation of the specialized VFSes
|
||||
** that do require it.
|
||||
** No longer in use.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_SYNC]]
|
||||
** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and
|
||||
** sent to the VFS immediately before the xSync method is invoked on a
|
||||
** database file descriptor. Or, if the xSync method is not invoked
|
||||
** because the user has configured SQLite with
|
||||
** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place
|
||||
** of the xSync method. In most cases, the pointer argument passed with
|
||||
** this file-control is NULL. However, if the database file is being synced
|
||||
** as part of a multi-database commit, the argument points to a nul-terminated
|
||||
** string containing the transactions master-journal file name. VFSes that
|
||||
** do not need this signal should silently ignore this opcode. Applications
|
||||
** should not call [sqlite3_file_control()] with this opcode as doing so may
|
||||
** disrupt the operation of the specialized VFSes that do require it.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_COMMIT_PHASETWO]]
|
||||
** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite
|
||||
** and sent to the VFS after a transaction has been committed immediately
|
||||
** but before the database is unlocked. VFSes that do not need this signal
|
||||
** should silently ignore this opcode. Applications should not call
|
||||
** [sqlite3_file_control()] with this opcode as doing so may disrupt the
|
||||
** operation of the specialized VFSes that do require it.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
|
||||
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
|
||||
@@ -916,6 +932,12 @@ struct sqlite3_io_methods {
|
||||
** SQLite stack may generate instances of this file control if
|
||||
** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_HAS_MOVED]]
|
||||
** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
|
||||
** pointer to an integer and it writes a boolean into that integer depending
|
||||
** on whether or not the file has been renamed, moved, or deleted since it
|
||||
** was first opened.
|
||||
**
|
||||
** </ul>
|
||||
*/
|
||||
#define SQLITE_FCNTL_LOCKSTATE 1
|
||||
@@ -936,6 +958,9 @@ struct sqlite3_io_methods {
|
||||
#define SQLITE_FCNTL_TEMPFILENAME 16
|
||||
#define SQLITE_FCNTL_MMAP_SIZE 18
|
||||
#define SQLITE_FCNTL_TRACE 19
|
||||
#define SQLITE_FCNTL_HAS_MOVED 20
|
||||
#define SQLITE_FCNTL_SYNC 21
|
||||
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
|
||||
|
||||
/*
|
||||
** CAPI3REF: Mutex Handle
|
||||
@@ -2370,11 +2395,13 @@ sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
|
||||
** applications to access the same PRNG for other purposes.
|
||||
**
|
||||
** ^A call to this routine stores N bytes of randomness into buffer P.
|
||||
** ^If N is less than one, then P can be a NULL pointer.
|
||||
**
|
||||
** ^The first time this routine is invoked (either internally or by
|
||||
** the application) the PRNG is seeded using randomness obtained
|
||||
** from the xRandomness method of the default [sqlite3_vfs] object.
|
||||
** ^On all subsequent invocations, the pseudo-randomness is generated
|
||||
** ^If this routine has not been previously called or if the previous
|
||||
** call had N less than one, then the PRNG is seeded using randomness
|
||||
** obtained from the xRandomness method of the default [sqlite3_vfs] object.
|
||||
** ^If the previous call to this routine had an N of 1 or more then
|
||||
** the pseudo-randomness is generated
|
||||
** internally and without recourse to the [sqlite3_vfs] xRandomness
|
||||
** method.
|
||||
*/
|
||||
@@ -2534,6 +2561,7 @@ int sqlite3_set_authorizer(
|
||||
#define SQLITE_FUNCTION 31 /* NULL Function Name */
|
||||
#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */
|
||||
#define SQLITE_COPY 0 /* No longer used */
|
||||
#define SQLITE_RECURSIVE 33 /* NULL NULL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Tracing And Profiling Functions
|
||||
@@ -3952,15 +3980,24 @@ int sqlite3_reset(sqlite3_stmt *pStmt);
|
||||
**
|
||||
** ^The fourth parameter, eTextRep, specifies what
|
||||
** [SQLITE_UTF8 | text encoding] this SQL function prefers for
|
||||
** its parameters. Every SQL function implementation must be able to work
|
||||
** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be
|
||||
** more efficient with one encoding than another. ^An application may
|
||||
** invoke sqlite3_create_function() or sqlite3_create_function16() multiple
|
||||
** times with the same function but with different values of eTextRep.
|
||||
** its parameters. The application should set this parameter to
|
||||
** [SQLITE_UTF16LE] if the function implementation invokes
|
||||
** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the
|
||||
** implementation invokes [sqlite3_value_text16be()] on an input, or
|
||||
** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8]
|
||||
** otherwise. ^The same SQL function may be registered multiple times using
|
||||
** different preferred text encodings, with different implementations for
|
||||
** each encoding.
|
||||
** ^When multiple implementations of the same function are available, SQLite
|
||||
** will pick the one that involves the least amount of data conversion.
|
||||
** If there is only a single implementation which does not care what text
|
||||
** encoding is used, then the fourth argument should be [SQLITE_ANY].
|
||||
**
|
||||
** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC]
|
||||
** to signal that the function will always return the same result given
|
||||
** the same inputs within a single SQL statement. Most SQL functions are
|
||||
** deterministic. The built-in [random()] SQL function is an example of a
|
||||
** function that is not deterministic. The SQLite query planner is able to
|
||||
** perform additional optimizations on deterministic functions, so use
|
||||
** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
|
||||
**
|
||||
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
|
||||
** function can gain access to this pointer using [sqlite3_user_data()].)^
|
||||
@@ -4046,9 +4083,19 @@ int sqlite3_create_function_v2(
|
||||
#define SQLITE_UTF16LE 2
|
||||
#define SQLITE_UTF16BE 3
|
||||
#define SQLITE_UTF16 4 /* Use native byte order */
|
||||
#define SQLITE_ANY 5 /* sqlite3_create_function only */
|
||||
#define SQLITE_ANY 5 /* Deprecated */
|
||||
#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Function Flags
|
||||
**
|
||||
** These constants may be ORed together with the
|
||||
** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
|
||||
** to [sqlite3_create_function()], [sqlite3_create_function16()], or
|
||||
** [sqlite3_create_function_v2()].
|
||||
*/
|
||||
#define SQLITE_DETERMINISTIC 0x800
|
||||
|
||||
/*
|
||||
** CAPI3REF: Deprecated Functions
|
||||
** DEPRECATED
|
||||
|
||||
+132
-24
@@ -742,6 +742,7 @@ typedef struct LookasideSlot LookasideSlot;
|
||||
typedef struct Module Module;
|
||||
typedef struct NameContext NameContext;
|
||||
typedef struct Parse Parse;
|
||||
typedef struct PrintfArguments PrintfArguments;
|
||||
typedef struct RowSet RowSet;
|
||||
typedef struct Savepoint Savepoint;
|
||||
typedef struct Select Select;
|
||||
@@ -759,6 +760,7 @@ typedef struct VTable VTable;
|
||||
typedef struct VtabCtx VtabCtx;
|
||||
typedef struct Walker Walker;
|
||||
typedef struct WhereInfo WhereInfo;
|
||||
typedef struct With With;
|
||||
|
||||
/*
|
||||
** Defer sourcing vdbe.h and btree.h until after the "u8" and
|
||||
@@ -1055,7 +1057,7 @@ struct sqlite3 {
|
||||
#define SQLITE_ColumnCache 0x0002 /* Column cache */
|
||||
#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
|
||||
#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
|
||||
#define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */
|
||||
/* not used 0x0010 // Was: SQLITE_IdxRealAsInt */
|
||||
#define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */
|
||||
#define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */
|
||||
#define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */
|
||||
@@ -1427,7 +1429,7 @@ struct Table {
|
||||
};
|
||||
|
||||
/*
|
||||
** Allowed values for Tabe.tabFlags.
|
||||
** Allowed values for Table.tabFlags.
|
||||
*/
|
||||
#define TF_Readonly 0x01 /* Read-only system table */
|
||||
#define TF_Ephemeral 0x02 /* An ephemeral table */
|
||||
@@ -1687,6 +1689,7 @@ struct AggInfo {
|
||||
int sortingIdx; /* Cursor number of the sorting index */
|
||||
int sortingIdxPTab; /* Cursor number of pseudo-table */
|
||||
int nSortingColumn; /* Number of columns in the sorting index */
|
||||
int mnReg, mxReg; /* Range of registers allocated for aCol and aFunc */
|
||||
ExprList *pGroupBy; /* The group by clause */
|
||||
struct AggInfo_col { /* For each column used in source tables */
|
||||
Table *pTab; /* Source table */
|
||||
@@ -1979,6 +1982,7 @@ typedef u64 Bitmask;
|
||||
** A bit in a Bitmask
|
||||
*/
|
||||
#define MASKBIT(n) (((Bitmask)1)<<(n))
|
||||
#define MASKBIT32(n) (((unsigned int)1)<<(n))
|
||||
|
||||
/*
|
||||
** The following structure describes the FROM clause of a SELECT statement.
|
||||
@@ -2015,6 +2019,7 @@ struct SrcList {
|
||||
unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
|
||||
unsigned isCorrelated :1; /* True if sub-query is correlated */
|
||||
unsigned viaCoroutine :1; /* Implemented as a co-routine */
|
||||
unsigned isRecursive :1; /* True for recursive reference in WITH */
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
|
||||
#endif
|
||||
@@ -2141,6 +2146,7 @@ struct Select {
|
||||
Select *pRightmost; /* Right-most select in a compound select statement */
|
||||
Expr *pLimit; /* LIMIT expression. NULL means not used. */
|
||||
Expr *pOffset; /* OFFSET expression. NULL means not used. */
|
||||
With *pWith; /* WITH clause attached to this select. Or NULL. */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2158,11 +2164,70 @@ struct Select {
|
||||
#define SF_Materialize 0x0100 /* Force materialization of views */
|
||||
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
|
||||
#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
|
||||
#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */
|
||||
|
||||
|
||||
/*
|
||||
** The results of a select can be distributed in several ways. The
|
||||
** "SRT" prefix means "SELECT Result Type".
|
||||
** The results of a SELECT can be distributed in several ways, as defined
|
||||
** by one of the following macros. The "SRT" prefix means "SELECT Result
|
||||
** Type".
|
||||
**
|
||||
** SRT_Union Store results as a key in a temporary index
|
||||
** identified by pDest->iSDParm.
|
||||
**
|
||||
** SRT_Except Remove results from the temporary index pDest->iSDParm.
|
||||
**
|
||||
** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result
|
||||
** set is not empty.
|
||||
**
|
||||
** SRT_Discard Throw the results away. This is used by SELECT
|
||||
** statements within triggers whose only purpose is
|
||||
** the side-effects of functions.
|
||||
**
|
||||
** All of the above are free to ignore their ORDER BY clause. Those that
|
||||
** follow must honor the ORDER BY clause.
|
||||
**
|
||||
** SRT_Output Generate a row of output (using the OP_ResultRow
|
||||
** opcode) for each row in the result set.
|
||||
**
|
||||
** SRT_Mem Only valid if the result is a single column.
|
||||
** Store the first column of the first result row
|
||||
** in register pDest->iSDParm then abandon the rest
|
||||
** of the query. This destination implies "LIMIT 1".
|
||||
**
|
||||
** SRT_Set The result must be a single column. Store each
|
||||
** row of result as the key in table pDest->iSDParm.
|
||||
** Apply the affinity pDest->affSdst before storing
|
||||
** results. Used to implement "IN (SELECT ...)".
|
||||
**
|
||||
** SRT_EphemTab Create an temporary table pDest->iSDParm and store
|
||||
** the result there. The cursor is left open after
|
||||
** returning. This is like SRT_Table except that
|
||||
** this destination uses OP_OpenEphemeral to create
|
||||
** the table first.
|
||||
**
|
||||
** SRT_Coroutine Generate a co-routine that returns a new row of
|
||||
** results each time it is invoked. The entry point
|
||||
** of the co-routine is stored in register pDest->iSDParm
|
||||
** and the result row is stored in pDest->nDest registers
|
||||
** starting with pDest->iSdst.
|
||||
**
|
||||
** SRT_Table Store results in temporary table pDest->iSDParm.
|
||||
** This is like SRT_EphemTab except that the table
|
||||
** is assumed to already be open.
|
||||
**
|
||||
** SRT_DistTable Store results in a temporary table pDest->iSDParm.
|
||||
** But also use temporary table pDest->iSDParm+1 as
|
||||
** a record of all prior results and ignore any duplicate
|
||||
** rows. Name means: "Distinct Table".
|
||||
**
|
||||
** SRT_Queue Store results in priority queue pDest->iSDParm (really
|
||||
** an index). Append a sequence number so that all entries
|
||||
** are distinct.
|
||||
**
|
||||
** SRT_DistQueue Store results in priority queue pDest->iSDParm only if
|
||||
** the same record has never been stored before. The
|
||||
** index at pDest->iSDParm+1 hold all prior stores.
|
||||
*/
|
||||
#define SRT_Union 1 /* Store result as keys in an index */
|
||||
#define SRT_Except 2 /* Remove result from a UNION index */
|
||||
@@ -2175,20 +2240,24 @@ struct Select {
|
||||
#define SRT_Output 5 /* Output each row of result */
|
||||
#define SRT_Mem 6 /* Store result in a memory cell */
|
||||
#define SRT_Set 7 /* Store results as keys in an index */
|
||||
#define SRT_Table 8 /* Store result as data with an automatic rowid */
|
||||
#define SRT_EphemTab 9 /* Create transient tab and store like SRT_Table */
|
||||
#define SRT_Coroutine 10 /* Generate a single row of result */
|
||||
#define SRT_EphemTab 8 /* Create transient tab and store like SRT_Table */
|
||||
#define SRT_Coroutine 9 /* Generate a single row of result */
|
||||
#define SRT_Table 10 /* Store result as data with an automatic rowid */
|
||||
#define SRT_DistTable 11 /* Like SRT_Table, but unique results only */
|
||||
#define SRT_Queue 12 /* Store result in an queue */
|
||||
#define SRT_DistQueue 13 /* Like SRT_Queue, but unique results only */
|
||||
|
||||
/*
|
||||
** An instance of this object describes where to put of the results of
|
||||
** a SELECT statement.
|
||||
*/
|
||||
struct SelectDest {
|
||||
u8 eDest; /* How to dispose of the results. On of SRT_* above. */
|
||||
char affSdst; /* Affinity used when eDest==SRT_Set */
|
||||
int iSDParm; /* A parameter used by the eDest disposal method */
|
||||
int iSdst; /* Base register where results are written */
|
||||
int nSdst; /* Number of registers allocated */
|
||||
u8 eDest; /* How to dispose of the results. On of SRT_* above. */
|
||||
char affSdst; /* Affinity used when eDest==SRT_Set */
|
||||
int iSDParm; /* A parameter used by the eDest disposal method */
|
||||
int iSdst; /* Base register where results are written */
|
||||
int nSdst; /* Number of registers allocated */
|
||||
ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2288,6 +2357,10 @@ struct Parse {
|
||||
int nMem; /* Number of memory cells used so far */
|
||||
int nSet; /* Number of sets used so far */
|
||||
int nOnce; /* Number of OP_Once instructions so far */
|
||||
int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
|
||||
int nLabel; /* Number of labels used */
|
||||
int *aLabel; /* Space to hold the labels */
|
||||
int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */
|
||||
int ckBase; /* Base register of data during check constraints */
|
||||
int iPartIdxTab; /* Table corresponding to a partial index */
|
||||
int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
|
||||
@@ -2358,6 +2431,8 @@ struct Parse {
|
||||
#endif
|
||||
Table *pZombieTab; /* List of Table objects to delete after code gen */
|
||||
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
|
||||
With *pWith; /* Current WITH clause, or NULL */
|
||||
u8 bFreeWith; /* True if pWith should be freed with parser */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2477,7 +2552,7 @@ struct TriggerStep {
|
||||
Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */
|
||||
Token target; /* Target table for DELETE, UPDATE, INSERT */
|
||||
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
|
||||
ExprList *pExprList; /* SET clause for UPDATE. VALUES clause for INSERT */
|
||||
ExprList *pExprList; /* SET clause for UPDATE. */
|
||||
IdList *pIdList; /* Column names for INSERT */
|
||||
TriggerStep *pNext; /* Next in the link-list */
|
||||
TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */
|
||||
@@ -2599,9 +2674,9 @@ struct Sqlite3Config {
|
||||
struct Walker {
|
||||
int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */
|
||||
int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */
|
||||
void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */
|
||||
Parse *pParse; /* Parser context. */
|
||||
int walkerDepth; /* Number of subqueries */
|
||||
u8 bSelectDepthFirst; /* Do subqueries first */
|
||||
union { /* Extra data for callback */
|
||||
NameContext *pNC; /* Naming context */
|
||||
int i; /* Integer value */
|
||||
@@ -2625,6 +2700,21 @@ int sqlite3WalkSelectFrom(Walker*, Select*);
|
||||
#define WRC_Prune 1 /* Omit children but continue walking siblings */
|
||||
#define WRC_Abort 2 /* Abandon the tree walk */
|
||||
|
||||
/*
|
||||
** An instance of this structure represents a set of one or more CTEs
|
||||
** (common table expressions) created by a single WITH clause.
|
||||
*/
|
||||
struct With {
|
||||
int nCte; /* Number of CTEs in the WITH clause */
|
||||
With *pOuter; /* Containing WITH clause, or NULL */
|
||||
struct Cte { /* For each CTE in the WITH clause.... */
|
||||
char *zName; /* Name of this CTE */
|
||||
ExprList *pCols; /* List of explicit column names, or NULL */
|
||||
Select *pSelect; /* The definition of this CTE */
|
||||
const char *zErr; /* Error message for circular references */
|
||||
} a[1];
|
||||
};
|
||||
|
||||
/*
|
||||
** Assuming zIn points to the first byte of a UTF-8 character,
|
||||
** advance zIn to point to the first byte of the next UTF-8 character.
|
||||
@@ -2764,10 +2854,20 @@ void sqlite3StatusSet(int, int);
|
||||
# define sqlite3IsNaN(X) 0
|
||||
#endif
|
||||
|
||||
void sqlite3VXPrintf(StrAccum*, int, const char*, va_list);
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
void sqlite3XPrintf(StrAccum*, const char*, ...);
|
||||
#endif
|
||||
/*
|
||||
** An instance of the following structure holds information about SQL
|
||||
** functions arguments that are the parameters to the printf() function.
|
||||
*/
|
||||
struct PrintfArguments {
|
||||
int nArg; /* Total number of arguments */
|
||||
int nUsed; /* Number of arguments used so far */
|
||||
sqlite3_value **apArg; /* The argument values */
|
||||
};
|
||||
|
||||
#define SQLITE_PRINTF_INTERNAL 0x01
|
||||
#define SQLITE_PRINTF_SQLFUNC 0x02
|
||||
void sqlite3VXPrintf(StrAccum*, u32, const char*, va_list);
|
||||
void sqlite3XPrintf(StrAccum*, u32, const char*, ...);
|
||||
char *sqlite3MPrintf(sqlite3*,const char*, ...);
|
||||
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
|
||||
char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
|
||||
@@ -2882,7 +2982,7 @@ void sqlite3DeleteTable(sqlite3*, Table*);
|
||||
# define sqlite3AutoincrementEnd(X)
|
||||
#endif
|
||||
int sqlite3CodeCoroutine(Parse*, Select*, SelectDest*);
|
||||
void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
|
||||
void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int);
|
||||
void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
|
||||
IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
|
||||
int sqlite3IdListIndex(IdList*,const char*);
|
||||
@@ -2957,7 +3057,6 @@ int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
|
||||
Vdbe *sqlite3GetVdbe(Parse*);
|
||||
void sqlite3PrngSaveState(void);
|
||||
void sqlite3PrngRestoreState(void);
|
||||
void sqlite3PrngResetState(void);
|
||||
void sqlite3RollbackAll(sqlite3*,int);
|
||||
void sqlite3CodeVerifySchema(Parse*, int);
|
||||
void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
|
||||
@@ -2977,7 +3076,7 @@ int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
|
||||
int sqlite3IsRowid(const char*);
|
||||
void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8);
|
||||
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*);
|
||||
int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*);
|
||||
int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
|
||||
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
|
||||
u8,u8,int,int*);
|
||||
void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
|
||||
@@ -3021,7 +3120,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, int);
|
||||
void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
|
||||
TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*);
|
||||
TriggerStep *sqlite3TriggerInsertStep(sqlite3*,Token*, IdList*,
|
||||
ExprList*,Select*,u8);
|
||||
Select*,u8);
|
||||
TriggerStep *sqlite3TriggerUpdateStep(sqlite3*,Token*,ExprList*, Expr*, u8);
|
||||
TriggerStep *sqlite3TriggerDeleteStep(sqlite3*,Token*, Expr*);
|
||||
void sqlite3DeleteTrigger(sqlite3*, Trigger*);
|
||||
@@ -3126,8 +3225,7 @@ void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
|
||||
u8 sqlite3HexToInt(int h);
|
||||
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
|
||||
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) || \
|
||||
defined(SQLITE_DEBUG_OS_TRACE)
|
||||
#if defined(SQLITE_TEST)
|
||||
const char *sqlite3ErrName(int);
|
||||
#endif
|
||||
|
||||
@@ -3157,6 +3255,7 @@ const void *sqlite3ValueText(sqlite3_value*, u8);
|
||||
int sqlite3ValueBytes(sqlite3_value*, u8);
|
||||
void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
|
||||
void(*)(void*));
|
||||
void sqlite3ValueSetNull(sqlite3_value*);
|
||||
void sqlite3ValueFree(sqlite3_value*);
|
||||
sqlite3_value *sqlite3ValueNew(sqlite3 *);
|
||||
char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
|
||||
@@ -3222,6 +3321,7 @@ int sqlite3OpenTempDatabase(Parse *);
|
||||
|
||||
void sqlite3StrAccumInit(StrAccum*, char*, int, int);
|
||||
void sqlite3StrAccumAppend(StrAccum*,const char*,int);
|
||||
void sqlite3StrAccumAppendAll(StrAccum*,const char*);
|
||||
void sqlite3AppendSpace(StrAccum*,int);
|
||||
char *sqlite3StrAccumFinish(StrAccum*);
|
||||
void sqlite3StrAccumReset(StrAccum*);
|
||||
@@ -3313,6 +3413,14 @@ const char *sqlite3JournalModename(int);
|
||||
int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
|
||||
int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_CTE
|
||||
With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*);
|
||||
void sqlite3WithDelete(sqlite3*,With*);
|
||||
void sqlite3WithPush(Parse*, With*, u8);
|
||||
#else
|
||||
#define sqlite3WithPush(x,y,z)
|
||||
#define sqlite3WithDelete(x,y)
|
||||
#endif
|
||||
|
||||
/* Declarations for functions in fkey.c. All of these are replaced by
|
||||
** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
|
||||
|
||||
+13
-13
@@ -873,7 +873,7 @@ static int auth_callback(
|
||||
const char *zArg3,
|
||||
const char *zArg4
|
||||
){
|
||||
char *zCode;
|
||||
const char *zCode;
|
||||
Tcl_DString str;
|
||||
int rc;
|
||||
const char *zReply;
|
||||
@@ -914,6 +914,7 @@ static int auth_callback(
|
||||
case SQLITE_DROP_VTABLE : zCode="SQLITE_DROP_VTABLE"; break;
|
||||
case SQLITE_FUNCTION : zCode="SQLITE_FUNCTION"; break;
|
||||
case SQLITE_SAVEPOINT : zCode="SQLITE_SAVEPOINT"; break;
|
||||
case SQLITE_RECURSIVE : zCode="SQLITE_RECURSIVE"; break;
|
||||
default : zCode="????"; break;
|
||||
}
|
||||
Tcl_DStringInit(&str);
|
||||
@@ -998,7 +999,7 @@ static int DbTransPostCmd(
|
||||
Tcl_Interp *interp, /* Tcl interpreter */
|
||||
int result /* Result of evaluating SCRIPT */
|
||||
){
|
||||
static const char *azEnd[] = {
|
||||
static const char *const azEnd[] = {
|
||||
"RELEASE _tcl_transaction", /* rc==TCL_ERROR, nTransaction!=0 */
|
||||
"COMMIT", /* rc!=TCL_ERROR, nTransaction==0 */
|
||||
"ROLLBACK TO _tcl_transaction ; RELEASE _tcl_transaction",
|
||||
@@ -1530,9 +1531,9 @@ static int DbUseNre(void){
|
||||
*/
|
||||
# define SQLITE_TCL_NRE 0
|
||||
# define DbUseNre() 0
|
||||
# define Tcl_NRAddCallback(a,b,c,d,e,f) 0
|
||||
# define Tcl_NRAddCallback(a,b,c,d,e,f) (void)0
|
||||
# define Tcl_NREvalObj(a,b,c) 0
|
||||
# define Tcl_NRCreateCommand(a,b,c,d,e,f) 0
|
||||
# define Tcl_NRCreateCommand(a,b,c,d,e,f) (void)0
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -1936,7 +1937,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
Tcl_AppendResult(interp, pDb->zCommit, 0);
|
||||
}
|
||||
}else{
|
||||
char *zCommit;
|
||||
const char *zCommit;
|
||||
int len;
|
||||
if( pDb->zCommit ){
|
||||
Tcl_Free(pDb->zCommit);
|
||||
@@ -2009,14 +2010,14 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
char *zSql; /* An SQL statement */
|
||||
char *zLine; /* A single line of input from the file */
|
||||
char **azCol; /* zLine[] broken up into columns */
|
||||
char *zCommit; /* How to commit changes */
|
||||
const char *zCommit; /* How to commit changes */
|
||||
FILE *in; /* The input file */
|
||||
int lineno = 0; /* Line number of input file */
|
||||
char zLineNum[80]; /* Line number print buffer */
|
||||
Tcl_Obj *pResult; /* interp result */
|
||||
|
||||
char *zSep;
|
||||
char *zNull;
|
||||
const char *zSep;
|
||||
const char *zNull;
|
||||
if( objc<5 || objc>7 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv,
|
||||
"CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?");
|
||||
@@ -2770,7 +2771,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
** or savepoint. */
|
||||
if( DbUseNre() ){
|
||||
Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0);
|
||||
Tcl_NREvalObj(interp, pScript, 0);
|
||||
(void)Tcl_NREvalObj(interp, pScript, 0);
|
||||
}else{
|
||||
rc = DbTransPostCmd(&cd, interp, Tcl_EvalObjEx(interp, pScript, 0));
|
||||
}
|
||||
@@ -2934,7 +2935,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
if( objc==2 ){
|
||||
zArg = Tcl_GetStringFromObj(objv[1], 0);
|
||||
if( strcmp(zArg,"-version")==0 ){
|
||||
Tcl_AppendResult(interp,sqlite3_version,0);
|
||||
Tcl_AppendResult(interp,sqlite3_libversion(),0);
|
||||
return TCL_OK;
|
||||
}
|
||||
if( strcmp(zArg,"-has-codec")==0 ){
|
||||
@@ -3016,7 +3017,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
||||
zErrMsg = 0;
|
||||
p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
|
||||
if( p==0 ){
|
||||
Tcl_SetResult(interp, "malloc failed", TCL_STATIC);
|
||||
Tcl_SetResult(interp, (char *)"malloc failed", TCL_STATIC);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
memset(p, 0, sizeof(*p));
|
||||
@@ -3371,8 +3372,7 @@ static void MD5Final(unsigned char digest[16], MD5Context *ctx){
|
||||
byteReverse(ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
((uint32 *)ctx->in)[ 14 ] = ctx->bits[0];
|
||||
((uint32 *)ctx->in)[ 15 ] = ctx->bits[1];
|
||||
memcpy(ctx->in + 14*4, ctx->bits, 8);
|
||||
|
||||
MD5Transform(ctx->buf, (uint32 *)ctx->in);
|
||||
byteReverse((unsigned char *)ctx->buf, 4);
|
||||
|
||||
+54
-8
@@ -242,7 +242,28 @@ static int test_io_trace(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Usage: clang_sanitize_address
|
||||
**
|
||||
** Returns true if the program was compiled using clang with the
|
||||
** -fsanitize=address switch on the command line. False otherwise.
|
||||
*/
|
||||
static int clang_sanitize_address(
|
||||
void *NotUsed,
|
||||
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
||||
int argc, /* Number of arguments */
|
||||
char **argv /* Text of each argument */
|
||||
){
|
||||
int res = 0;
|
||||
#if defined(__has_feature)
|
||||
# if __has_feature(address_sanitizer)
|
||||
res = 1;
|
||||
# endif
|
||||
#endif
|
||||
Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_exec_printf DB FORMAT STRING
|
||||
**
|
||||
@@ -942,9 +963,21 @@ static void ptrChngFunction(
|
||||
sqlite3_result_int(context, p1!=p2);
|
||||
}
|
||||
|
||||
/*
|
||||
** This SQL function returns a different answer each time it is called, even if
|
||||
** the arguments are the same.
|
||||
*/
|
||||
static void nondeterministicFunction(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
static int cnt = 0;
|
||||
sqlite3_result_int(context, cnt++);
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite_test_create_function DB
|
||||
** Usage: sqlite3_create_function DB
|
||||
**
|
||||
** Call the sqlite3_create_function API on the given database in order
|
||||
** to create a function named "x_coalesce". This function does the same thing
|
||||
@@ -973,16 +1006,16 @@ static int test_create_function(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
|
||||
rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
|
||||
rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0,
|
||||
t1_ifnullFunc, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "hex8", 1, SQLITE_ANY, 0,
|
||||
hex8Func, 0, 0);
|
||||
rc = sqlite3_create_function(db, "hex8", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
|
||||
0, hex8Func, 0, 0);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "hex16", 1, SQLITE_ANY, 0,
|
||||
hex16Func, 0, 0);
|
||||
rc = sqlite3_create_function(db, "hex16", 1, SQLITE_UTF16 | SQLITE_DETERMINISTIC,
|
||||
0, hex16Func, 0, 0);
|
||||
}
|
||||
#endif
|
||||
if( rc==SQLITE_OK ){
|
||||
@@ -994,6 +1027,19 @@ static int test_create_function(
|
||||
ptrChngFunction, 0, 0);
|
||||
}
|
||||
|
||||
/* Functions counter1() and counter2() have the same implementation - they
|
||||
** both return an ascending integer with each call. But counter1() is marked
|
||||
** as non-deterministic and counter2() is marked as deterministic.
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "counter1", -1, SQLITE_UTF8,
|
||||
0, nondeterministicFunction, 0, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "counter2", -1, SQLITE_UTF8|SQLITE_DETERMINISTIC,
|
||||
0, nondeterministicFunction, 0, 0);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
/* Use the sqlite3_create_function16() API here. Mainly for fun, but also
|
||||
** because it is not tested anywhere else. */
|
||||
@@ -6135,7 +6181,6 @@ static int optimization_control(
|
||||
{ "column-cache", SQLITE_ColumnCache },
|
||||
{ "groupby-order", SQLITE_GroupByOrder },
|
||||
{ "factor-constants", SQLITE_FactorOutConst },
|
||||
{ "real-as-int", SQLITE_IdxRealAsInt },
|
||||
{ "distinct-opt", SQLITE_DistinctOpt },
|
||||
{ "cover-idx-scan", SQLITE_CoverIdxScan },
|
||||
{ "order-by-idx-join", SQLITE_OrderByIdxJoin },
|
||||
@@ -6299,6 +6344,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout },
|
||||
{ "printf", (Tcl_CmdProc*)test_printf },
|
||||
{ "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace },
|
||||
{ "clang_sanitize_address", (Tcl_CmdProc*)clang_sanitize_address },
|
||||
};
|
||||
static struct {
|
||||
char *zName;
|
||||
|
||||
+6
-7
@@ -173,9 +173,6 @@ static void *crash_realloc(void *p, int n){
|
||||
static int writeDbFile(CrashFile *p, u8 *z, i64 iAmt, i64 iOff){
|
||||
int rc = SQLITE_OK;
|
||||
int iSkip = 0;
|
||||
if( iOff==PENDING_BYTE && (p->flags&SQLITE_OPEN_MAIN_DB) ){
|
||||
iSkip = 512;
|
||||
}
|
||||
if( (iAmt-iSkip)>0 ){
|
||||
rc = sqlite3OsWrite(p->pRealFile, &z[iSkip], (int)(iAmt-iSkip), iOff+iSkip);
|
||||
}
|
||||
@@ -409,13 +406,17 @@ static int cfRead(
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
CrashFile *pCrash = (CrashFile *)pFile;
|
||||
int nCopy = (int)MIN((i64)iAmt, (pCrash->iSize - iOfst));
|
||||
|
||||
if( nCopy>0 ){
|
||||
memcpy(zBuf, &pCrash->zData[iOfst], nCopy);
|
||||
}
|
||||
|
||||
/* Check the file-size to see if this is a short-read */
|
||||
if( pCrash->iSize<(iOfst+iAmt) ){
|
||||
if( nCopy<iAmt ){
|
||||
return SQLITE_IOERR_SHORT_READ;
|
||||
}
|
||||
|
||||
memcpy(zBuf, &pCrash->zData[iOfst], iAmt);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -632,14 +633,12 @@ static int cfOpen(
|
||||
** UPDATE: It also contains an assert() verifying that each call
|
||||
** to the xRead() method reads less than 128KB of data.
|
||||
*/
|
||||
const int isDb = (flags&SQLITE_OPEN_MAIN_DB);
|
||||
i64 iOff;
|
||||
|
||||
memset(pWrapper->zData, 0, pWrapper->nData);
|
||||
for(iOff=0; iOff<pWrapper->iSize; iOff += 512){
|
||||
int nRead = (int)(pWrapper->iSize - iOff);
|
||||
if( nRead>512 ) nRead = 512;
|
||||
if( isDb && iOff==PENDING_BYTE ) continue;
|
||||
rc = sqlite3OsRead(pReal, &pWrapper->zData[iOff], nRead, iOff);
|
||||
}
|
||||
}else{
|
||||
|
||||
+1
-1
@@ -892,7 +892,7 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
pIdxInfo->estimatedCost = cost;
|
||||
}else if( useIdx ){
|
||||
/* Approximation of log2(nRow). */
|
||||
for( ii=0; ii<(sizeof(int)*8); ii++ ){
|
||||
for( ii=0; ii<(sizeof(int)*8)-1; ii++ ){
|
||||
if( nRow & (1<<ii) ){
|
||||
pIdxInfo->estimatedCost = (double)ii;
|
||||
}
|
||||
|
||||
@@ -225,6 +225,12 @@ static void set_options(Tcl_Interp *interp){
|
||||
Tcl_SetVar2(interp, "sqlite_options", "check", "1", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_OMIT_CTE
|
||||
Tcl_SetVar2(interp, "sqlite_options", "cte", "0", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
Tcl_SetVar2(interp, "sqlite_options", "cte", "1", TCL_GLOBAL_ONLY);
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||
Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "1", TCL_GLOBAL_ONLY);
|
||||
#else
|
||||
|
||||
@@ -258,6 +258,11 @@ static void vfstrace_print_errcode(
|
||||
case SQLITE_IOERR_SHMOPEN: zVal = "SQLITE_IOERR_SHMOPEN"; break;
|
||||
case SQLITE_IOERR_SHMSIZE: zVal = "SQLITE_IOERR_SHMSIZE"; break;
|
||||
case SQLITE_IOERR_SHMLOCK: zVal = "SQLITE_IOERR_SHMLOCK"; break;
|
||||
case SQLITE_IOERR_SHMMAP: zVal = "SQLITE_IOERR_SHMMAP"; break;
|
||||
case SQLITE_IOERR_SEEK: zVal = "SQLITE_IOERR_SEEK"; break;
|
||||
case SQLITE_IOERR_GETTEMPPATH: zVal = "SQLITE_IOERR_GETTEMPPATH"; break;
|
||||
case SQLITE_IOERR_CONVPATH: zVal = "SQLITE_IOERR_CONVPATH"; break;
|
||||
case SQLITE_READONLY_DBMOVED: zVal = "SQLITE_READONLY_DBMOVED"; break;
|
||||
case SQLITE_LOCKED_SHAREDCACHE: zVal = "SQLITE_LOCKED_SHAREDCACHE"; break;
|
||||
case SQLITE_BUSY_RECOVERY: zVal = "SQLITE_BUSY_RECOVERY"; break;
|
||||
case SQLITE_CANTOPEN_NOTEMPDIR: zVal = "SQLITE_CANTOPEN_NOTEMPDIR"; break;
|
||||
|
||||
+4
-12
@@ -303,24 +303,15 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
|
||||
for(i=1; sqlite3Isdigit(z[i]); i++){}
|
||||
return i;
|
||||
}
|
||||
case '#': {
|
||||
for(i=1; sqlite3Isdigit(z[i]); i++){}
|
||||
if( i>1 ){
|
||||
/* Parameters of the form #NNN (where NNN is a number) are used
|
||||
** internally by sqlite3NestedParse. */
|
||||
*tokenType = TK_REGISTER;
|
||||
return i;
|
||||
}
|
||||
/* Fall through into the next case if the '#' is not followed by
|
||||
** a digit. Try to match #AAAA where AAAA is a parameter name. */
|
||||
}
|
||||
#ifndef SQLITE_OMIT_TCL_VARIABLE
|
||||
case '$':
|
||||
#endif
|
||||
case '@': /* For compatibility with MS SQL Server */
|
||||
case '#':
|
||||
case ':': {
|
||||
int n = 0;
|
||||
testcase( z[0]=='$' ); testcase( z[0]=='@' ); testcase( z[0]==':' );
|
||||
testcase( z[0]=='$' ); testcase( z[0]=='@' );
|
||||
testcase( z[0]==':' ); testcase( z[0]=='#' );
|
||||
*tokenType = TK_VARIABLE;
|
||||
for(i=1; (c=z[i])!=0; i++){
|
||||
if( IdChar(c) ){
|
||||
@@ -503,6 +494,7 @@ abort_parse:
|
||||
sqlite3DeleteTable(db, pParse->pNewTable);
|
||||
}
|
||||
|
||||
if( pParse->bFreeWith ) sqlite3WithDelete(db, pParse->pWith);
|
||||
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
|
||||
for(i=pParse->nzVar-1; i>=0; i--) sqlite3DbFree(db, pParse->azVar[i]);
|
||||
sqlite3DbFree(db, pParse->azVar);
|
||||
|
||||
+1
-6
@@ -397,25 +397,21 @@ TriggerStep *sqlite3TriggerInsertStep(
|
||||
sqlite3 *db, /* The database connection */
|
||||
Token *pTableName, /* Name of the table into which we insert */
|
||||
IdList *pColumn, /* List of columns in pTableName to insert into */
|
||||
ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
|
||||
Select *pSelect, /* A SELECT statement that supplies values */
|
||||
u8 orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
|
||||
){
|
||||
TriggerStep *pTriggerStep;
|
||||
|
||||
assert(pEList == 0 || pSelect == 0);
|
||||
assert(pEList != 0 || pSelect != 0 || db->mallocFailed);
|
||||
assert(pSelect != 0 || db->mallocFailed);
|
||||
|
||||
pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName);
|
||||
if( pTriggerStep ){
|
||||
pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
|
||||
pTriggerStep->pIdList = pColumn;
|
||||
pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
|
||||
pTriggerStep->orconf = orconf;
|
||||
}else{
|
||||
sqlite3IdListDelete(db, pColumn);
|
||||
}
|
||||
sqlite3ExprListDelete(db, pEList);
|
||||
sqlite3SelectDelete(db, pSelect);
|
||||
|
||||
return pTriggerStep;
|
||||
@@ -753,7 +749,6 @@ static int codeTriggerProgram(
|
||||
case TK_INSERT: {
|
||||
sqlite3Insert(pParse,
|
||||
targetSrcList(pParse, pStep),
|
||||
sqlite3ExprListDup(db, pStep->pExprList, 0),
|
||||
sqlite3SelectDup(db, pStep->pSelect, 0),
|
||||
sqlite3IdListDup(db, pStep->pIdList),
|
||||
pParse->eOrconf
|
||||
|
||||
+8
-5
@@ -72,7 +72,7 @@ void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
|
||||
sqlite3VdbeChangeP4(v, -1, (const char *)pValue, P4_MEM);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
if( iReg>=0 && pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
|
||||
if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
|
||||
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
|
||||
}
|
||||
#endif
|
||||
@@ -467,9 +467,10 @@ void sqlite3Update(
|
||||
);
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( oldmask==0xffffffff
|
||||
|| (i<32 && (oldmask & (1<<i)))
|
||||
|| (i<32 && (oldmask & MASKBIT32(i))!=0)
|
||||
|| (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
|
||||
){
|
||||
testcase( oldmask!=0xffffffff && i==31 );
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
|
||||
@@ -496,15 +497,15 @@ void sqlite3Update(
|
||||
newmask = sqlite3TriggerColmask(
|
||||
pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
|
||||
);
|
||||
sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);
|
||||
/*sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);*/
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( i==pTab->iPKey ){
|
||||
/*sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);*/
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
|
||||
}else{
|
||||
j = aXRef[i];
|
||||
if( j>=0 ){
|
||||
sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
|
||||
}else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){
|
||||
}else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
|
||||
/* This branch loads the value of a column that will not be changed
|
||||
** into a register. This is done if there are no BEFORE triggers, or
|
||||
** if there are one or more BEFORE triggers that use this value via
|
||||
@@ -513,6 +514,8 @@ void sqlite3Update(
|
||||
testcase( i==31 );
|
||||
testcase( i==32 );
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-13
@@ -115,18 +115,17 @@ int sqlite3Strlen30(const char *z){
|
||||
** to NULL.
|
||||
*/
|
||||
void sqlite3Error(sqlite3 *db, int err_code, const char *zFormat, ...){
|
||||
if( db && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){
|
||||
db->errCode = err_code;
|
||||
if( zFormat ){
|
||||
char *z;
|
||||
va_list ap;
|
||||
va_start(ap, zFormat);
|
||||
z = sqlite3VMPrintf(db, zFormat, ap);
|
||||
va_end(ap);
|
||||
sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
|
||||
}else{
|
||||
sqlite3ValueSetStr(db->pErr, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
|
||||
}
|
||||
assert( db!=0 );
|
||||
db->errCode = err_code;
|
||||
if( zFormat && (db->pErr || (db->pErr = sqlite3ValueNew(db))!=0) ){
|
||||
char *z;
|
||||
va_list ap;
|
||||
va_start(ap, zFormat);
|
||||
z = sqlite3VMPrintf(db, zFormat, ap);
|
||||
va_end(ap);
|
||||
sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
|
||||
}else if( db->pErr ){
|
||||
sqlite3ValueSetNull(db->pErr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1002,7 +1001,8 @@ int sqlite3VarintLen(u64 v){
|
||||
** Read or write a four-byte big-endian integer value.
|
||||
*/
|
||||
u32 sqlite3Get4byte(const u8 *p){
|
||||
return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
|
||||
testcase( p[0]&0x80 );
|
||||
return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
|
||||
}
|
||||
void sqlite3Put4byte(unsigned char *p, u32 v){
|
||||
p[0] = (u8)(v>>24);
|
||||
|
||||
+54
-34
@@ -1111,7 +1111,7 @@ case OP_Move: {
|
||||
}
|
||||
|
||||
/* Opcode: Copy P1 P2 P3 * *
|
||||
** Synopsis: r[P2@P3]=r[P1@P3]
|
||||
** Synopsis: r[P2@P3+1]=r[P1@P3+1]
|
||||
**
|
||||
** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
|
||||
**
|
||||
@@ -2454,7 +2454,7 @@ case OP_Column: {
|
||||
VdbeMemRelease(pDest);
|
||||
sqlite3VdbeSerialGet(pC->aRow+aOffset[p2], aType[p2], pDest);
|
||||
}else{
|
||||
/* This branch happens only when content is on overflow pages */
|
||||
/* This branch happens only when content is on overflow pages */
|
||||
t = aType[p2];
|
||||
if( ((pOp->p5 & (OPFLAG_LENGTHARG|OPFLAG_TYPEOFARG))!=0
|
||||
&& ((t>=12 && (t&1)==0) || (pOp->p5 & OPFLAG_TYPEOFARG)!=0))
|
||||
@@ -2496,7 +2496,7 @@ case OP_Column: {
|
||||
pDest->enc = encoding;
|
||||
|
||||
op_column_out:
|
||||
rc = sqlite3VdbeMemMakeWriteable(pDest);
|
||||
Deephemeralize(pDest);
|
||||
op_column_error:
|
||||
UPDATE_MAX_BLOBSIZE(pDest);
|
||||
REGISTER_TRACE(pOp->p3, pDest);
|
||||
@@ -2560,7 +2560,8 @@ case OP_MakeRecord: {
|
||||
int nField; /* Number of fields in the record */
|
||||
char *zAffinity; /* The affinity string for the record */
|
||||
int file_format; /* File format to use for encoding */
|
||||
int i; /* Space used in zNewRecord[] */
|
||||
int i; /* Space used in zNewRecord[] header */
|
||||
int j; /* Space used in zNewRecord[] content */
|
||||
int len; /* Length of a field */
|
||||
|
||||
/* Assuming the record contains N fields, the record format looks
|
||||
@@ -2594,36 +2595,51 @@ case OP_MakeRecord: {
|
||||
pOut = &aMem[pOp->p3];
|
||||
memAboutToChange(p, pOut);
|
||||
|
||||
/* Apply the requested affinity to all inputs
|
||||
*/
|
||||
assert( pData0<=pLast );
|
||||
if( zAffinity ){
|
||||
pRec = pData0;
|
||||
do{
|
||||
applyAffinity(pRec, *(zAffinity++), encoding);
|
||||
}while( (++pRec)<=pLast );
|
||||
}
|
||||
|
||||
/* Loop through the elements that will make up the record to figure
|
||||
** out how much space is required for the new record.
|
||||
*/
|
||||
for(pRec=pData0; pRec<=pLast; pRec++){
|
||||
pRec = pLast;
|
||||
do{
|
||||
assert( memIsValid(pRec) );
|
||||
if( zAffinity ){
|
||||
applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
|
||||
}
|
||||
if( pRec->flags&MEM_Zero && pRec->n>0 ){
|
||||
sqlite3VdbeMemExpandBlob(pRec);
|
||||
}
|
||||
serial_type = sqlite3VdbeSerialType(pRec, file_format);
|
||||
len = sqlite3VdbeSerialTypeLen(serial_type);
|
||||
nData += len;
|
||||
nHdr += sqlite3VarintLen(serial_type);
|
||||
if( pRec->flags & MEM_Zero ){
|
||||
/* Only pure zero-filled BLOBs can be input to this Opcode.
|
||||
** We do not allow blobs with a prefix and a zero-filled tail. */
|
||||
nZero += pRec->u.nZero;
|
||||
}else if( len ){
|
||||
nZero = 0;
|
||||
if( nData ){
|
||||
sqlite3VdbeMemExpandBlob(pRec);
|
||||
}else{
|
||||
nZero += pRec->u.nZero;
|
||||
len -= pRec->u.nZero;
|
||||
}
|
||||
}
|
||||
}
|
||||
nData += len;
|
||||
testcase( serial_type==127 );
|
||||
testcase( serial_type==128 );
|
||||
nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
|
||||
}while( (--pRec)>=pData0 );
|
||||
|
||||
/* Add the initial header varint and total the size */
|
||||
nHdr += nVarint = sqlite3VarintLen(nHdr);
|
||||
if( nVarint<sqlite3VarintLen(nHdr) ){
|
||||
nHdr++;
|
||||
testcase( nHdr==126 );
|
||||
testcase( nHdr==127 );
|
||||
if( nHdr<=126 ){
|
||||
/* The common case */
|
||||
nHdr += 1;
|
||||
}else{
|
||||
/* Rare case of a really large header */
|
||||
nVarint = sqlite3VarintLen(nHdr);
|
||||
nHdr += nVarint;
|
||||
if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++;
|
||||
}
|
||||
nByte = nHdr+nData-nZero;
|
||||
nByte = nHdr+nData;
|
||||
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
goto too_big;
|
||||
}
|
||||
@@ -2640,14 +2656,16 @@ case OP_MakeRecord: {
|
||||
|
||||
/* Write the record */
|
||||
i = putVarint32(zNewRecord, nHdr);
|
||||
for(pRec=pData0; pRec<=pLast; pRec++){
|
||||
j = nHdr;
|
||||
assert( pData0<=pLast );
|
||||
pRec = pData0;
|
||||
do{
|
||||
serial_type = sqlite3VdbeSerialType(pRec, file_format);
|
||||
i += putVarint32(&zNewRecord[i], serial_type); /* serial type */
|
||||
}
|
||||
for(pRec=pData0; pRec<=pLast; pRec++){ /* serial data */
|
||||
i += sqlite3VdbeSerialPut(&zNewRecord[i], (int)(nByte-i), pRec,file_format);
|
||||
}
|
||||
assert( i==nByte );
|
||||
i += putVarint32(&zNewRecord[i], serial_type); /* serial type */
|
||||
j += sqlite3VdbeSerialPut(&zNewRecord[j], pRec, serial_type); /* content */
|
||||
}while( (++pRec)<=pLast );
|
||||
assert( i==nHdr );
|
||||
assert( j==nByte );
|
||||
|
||||
assert( pOp->p3>0 && pOp->p3<=(p->nMem-p->nCursor) );
|
||||
pOut->n = (int)nByte;
|
||||
@@ -2676,6 +2694,7 @@ case OP_Count: { /* out2-prerelease */
|
||||
|
||||
pCrsr = p->apCsr[pOp->p1]->pCursor;
|
||||
assert( pCrsr );
|
||||
nEntry = 0; /* Not needed. Only used to silence a warning. */
|
||||
rc = sqlite3BtreeCount(pCrsr, &nEntry);
|
||||
pOut->u.i = nEntry;
|
||||
break;
|
||||
@@ -3696,7 +3715,6 @@ case OP_Found: { /* jump, in3 */
|
||||
if( pOp->opcode!=OP_NoConflict ) sqlite3_found_count++;
|
||||
#endif
|
||||
|
||||
alreadyExists = 0;
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
assert( pOp->p4type==P4_INT32 );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
@@ -3704,6 +3722,7 @@ case OP_Found: { /* jump, in3 */
|
||||
pIn3 = &aMem[pOp->p3];
|
||||
assert( pC->pCursor!=0 );
|
||||
assert( pC->isTable==0 );
|
||||
pFree = 0; /* Not needed. Only used to suppress a compiler warning. */
|
||||
if( pOp->p4.i>0 ){
|
||||
r.pKeyInfo = pC->pKeyInfo;
|
||||
r.nField = (u16)pOp->p4.i;
|
||||
@@ -4347,7 +4366,6 @@ case OP_NullRow: {
|
||||
pC->nullRow = 1;
|
||||
pC->rowidIsValid = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
assert( pC->pCursor || pC->pVtabCursor );
|
||||
if( pC->pCursor ){
|
||||
sqlite3BtreeClearCursor(pC->pCursor);
|
||||
}
|
||||
@@ -4636,6 +4654,7 @@ case OP_IdxRowid: { /* out2-prerelease */
|
||||
assert( pC->deferredMoveto==0 );
|
||||
assert( pC->isTable==0 );
|
||||
if( !pC->nullRow ){
|
||||
rowid = 0; /* Not needed. Only used to silence a warning. */
|
||||
rc = sqlite3VdbeIdxRowid(db, pCrsr, &rowid);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto abort_due_to_error;
|
||||
@@ -4699,6 +4718,7 @@ case OP_IdxGE: { /* jump */
|
||||
#ifdef SQLITE_DEBUG
|
||||
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
|
||||
#endif
|
||||
res = 0; /* Not needed. Only used to silence a warning. */
|
||||
rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res);
|
||||
if( pOp->opcode==OP_IdxLT ){
|
||||
res = -res;
|
||||
@@ -4759,6 +4779,7 @@ case OP_Destroy: { /* out2-prerelease */
|
||||
iDb = pOp->p3;
|
||||
assert( iCnt==1 );
|
||||
assert( (p->btreeMask & (((yDbMask)1)<<iDb))!=0 );
|
||||
iMoved = 0; /* Not needed. Only to silence a warning. */
|
||||
rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
|
||||
pOut->flags = MEM_Int;
|
||||
pOut->u.i = iMoved;
|
||||
@@ -5331,7 +5352,6 @@ case OP_FkIfZero: { /* jump */
|
||||
** an integer.
|
||||
*/
|
||||
case OP_MemMax: { /* in2 */
|
||||
Mem *pIn1;
|
||||
VdbeFrame *pFrame;
|
||||
if( p->pFrame ){
|
||||
for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
|
||||
@@ -6154,7 +6174,7 @@ case OP_Trace: {
|
||||
if( zTrace ){
|
||||
int i;
|
||||
for(i=0; i<db->nDb; i++){
|
||||
if( ((1<<i) & p->btreeMask)==0 ) continue;
|
||||
if( MASKBIT(i) & p->btreeMask)==0 ) continue;
|
||||
sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -160,7 +160,7 @@ typedef struct VdbeOpList VdbeOpList;
|
||||
** Prototypes for the VDBE interface. See comments on the implementation
|
||||
** for a description of what each of these routines does.
|
||||
*/
|
||||
Vdbe *sqlite3VdbeCreate(sqlite3*);
|
||||
Vdbe *sqlite3VdbeCreate(Parse*);
|
||||
int sqlite3VdbeAddOp0(Vdbe*,int);
|
||||
int sqlite3VdbeAddOp1(Vdbe*,int,int);
|
||||
int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
|
||||
@@ -175,6 +175,7 @@ void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
|
||||
void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
|
||||
void sqlite3VdbeJumpHere(Vdbe*, int addr);
|
||||
void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
|
||||
int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
|
||||
void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
|
||||
void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
|
||||
void sqlite3VdbeUsesBtree(Vdbe*, int);
|
||||
|
||||
+3
-5
@@ -312,12 +312,9 @@ struct Vdbe {
|
||||
Mem **apArg; /* Arguments to currently executing user function */
|
||||
Mem *aColName; /* Column names to return */
|
||||
Mem *pResultSet; /* Pointer to an array of results */
|
||||
Parse *pParse; /* Parsing context used to create this Vdbe */
|
||||
int nMem; /* Number of memory locations currently allocated */
|
||||
int nOp; /* Number of instructions in the program */
|
||||
int nOpAlloc; /* Number of slots allocated for aOp[] */
|
||||
int nLabel; /* Number of labels used */
|
||||
int *aLabel; /* Space to hold the labels */
|
||||
u16 nResColumn; /* Number of columns in one row of the result set */
|
||||
int nCursor; /* Number of slots in apCsr[] */
|
||||
u32 magic; /* Magic number for sanity checking */
|
||||
char *zErrMsg; /* Error message written here */
|
||||
@@ -330,6 +327,7 @@ struct Vdbe {
|
||||
u32 cacheCtr; /* VdbeCursor row cache generation counter */
|
||||
int pc; /* The program counter */
|
||||
int rc; /* Value to return */
|
||||
u16 nResColumn; /* Number of columns in one row of the result set */
|
||||
u8 errorAction; /* Recovery action to do in case of an error */
|
||||
u8 minWriteFileFormat; /* Minimum file format for writable database files */
|
||||
bft explain:2; /* True if EXPLAIN present on SQL command */
|
||||
@@ -389,7 +387,7 @@ void sqlite3VdbePrintOp(FILE*, int, Op*);
|
||||
#endif
|
||||
u32 sqlite3VdbeSerialTypeLen(u32);
|
||||
u32 sqlite3VdbeSerialType(Mem*, int);
|
||||
u32 sqlite3VdbeSerialPut(unsigned char*, int, Mem*, int);
|
||||
u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
|
||||
u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
|
||||
void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
|
||||
|
||||
|
||||
+2
-1
@@ -486,7 +486,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){
|
||||
v->doingRerun = 1;
|
||||
assert( v->expired==0 );
|
||||
}
|
||||
if( rc2!=SQLITE_OK && ALWAYS(v->isPrepareV2) && ALWAYS(db->pErr) ){
|
||||
if( rc2!=SQLITE_OK ){
|
||||
/* This case occurs after failing to recompile an sql statement.
|
||||
** The error message from the SQL compiler has already been loaded
|
||||
** into the database handle. This block copies the error message
|
||||
@@ -496,6 +496,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){
|
||||
** sqlite3_errmsg() and sqlite3_errcode().
|
||||
*/
|
||||
const char *zErr = (const char *)sqlite3_value_text(db->pErr);
|
||||
assert( zErr!=0 || db->mallocFailed );
|
||||
sqlite3DbFree(db, v->zErrMsg);
|
||||
if( !db->mallocFailed ){
|
||||
v->zErrMsg = sqlite3DbStrDup(db, zErr);
|
||||
|
||||
+94
-54
@@ -20,7 +20,8 @@
|
||||
/*
|
||||
** Create a new virtual database engine.
|
||||
*/
|
||||
Vdbe *sqlite3VdbeCreate(sqlite3 *db){
|
||||
Vdbe *sqlite3VdbeCreate(Parse *pParse){
|
||||
sqlite3 *db = pParse->db;
|
||||
Vdbe *p;
|
||||
p = sqlite3DbMallocZero(db, sizeof(Vdbe) );
|
||||
if( p==0 ) return 0;
|
||||
@@ -32,6 +33,10 @@ Vdbe *sqlite3VdbeCreate(sqlite3 *db){
|
||||
p->pPrev = 0;
|
||||
db->pVdbe = p;
|
||||
p->magic = VDBE_MAGIC_INIT;
|
||||
p->pParse = pParse;
|
||||
assert( pParse->aLabel==0 );
|
||||
assert( pParse->nLabel==0 );
|
||||
assert( pParse->nOpAlloc==0 );
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -87,13 +92,14 @@ void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
|
||||
** unchanged (this is so that any opcodes already allocated can be
|
||||
** correctly deallocated along with the rest of the Vdbe).
|
||||
*/
|
||||
static int growOpArray(Vdbe *p){
|
||||
static int growOpArray(Vdbe *v){
|
||||
VdbeOp *pNew;
|
||||
Parse *p = v->pParse;
|
||||
int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op)));
|
||||
pNew = sqlite3DbRealloc(p->db, p->aOp, nNew*sizeof(Op));
|
||||
pNew = sqlite3DbRealloc(p->db, v->aOp, nNew*sizeof(Op));
|
||||
if( pNew ){
|
||||
p->nOpAlloc = sqlite3DbMallocSize(p->db, pNew)/sizeof(Op);
|
||||
p->aOp = pNew;
|
||||
v->aOp = pNew;
|
||||
}
|
||||
return (pNew ? SQLITE_OK : SQLITE_NOMEM);
|
||||
}
|
||||
@@ -132,7 +138,7 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
|
||||
i = p->nOp;
|
||||
assert( p->magic==VDBE_MAGIC_INIT );
|
||||
assert( op>0 && op<0xff );
|
||||
if( p->nOpAlloc<=i ){
|
||||
if( p->pParse->nOpAlloc<=i ){
|
||||
if( growOpArray(p) ){
|
||||
return 1;
|
||||
}
|
||||
@@ -151,6 +157,15 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( p->db->flags & SQLITE_VdbeAddopTrace ){
|
||||
int jj, kk;
|
||||
Parse *pParse = p->pParse;
|
||||
for(jj=kk=0; jj<SQLITE_N_COLCACHE; jj++){
|
||||
struct yColCache *x = pParse->aColCache + jj;
|
||||
if( x->iLevel>pParse->iCacheLevel || x->iReg==0 ) continue;
|
||||
printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn);
|
||||
kk++;
|
||||
}
|
||||
if( kk ) printf("\n");
|
||||
sqlite3VdbePrintOp(0, i, &p->aOp[i]);
|
||||
test_addop_breakpoint();
|
||||
}
|
||||
@@ -234,9 +249,10 @@ int sqlite3VdbeAddOp4Int(
|
||||
**
|
||||
** Zero is returned if a malloc() fails.
|
||||
*/
|
||||
int sqlite3VdbeMakeLabel(Vdbe *p){
|
||||
int sqlite3VdbeMakeLabel(Vdbe *v){
|
||||
Parse *p = v->pParse;
|
||||
int i = p->nLabel++;
|
||||
assert( p->magic==VDBE_MAGIC_INIT );
|
||||
assert( v->magic==VDBE_MAGIC_INIT );
|
||||
if( (i & (i-1))==0 ){
|
||||
p->aLabel = sqlite3DbReallocOrFree(p->db, p->aLabel,
|
||||
(i*2+1)*sizeof(p->aLabel[0]));
|
||||
@@ -252,13 +268,15 @@ int sqlite3VdbeMakeLabel(Vdbe *p){
|
||||
** be inserted. The parameter "x" must have been obtained from
|
||||
** a prior call to sqlite3VdbeMakeLabel().
|
||||
*/
|
||||
void sqlite3VdbeResolveLabel(Vdbe *p, int x){
|
||||
void sqlite3VdbeResolveLabel(Vdbe *v, int x){
|
||||
Parse *p = v->pParse;
|
||||
int j = -1-x;
|
||||
assert( p->magic==VDBE_MAGIC_INIT );
|
||||
assert( v->magic==VDBE_MAGIC_INIT );
|
||||
assert( j<p->nLabel );
|
||||
if( j>=0 && p->aLabel ){
|
||||
p->aLabel[j] = p->nOp;
|
||||
p->aLabel[j] = v->nOp;
|
||||
}
|
||||
p->iFixedOp = v->nOp - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -406,7 +424,8 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
|
||||
int i;
|
||||
int nMaxArgs = *pMaxFuncArgs;
|
||||
Op *pOp;
|
||||
int *aLabel = p->aLabel;
|
||||
Parse *pParse = p->pParse;
|
||||
int *aLabel = pParse->aLabel;
|
||||
p->readOnly = 1;
|
||||
p->bIsReader = 0;
|
||||
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
|
||||
@@ -469,12 +488,13 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
|
||||
|
||||
pOp->opflags = sqlite3OpcodeProperty[opcode];
|
||||
if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
|
||||
assert( -1-pOp->p2<p->nLabel );
|
||||
assert( -1-pOp->p2<pParse->nLabel );
|
||||
pOp->p2 = aLabel[-1-pOp->p2];
|
||||
}
|
||||
}
|
||||
sqlite3DbFree(p->db, p->aLabel);
|
||||
p->aLabel = 0;
|
||||
sqlite3DbFree(p->db, pParse->aLabel);
|
||||
pParse->aLabel = 0;
|
||||
pParse->nLabel = 0;
|
||||
*pMaxFuncArgs = nMaxArgs;
|
||||
assert( p->bIsReader!=0 || p->btreeMask==0 );
|
||||
}
|
||||
@@ -518,7 +538,7 @@ VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
|
||||
int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
|
||||
int addr;
|
||||
assert( p->magic==VDBE_MAGIC_INIT );
|
||||
if( p->nOp + nOp > p->nOpAlloc && growOpArray(p) ){
|
||||
if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p) ){
|
||||
return 0;
|
||||
}
|
||||
addr = p->nOp;
|
||||
@@ -605,7 +625,8 @@ void sqlite3VdbeChangeP5(Vdbe *p, u8 val){
|
||||
** the address of the next instruction to be coded.
|
||||
*/
|
||||
void sqlite3VdbeJumpHere(Vdbe *p, int addr){
|
||||
if( ALWAYS(addr>=0) ) sqlite3VdbeChangeP2(p, addr, p->nOp);
|
||||
sqlite3VdbeChangeP2(p, addr, p->nOp);
|
||||
p->pParse->iFixedOp = p->nOp - 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -707,6 +728,18 @@ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Remove the last opcode inserted
|
||||
*/
|
||||
int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
|
||||
if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){
|
||||
sqlite3VdbeChangeToNoop(p, p->nOp-1);
|
||||
return 1;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Change the value of the P4 operand for a specific instruction.
|
||||
** This routine is useful when a large program is loaded from a
|
||||
@@ -872,7 +905,17 @@ static int translateP(char c, const Op *pOp){
|
||||
}
|
||||
|
||||
/*
|
||||
** Compute a string for the "comment" field of a VDBE opcode listing
|
||||
** Compute a string for the "comment" field of a VDBE opcode listing.
|
||||
**
|
||||
** The Synopsis: field in comments in the vdbe.c source file gets converted
|
||||
** to an extra string that is appended to the sqlite3OpcodeName(). In the
|
||||
** absence of other comments, this synopsis becomes the comment on the opcode.
|
||||
** Some translation occurs:
|
||||
**
|
||||
** "PX" -> "r[X]"
|
||||
** "PX@PY" -> "r[X..X+Y-1]" or "r[x]" if y is 0 or 1
|
||||
** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0
|
||||
** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x
|
||||
*/
|
||||
static int displayComment(
|
||||
const Op *pOp, /* The opcode to be commented */
|
||||
@@ -906,7 +949,13 @@ static int displayComment(
|
||||
ii += 3;
|
||||
jj += sqlite3Strlen30(zTemp+jj);
|
||||
v2 = translateP(zSynopsis[ii], pOp);
|
||||
if( v2>1 ) sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1);
|
||||
if( strncmp(zSynopsis+ii+1,"+1",2)==0 ){
|
||||
ii += 2;
|
||||
v2++;
|
||||
}
|
||||
if( v2>1 ){
|
||||
sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1);
|
||||
}
|
||||
}else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
|
||||
ii += 4;
|
||||
}
|
||||
@@ -1138,6 +1187,9 @@ void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
|
||||
#else
|
||||
zCom[0] = 0
|
||||
#endif
|
||||
/* NB: The sqlite3OpcodeName() function is implemented by code created
|
||||
** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the
|
||||
** information from the vdbe.c source text */
|
||||
fprintf(pOut, zFormat1, pc,
|
||||
sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
|
||||
zCom
|
||||
@@ -1569,6 +1621,7 @@ void sqlite3VdbeMakeReady(
|
||||
assert( p->nOp>0 );
|
||||
assert( pParse!=0 );
|
||||
assert( p->magic==VDBE_MAGIC_INIT );
|
||||
assert( pParse==p->pParse );
|
||||
db = p->db;
|
||||
assert( db->mallocFailed==0 );
|
||||
nVar = pParse->nVar;
|
||||
@@ -1592,8 +1645,8 @@ void sqlite3VdbeMakeReady(
|
||||
/* Allocate space for memory registers, SQL variables, VDBE cursors and
|
||||
** an array to marshal SQL function arguments in.
|
||||
*/
|
||||
zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */
|
||||
zEnd = (u8*)&p->aOp[p->nOpAlloc]; /* First byte past end of zCsr[] */
|
||||
zCsr = (u8*)&p->aOp[p->nOp]; /* Memory avaliable for allocation */
|
||||
zEnd = (u8*)&p->aOp[pParse->nOpAlloc]; /* First byte past end of zCsr[] */
|
||||
|
||||
resolveP2Values(p, &nArg);
|
||||
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
|
||||
@@ -2420,6 +2473,7 @@ int sqlite3VdbeTransferError(Vdbe *p){
|
||||
if( p->zErrMsg ){
|
||||
u8 mallocFailed = db->mallocFailed;
|
||||
sqlite3BeginBenignMalloc();
|
||||
if( db->pErr==0 ) db->pErr = sqlite3ValueNew(db);
|
||||
sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
|
||||
sqlite3EndBenignMalloc();
|
||||
db->mallocFailed = mallocFailed;
|
||||
@@ -2488,8 +2542,7 @@ int sqlite3VdbeReset(Vdbe *p){
|
||||
** to sqlite3_step(). For consistency (since sqlite3_step() was
|
||||
** called), set the database error in this case as well.
|
||||
*/
|
||||
sqlite3Error(db, p->rc, 0);
|
||||
sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
|
||||
sqlite3Error(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = 0;
|
||||
}
|
||||
@@ -2562,8 +2615,9 @@ void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
|
||||
while( *pp ){
|
||||
AuxData *pAux = *pp;
|
||||
if( (iOp<0)
|
||||
|| (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & ((u32)1<<pAux->iArg))))
|
||||
|| (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & MASKBIT32(pAux->iArg))))
|
||||
){
|
||||
testcase( pAux->iArg==31 );
|
||||
if( pAux->xDelete ){
|
||||
pAux->xDelete(pAux->pAux);
|
||||
}
|
||||
@@ -2596,7 +2650,6 @@ void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
|
||||
}
|
||||
for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
|
||||
vdbeFreeOpArray(db, p->aOp, p->nOp);
|
||||
sqlite3DbFree(db, p->aLabel);
|
||||
sqlite3DbFree(db, p->aColName);
|
||||
sqlite3DbFree(db, p->zSql);
|
||||
sqlite3DbFree(db, p->pFree);
|
||||
@@ -2827,21 +2880,15 @@ static u64 floatSwap(u64 in){
|
||||
** buf. It is assumed that the caller has allocated sufficient space.
|
||||
** Return the number of bytes written.
|
||||
**
|
||||
** nBuf is the amount of space left in buf[]. nBuf must always be
|
||||
** large enough to hold the entire field. Except, if the field is
|
||||
** a blob with a zero-filled tail, then buf[] might be just the right
|
||||
** size to hold everything except for the zero-filled tail. If buf[]
|
||||
** is only big enough to hold the non-zero prefix, then only write that
|
||||
** prefix into buf[]. But if buf[] is large enough to hold both the
|
||||
** prefix and the tail then write the prefix and set the tail to all
|
||||
** zeros.
|
||||
** nBuf is the amount of space left in buf[]. The caller is responsible
|
||||
** for allocating enough space to buf[] to hold the entire field, exclusive
|
||||
** of the pMem->u.nZero bytes for a MEM_Zero value.
|
||||
**
|
||||
** Return the number of bytes actually written into buf[]. The number
|
||||
** of bytes in the zero-filled tail is included in the return value only
|
||||
** if those bytes were zeroed in buf[].
|
||||
*/
|
||||
u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){
|
||||
u32 serial_type = sqlite3VdbeSerialType(pMem, file_format);
|
||||
u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
|
||||
u32 len;
|
||||
|
||||
/* Integer and Real */
|
||||
@@ -2856,7 +2903,6 @@ u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){
|
||||
v = pMem->u.i;
|
||||
}
|
||||
len = i = sqlite3VdbeSerialTypeLen(serial_type);
|
||||
assert( len<=(u32)nBuf );
|
||||
while( i-- ){
|
||||
buf[i] = (u8)(v&0xFF);
|
||||
v >>= 8;
|
||||
@@ -2868,17 +2914,8 @@ u32 sqlite3VdbeSerialPut(u8 *buf, int nBuf, Mem *pMem, int file_format){
|
||||
if( serial_type>=12 ){
|
||||
assert( pMem->n + ((pMem->flags & MEM_Zero)?pMem->u.nZero:0)
|
||||
== (int)sqlite3VdbeSerialTypeLen(serial_type) );
|
||||
assert( pMem->n<=nBuf );
|
||||
len = pMem->n;
|
||||
memcpy(buf, pMem->z, len);
|
||||
if( pMem->flags & MEM_Zero ){
|
||||
len += pMem->u.nZero;
|
||||
assert( nBuf>=0 );
|
||||
if( len > (u32)nBuf ){
|
||||
len = (u32)nBuf;
|
||||
}
|
||||
memset(&buf[pMem->n], 0, len-pMem->n);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -2895,6 +2932,9 @@ u32 sqlite3VdbeSerialGet(
|
||||
u32 serial_type, /* Serial type to deserialize */
|
||||
Mem *pMem /* Memory cell to write value into */
|
||||
){
|
||||
u64 x;
|
||||
u32 y;
|
||||
int i;
|
||||
switch( serial_type ){
|
||||
case 10: /* Reserved for future use */
|
||||
case 11: /* Reserved for future use */
|
||||
@@ -2908,23 +2948,26 @@ u32 sqlite3VdbeSerialGet(
|
||||
return 1;
|
||||
}
|
||||
case 2: { /* 2-byte signed integer */
|
||||
pMem->u.i = (((signed char)buf[0])<<8) | buf[1];
|
||||
i = 256*(signed char)buf[0] | buf[1];
|
||||
pMem->u.i = (i64)i;
|
||||
pMem->flags = MEM_Int;
|
||||
return 2;
|
||||
}
|
||||
case 3: { /* 3-byte signed integer */
|
||||
pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2];
|
||||
i = 65536*(signed char)buf[0] | (buf[1]<<8) | buf[2];
|
||||
pMem->u.i = (i64)i;
|
||||
pMem->flags = MEM_Int;
|
||||
return 3;
|
||||
}
|
||||
case 4: { /* 4-byte signed integer */
|
||||
pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
|
||||
y = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
|
||||
pMem->u.i = (i64)*(int*)&y;
|
||||
pMem->flags = MEM_Int;
|
||||
return 4;
|
||||
}
|
||||
case 5: { /* 6-byte signed integer */
|
||||
u64 x = (((signed char)buf[0])<<8) | buf[1];
|
||||
u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
|
||||
x = 256*(signed char)buf[0] + buf[1];
|
||||
y = ((unsigned)buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
|
||||
x = (x<<32) | y;
|
||||
pMem->u.i = *(i64*)&x;
|
||||
pMem->flags = MEM_Int;
|
||||
@@ -2932,8 +2975,6 @@ u32 sqlite3VdbeSerialGet(
|
||||
}
|
||||
case 6: /* 8-byte signed integer */
|
||||
case 7: { /* IEEE floating point */
|
||||
u64 x;
|
||||
u32 y;
|
||||
#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
|
||||
/* Verify that integers and floating point values use the same
|
||||
** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
|
||||
@@ -2946,9 +2987,8 @@ u32 sqlite3VdbeSerialGet(
|
||||
swapMixedEndianFloat(t2);
|
||||
assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
|
||||
#endif
|
||||
|
||||
x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
|
||||
y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
|
||||
x = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
|
||||
y = ((unsigned)buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
|
||||
x = (x<<32) | y;
|
||||
if( serial_type==6 ){
|
||||
pMem->u.i = *(i64*)&x;
|
||||
|
||||
+1
-1
@@ -255,7 +255,7 @@ int sqlite3_blob_open(
|
||||
}
|
||||
}
|
||||
|
||||
pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(db);
|
||||
pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse);
|
||||
assert( pBlob->pStmt || db->mallocFailed );
|
||||
if( pBlob->pStmt ){
|
||||
Vdbe *v = (Vdbe *)pBlob->pStmt;
|
||||
|
||||
+32
-29
@@ -59,18 +59,14 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
|
||||
|
||||
/*
|
||||
** Make sure pMem->z points to a writable allocation of at least
|
||||
** n bytes.
|
||||
** min(n,32) bytes.
|
||||
**
|
||||
** If the third argument passed to this function is true, then memory
|
||||
** cell pMem must contain a string or blob. In this case the content is
|
||||
** preserved. Otherwise, if the third parameter to this function is false,
|
||||
** any current string or blob value may be discarded.
|
||||
**
|
||||
** This function sets the MEM_Dyn flag and clears any xDel callback.
|
||||
** It also clears MEM_Ephem and MEM_Static. If the preserve flag is
|
||||
** not set, Mem.n is zeroed.
|
||||
** If the bPreserve argument is true, then copy of the content of
|
||||
** pMem->z into the new allocation. pMem must be either a string or
|
||||
** blob if bPreserve is true. If bPreserve is false, any prior content
|
||||
** in pMem->z is discarded.
|
||||
*/
|
||||
int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
|
||||
int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
|
||||
assert( 1 >=
|
||||
((pMem->zMalloc && pMem->zMalloc==pMem->z) ? 1 : 0) +
|
||||
(((pMem->flags&MEM_Dyn)&&pMem->xDel) ? 1 : 0) +
|
||||
@@ -79,37 +75,39 @@ int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve){
|
||||
);
|
||||
assert( (pMem->flags&MEM_RowSet)==0 );
|
||||
|
||||
/* If the preserve flag is set to true, then the memory cell must already
|
||||
/* If the bPreserve flag is set to true, then the memory cell must already
|
||||
** contain a valid string or blob value. */
|
||||
assert( preserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
|
||||
assert( bPreserve==0 || pMem->flags&(MEM_Blob|MEM_Str) );
|
||||
testcase( bPreserve && pMem->z==0 );
|
||||
|
||||
if( n<32 ) n = 32;
|
||||
if( sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
|
||||
if( preserve && pMem->z==pMem->zMalloc ){
|
||||
if( pMem->zMalloc==0 || sqlite3DbMallocSize(pMem->db, pMem->zMalloc)<n ){
|
||||
if( n<32 ) n = 32;
|
||||
if( bPreserve && pMem->z==pMem->zMalloc ){
|
||||
pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
|
||||
preserve = 0;
|
||||
bPreserve = 0;
|
||||
}else{
|
||||
sqlite3DbFree(pMem->db, pMem->zMalloc);
|
||||
pMem->zMalloc = sqlite3DbMallocRaw(pMem->db, n);
|
||||
}
|
||||
if( pMem->zMalloc==0 ){
|
||||
sqlite3VdbeMemRelease(pMem);
|
||||
pMem->flags = MEM_Null;
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if( pMem->z && preserve && pMem->zMalloc && pMem->z!=pMem->zMalloc ){
|
||||
if( pMem->z && bPreserve && pMem->z!=pMem->zMalloc ){
|
||||
memcpy(pMem->zMalloc, pMem->z, pMem->n);
|
||||
}
|
||||
if( pMem->flags&MEM_Dyn && pMem->xDel ){
|
||||
if( (pMem->flags&MEM_Dyn)!=0 && pMem->xDel ){
|
||||
assert( pMem->xDel!=SQLITE_DYNAMIC );
|
||||
pMem->xDel((void *)(pMem->z));
|
||||
}
|
||||
|
||||
pMem->z = pMem->zMalloc;
|
||||
if( pMem->z==0 ){
|
||||
pMem->flags = MEM_Null;
|
||||
}else{
|
||||
pMem->flags &= ~(MEM_Ephem|MEM_Static);
|
||||
}
|
||||
pMem->flags &= ~(MEM_Ephem|MEM_Static);
|
||||
pMem->xDel = 0;
|
||||
return (pMem->z ? SQLITE_OK : SQLITE_NOMEM);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -295,10 +293,12 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){
|
||||
*/
|
||||
void sqlite3VdbeMemRelease(Mem *p){
|
||||
VdbeMemRelease(p);
|
||||
sqlite3DbFree(p->db, p->zMalloc);
|
||||
if( p->zMalloc ){
|
||||
sqlite3DbFree(p->db, p->zMalloc);
|
||||
p->zMalloc = 0;
|
||||
}
|
||||
p->z = 0;
|
||||
p->zMalloc = 0;
|
||||
p->xDel = 0;
|
||||
assert( p->xDel==0 ); /* Zeroed by VdbeMemRelease() above */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -482,6 +482,9 @@ void sqlite3VdbeMemSetNull(Mem *pMem){
|
||||
MemSetTypeFlag(pMem, MEM_Null);
|
||||
pMem->type = SQLITE_NULL;
|
||||
}
|
||||
void sqlite3ValueSetNull(sqlite3_value *p){
|
||||
sqlite3VdbeMemSetNull((Mem*)p);
|
||||
}
|
||||
|
||||
/*
|
||||
** Delete any previous value and set the value to be a BLOB of length
|
||||
@@ -595,7 +598,7 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
|
||||
/*
|
||||
** Size of struct Mem not including the Mem.zMalloc member.
|
||||
*/
|
||||
#define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc))
|
||||
#define MEMCELLSIZE offsetof(Mem,zMalloc)
|
||||
|
||||
/*
|
||||
** Make an shallow copy of pFrom into pTo. Prior contents of
|
||||
@@ -1219,7 +1222,7 @@ static void recordFunc(
|
||||
}else{
|
||||
aRet[0] = nSerial+1;
|
||||
sqlite3PutVarint(&aRet[1], iSerial);
|
||||
sqlite3VdbeSerialPut(&aRet[1+nSerial], nVal, argv[0], file_format);
|
||||
sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial);
|
||||
sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
|
||||
sqlite3DbFree(db, aRet);
|
||||
}
|
||||
|
||||
+13
-8
@@ -92,6 +92,7 @@ char *sqlite3VdbeExpandSql(
|
||||
const char *zStart = zRawSql;
|
||||
while( *(zRawSql++)!='\n' && *zRawSql );
|
||||
sqlite3StrAccumAppend(&out, "-- ", 3);
|
||||
assert( (zRawSql - zStart) > 0 );
|
||||
sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart));
|
||||
}
|
||||
}else{
|
||||
@@ -124,9 +125,9 @@ char *sqlite3VdbeExpandSql(
|
||||
if( pVar->flags & MEM_Null ){
|
||||
sqlite3StrAccumAppend(&out, "NULL", 4);
|
||||
}else if( pVar->flags & MEM_Int ){
|
||||
sqlite3XPrintf(&out, "%lld", pVar->u.i);
|
||||
sqlite3XPrintf(&out, 0, "%lld", pVar->u.i);
|
||||
}else if( pVar->flags & MEM_Real ){
|
||||
sqlite3XPrintf(&out, "%!.15g", pVar->r);
|
||||
sqlite3XPrintf(&out, 0, "%!.15g", pVar->r);
|
||||
}else if( pVar->flags & MEM_Str ){
|
||||
int nOut; /* Number of bytes of the string text to include in output */
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
@@ -147,15 +148,17 @@ char *sqlite3VdbeExpandSql(
|
||||
while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; }
|
||||
}
|
||||
#endif
|
||||
sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z);
|
||||
sqlite3XPrintf(&out, 0, "'%.*q'", nOut, pVar->z);
|
||||
#ifdef SQLITE_TRACE_SIZE_LIMIT
|
||||
if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
|
||||
if( nOut<pVar->n ){
|
||||
sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut);
|
||||
}
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8);
|
||||
#endif
|
||||
}else if( pVar->flags & MEM_Zero ){
|
||||
sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero);
|
||||
sqlite3XPrintf(&out, 0, "zeroblob(%d)", pVar->u.nZero);
|
||||
}else{
|
||||
int nOut; /* Number of bytes of the blob to include in output */
|
||||
assert( pVar->flags & MEM_Blob );
|
||||
@@ -165,11 +168,13 @@ char *sqlite3VdbeExpandSql(
|
||||
if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT;
|
||||
#endif
|
||||
for(i=0; i<nOut; i++){
|
||||
sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff);
|
||||
sqlite3XPrintf(&out, 0, "%02x", pVar->z[i]&0xff);
|
||||
}
|
||||
sqlite3StrAccumAppend(&out, "'", 1);
|
||||
#ifdef SQLITE_TRACE_SIZE_LIMIT
|
||||
if( nOut<pVar->n ) sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
|
||||
if( nOut<pVar->n ){
|
||||
sqlite3XPrintf(&out, 0, "/*+%d bytes*/", pVar->n-nOut);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -228,7 +233,7 @@ void sqlite3ExplainPrintf(Vdbe *pVdbe, const char *zFormat, ...){
|
||||
sqlite3AppendSpace(&p->str, p->aIndent[n-1]);
|
||||
}
|
||||
va_start(ap, zFormat);
|
||||
sqlite3VXPrintf(&p->str, 1, zFormat, ap);
|
||||
sqlite3VXPrintf(&p->str, SQLITE_PRINTF_INTERNAL, zFormat, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
+12
-11
@@ -113,9 +113,12 @@ int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
|
||||
/*
|
||||
** Call sqlite3WalkExpr() for every expression in Select statement p.
|
||||
** Invoke sqlite3WalkSelect() for subqueries in the FROM clause and
|
||||
** on the compound select chain, p->pPrior. Invoke the xSelectCallback()
|
||||
** either before or after the walk of expressions and FROM clause, depending
|
||||
** on whether pWalker->bSelectDepthFirst is false or true, respectively.
|
||||
** on the compound select chain, p->pPrior.
|
||||
**
|
||||
** If it is not NULL, the xSelectCallback() callback is invoked before
|
||||
** the walk of the expressions and FROM clause. The xSelectCallback2()
|
||||
** method, if it is not NULL, is invoked following the walk of the
|
||||
** expressions and FROM clause.
|
||||
**
|
||||
** Return WRC_Continue under normal conditions. Return WRC_Abort if
|
||||
** there is an abort request.
|
||||
@@ -125,11 +128,13 @@ int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
|
||||
*/
|
||||
int sqlite3WalkSelect(Walker *pWalker, Select *p){
|
||||
int rc;
|
||||
if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
|
||||
if( p==0 || (pWalker->xSelectCallback==0 && pWalker->xSelectCallback2==0) ){
|
||||
return WRC_Continue;
|
||||
}
|
||||
rc = WRC_Continue;
|
||||
pWalker->walkerDepth++;
|
||||
while( p ){
|
||||
if( !pWalker->bSelectDepthFirst ){
|
||||
if( pWalker->xSelectCallback ){
|
||||
rc = pWalker->xSelectCallback(pWalker, p);
|
||||
if( rc ) break;
|
||||
}
|
||||
@@ -139,12 +144,8 @@ int sqlite3WalkSelect(Walker *pWalker, Select *p){
|
||||
pWalker->walkerDepth--;
|
||||
return WRC_Abort;
|
||||
}
|
||||
if( pWalker->bSelectDepthFirst ){
|
||||
rc = pWalker->xSelectCallback(pWalker, p);
|
||||
/* Depth-first search is currently only used for
|
||||
** selectAddSubqueryTypeInfo() and that routine always returns
|
||||
** WRC_Continue (0). So the following branch is never taken. */
|
||||
if( NEVER(rc) ) break;
|
||||
if( pWalker->xSelectCallback2 ){
|
||||
pWalker->xSelectCallback2(pWalker, p);
|
||||
}
|
||||
p = p->pPrior;
|
||||
}
|
||||
|
||||
+26
-13
@@ -667,7 +667,7 @@ static int isLikeOrGlob(
|
||||
}
|
||||
assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
|
||||
|
||||
pRight = pList->a[0].pExpr;
|
||||
pRight = sqlite3ExprSkipCollate(pList->a[0].pExpr);
|
||||
op = pRight->op;
|
||||
if( op==TK_VARIABLE ){
|
||||
Vdbe *pReprepare = pParse->pReprepare;
|
||||
@@ -1710,7 +1710,7 @@ static void constructAutomaticIndex(
|
||||
/* Fill the automatic index with content */
|
||||
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur);
|
||||
regRecord = sqlite3GetTempReg(pParse);
|
||||
sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0);
|
||||
sqlite3GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 0, 0, 0, 0);
|
||||
sqlite3VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1);
|
||||
@@ -1751,7 +1751,8 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
|
||||
testcase( pTerm->eOperator & WO_IN );
|
||||
testcase( pTerm->eOperator & WO_ISNULL );
|
||||
if( pTerm->eOperator & (WO_ISNULL) ) continue;
|
||||
testcase( pTerm->eOperator & WO_ALL );
|
||||
if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV))==0 ) continue;
|
||||
if( pTerm->wtFlags & TERM_VNULL ) continue;
|
||||
nTerm++;
|
||||
}
|
||||
@@ -1803,7 +1804,8 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
|
||||
testcase( pTerm->eOperator & WO_IN );
|
||||
testcase( pTerm->eOperator & WO_ISNULL );
|
||||
if( pTerm->eOperator & (WO_ISNULL) ) continue;
|
||||
testcase( pTerm->eOperator & WO_ALL );
|
||||
if( (pTerm->eOperator & ~(WO_ISNULL|WO_EQUIV))==0 ) continue;
|
||||
if( pTerm->wtFlags & TERM_VNULL ) continue;
|
||||
pIdxCons[j].iColumn = pTerm->u.leftColumn;
|
||||
pIdxCons[j].iTermOffset = i;
|
||||
@@ -2568,7 +2570,7 @@ static void explainAppendTerm(
|
||||
const char *zOp /* Name of the operator */
|
||||
){
|
||||
if( iTerm ) sqlite3StrAccumAppend(pStr, " AND ", 5);
|
||||
sqlite3StrAccumAppend(pStr, zColumn, -1);
|
||||
sqlite3StrAccumAppendAll(pStr, zColumn);
|
||||
sqlite3StrAccumAppend(pStr, zOp, 1);
|
||||
sqlite3StrAccumAppend(pStr, "?", 1);
|
||||
}
|
||||
@@ -2614,7 +2616,7 @@ static char *explainIndexRange(sqlite3 *db, WhereLoop *pLoop, Table *pTab){
|
||||
}else{
|
||||
if( i ) sqlite3StrAccumAppend(&txt, " AND ", 5);
|
||||
sqlite3StrAccumAppend(&txt, "ANY(", 4);
|
||||
sqlite3StrAccumAppend(&txt, z, -1);
|
||||
sqlite3StrAccumAppendAll(&txt, z);
|
||||
sqlite3StrAccumAppend(&txt, ")", 1);
|
||||
}
|
||||
}
|
||||
@@ -3408,10 +3410,16 @@ static Bitmask codeOneLoopStart(
|
||||
static const u8 aStep[] = { OP_Next, OP_Prev };
|
||||
static const u8 aStart[] = { OP_Rewind, OP_Last };
|
||||
assert( bRev==0 || bRev==1 );
|
||||
pLevel->op = aStep[bRev];
|
||||
pLevel->p1 = iCur;
|
||||
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
|
||||
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
|
||||
if( pTabItem->isRecursive ){
|
||||
/* Tables marked isRecursive have only a single row that is stored in
|
||||
** a pseudo-cursor. No need to Rewind or Next such cursors. */
|
||||
pLevel->op = OP_Noop;
|
||||
}else{
|
||||
pLevel->op = aStep[bRev];
|
||||
pLevel->p1 = iCur;
|
||||
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
|
||||
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert code to test every subexpression that can be completely
|
||||
@@ -3928,6 +3936,7 @@ static int whereLoopAddBtreeIndex(
|
||||
&& saved_nEq==saved_nSkip
|
||||
&& saved_nEq+1<pProbe->nKeyCol
|
||||
&& pProbe->aiRowEst[saved_nEq+1]>=18 /* TUNING: Minimum for skip-scan */
|
||||
&& (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK
|
||||
){
|
||||
LogEst nIter;
|
||||
pNew->u.btree.nEq++;
|
||||
@@ -4195,6 +4204,7 @@ static int whereLoopAddBtree(
|
||||
&& !pSrc->notIndexed
|
||||
&& HasRowid(pTab)
|
||||
&& !pSrc->isCorrelated
|
||||
&& !pSrc->isRecursive
|
||||
){
|
||||
/* Generate auto-index WhereLoops */
|
||||
WhereTerm *pTerm;
|
||||
@@ -5429,9 +5439,12 @@ WhereInfo *sqlite3WhereBegin(
|
||||
/* Special case: a WHERE clause that is constant. Evaluate the
|
||||
** expression and either jump over all of the code or fall thru.
|
||||
*/
|
||||
if( pWhere && (nTabList==0 || sqlite3ExprIsConstantNotJoin(pWhere)) ){
|
||||
sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE_JUMPIFNULL);
|
||||
pWhere = 0;
|
||||
for(ii=0; ii<sWLB.pWC->nTerm; ii++){
|
||||
if( nTabList==0 || sqlite3ExprIsConstantNotJoin(sWLB.pWC->a[ii].pExpr) ){
|
||||
sqlite3ExprIfFalse(pParse, sWLB.pWC->a[ii].pExpr, pWInfo->iBreak,
|
||||
SQLITE_JUMPIFNULL);
|
||||
sWLB.pWC->a[ii].wtFlags |= TERM_CODED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special case: No FROM clause
|
||||
|
||||
@@ -322,7 +322,6 @@ do_test attach3-12.9 {
|
||||
db_list
|
||||
} {main temp {}}
|
||||
do_test attach3-12.10 {
|
||||
breakpoint
|
||||
execsql {
|
||||
DETACH ?
|
||||
}
|
||||
|
||||
@@ -2080,6 +2080,42 @@ ifcapable {altertable} {
|
||||
execsql {DROP TABLE t5}
|
||||
} ;# ifcapable altertable
|
||||
|
||||
ifcapable {cte} {
|
||||
do_test auth-1.310 {
|
||||
proc auth {code arg1 arg2 arg3 arg4} {
|
||||
if {$code=="SQLITE_RECURSIVE"} {
|
||||
return SQLITE_DENY
|
||||
}
|
||||
return SQLITE_OK
|
||||
}
|
||||
db eval {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1 VALUES(1,2),(3,4),(5,6);
|
||||
}
|
||||
} {}
|
||||
do_catchsql_test auth-1.311 {
|
||||
WITH
|
||||
auth1311(x,y) AS (SELECT a+b, b-a FROM t1)
|
||||
SELECT * FROM auth1311 ORDER BY x;
|
||||
} {0 {3 1 7 1 11 1}}
|
||||
do_catchsql_test auth-1.312 {
|
||||
WITH RECURSIVE
|
||||
auth1312(x,y) AS (SELECT a+b, b-a FROM t1)
|
||||
SELECT x, y FROM auth1312 ORDER BY x;
|
||||
} {0 {3 1 7 1 11 1}}
|
||||
do_catchsql_test auth-1.313 {
|
||||
WITH RECURSIVE
|
||||
auth1313(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM auth1313 WHERE x<5)
|
||||
SELECT * FROM t1;
|
||||
} {0 {1 2 3 4 5 6}}
|
||||
do_catchsql_test auth-1.314 {
|
||||
WITH RECURSIVE
|
||||
auth1314(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM auth1314 WHERE x<5)
|
||||
SELECT * FROM t1 LEFT JOIN auth1314;
|
||||
} {1 {not authorized}}
|
||||
} ;# ifcapable cte
|
||||
|
||||
do_test auth-2.1 {
|
||||
proc auth {code arg1 arg2 arg3 arg4} {
|
||||
if {$code=="SQLITE_READ" && $arg1=="t3" && $arg2=="x"} {
|
||||
|
||||
+24
-18
@@ -179,16 +179,18 @@ do_test capi3-3.4 {
|
||||
do_test capi3-3.5 {
|
||||
sqlite3_close $db2
|
||||
} {SQLITE_OK}
|
||||
do_test capi3-3.6.1-misuse {
|
||||
sqlite3_close $db2
|
||||
} {SQLITE_MISUSE}
|
||||
do_test capi3-3.6.2-misuse {
|
||||
sqlite3_errmsg $db2
|
||||
} {library routine called out of sequence}
|
||||
ifcapable {utf16} {
|
||||
do_test capi3-3.6.3-misuse {
|
||||
utf8 [sqlite3_errmsg16 $db2]
|
||||
if {[clang_sanitize_address]==0} {
|
||||
do_test capi3-3.6.1-misuse {
|
||||
sqlite3_close $db2
|
||||
} {SQLITE_MISUSE}
|
||||
do_test capi3-3.6.2-misuse {
|
||||
sqlite3_errmsg $db2
|
||||
} {library routine called out of sequence}
|
||||
ifcapable {utf16} {
|
||||
do_test capi3-3.6.3-misuse {
|
||||
utf8 [sqlite3_errmsg16 $db2]
|
||||
} {library routine called out of sequence}
|
||||
}
|
||||
}
|
||||
|
||||
do_test capi3-3.7 {
|
||||
@@ -661,10 +663,12 @@ do_test capi3-6.3 {
|
||||
sqlite3_finalize $STMT
|
||||
} {SQLITE_OK}
|
||||
|
||||
do_test capi3-6.4-misuse {
|
||||
db cache flush
|
||||
sqlite3_close $DB
|
||||
} {SQLITE_OK}
|
||||
if {[clang_sanitize_address]==0} {
|
||||
do_test capi3-6.4-misuse {
|
||||
db cache flush
|
||||
sqlite3_close $DB
|
||||
} {SQLITE_OK}
|
||||
}
|
||||
db close
|
||||
|
||||
# This procedure sets the value of the file-format in file 'test.db'
|
||||
@@ -1060,11 +1064,13 @@ if {[llength [info commands sqlite3_sleep]]>0} {
|
||||
}
|
||||
|
||||
# Ticket #1219: Make sure binding APIs can handle a NULL pointer.
|
||||
#
|
||||
do_test capi3-14.1-misuse {
|
||||
set rc [catch {sqlite3_bind_text 0 1 hello 5} msg]
|
||||
lappend rc $msg
|
||||
} {1 SQLITE_MISUSE}
|
||||
#
|
||||
if {[clang_sanitize_address]==0} {
|
||||
do_test capi3-14.1-misuse {
|
||||
set rc [catch {sqlite3_bind_text 0 1 hello 5} msg]
|
||||
lappend rc $msg
|
||||
} {1 SQLITE_MISUSE}
|
||||
}
|
||||
|
||||
# Ticket #1650: Honor the nBytes parameter to sqlite3_prepare.
|
||||
#
|
||||
|
||||
+21
-15
@@ -169,16 +169,18 @@ do_test capi3c-3.4 {
|
||||
do_test capi3c-3.5 {
|
||||
sqlite3_close $db2
|
||||
} {SQLITE_OK}
|
||||
do_test capi3c-3.6.1-misuse {
|
||||
sqlite3_close $db2
|
||||
} {SQLITE_MISUSE}
|
||||
do_test capi3c-3.6.2-misuse {
|
||||
sqlite3_errmsg $db2
|
||||
} {library routine called out of sequence}
|
||||
ifcapable {utf16} {
|
||||
do_test capi3c-3.6.3-misuse {
|
||||
utf8 [sqlite3_errmsg16 $db2]
|
||||
if {[clang_sanitize_address]==0} {
|
||||
do_test capi3c-3.6.1-misuse {
|
||||
sqlite3_close $db2
|
||||
} {SQLITE_MISUSE}
|
||||
do_test capi3c-3.6.2-misuse {
|
||||
sqlite3_errmsg $db2
|
||||
} {library routine called out of sequence}
|
||||
ifcapable {utf16} {
|
||||
do_test capi3c-3.6.3-misuse {
|
||||
utf8 [sqlite3_errmsg16 $db2]
|
||||
} {library routine called out of sequence}
|
||||
}
|
||||
}
|
||||
|
||||
# rename sqlite3_open ""
|
||||
@@ -627,13 +629,17 @@ check_data $STMT capi3c-6.3 {INTEGER} {1} {1.0} {1}
|
||||
do_test capi3c-6.3 {
|
||||
sqlite3_finalize $STMT
|
||||
} {SQLITE_OK}
|
||||
do_test capi3c-6.4 {
|
||||
db cache flush
|
||||
sqlite3_close $DB
|
||||
} {SQLITE_OK}
|
||||
do_test capi3c-6.99-misuse {
|
||||
if {[clang_sanitize_address]==0} {
|
||||
do_test capi3c-6.4 {
|
||||
db cache flush
|
||||
sqlite3_close $DB
|
||||
} {SQLITE_OK}
|
||||
do_test capi3c-6.99-misuse {
|
||||
db close
|
||||
} {}
|
||||
} else {
|
||||
db close
|
||||
} {}
|
||||
}
|
||||
|
||||
# This procedure sets the value of the file-format in file 'test.db'
|
||||
# to $newval. Also, the schema cookie is incremented.
|
||||
|
||||
+75
-25
@@ -15,51 +15,68 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix closure01
|
||||
|
||||
ifcapable !vtab { finish_test ; return }
|
||||
ifcapable !vtab||!cte { finish_test ; return }
|
||||
|
||||
load_static_extension db closure
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
BEGIN;
|
||||
CREATE TABLE t1(x INTEGER PRIMARY KEY, y INTEGER);
|
||||
WITH RECURSIVE
|
||||
cnt(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM cnt LIMIT 131072)
|
||||
INSERT INTO t1(x, y) SELECT i, nullif(i,1)/2 FROM cnt;
|
||||
CREATE INDEX t1y ON t1(y);
|
||||
INSERT INTO t1(x) VALUES(1),(2);
|
||||
INSERT INTO t1(x) SELECT x+2 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+4 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+8 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+16 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+32 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+64 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+128 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+256 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+512 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+1024 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+2048 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+4096 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+8192 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+16384 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+32768 FROM t1;
|
||||
INSERT INTO t1(x) SELECT x+65536 FROM t1;
|
||||
UPDATE t1 SET y=x/2 WHERE x>1;
|
||||
COMMIT;
|
||||
CREATE VIRTUAL TABLE cx
|
||||
USING transitive_closure(tablename=t1, idcolumn=x, parentcolumn=y);
|
||||
} {}
|
||||
|
||||
# The entire table
|
||||
do_execsql_test 1.1 {
|
||||
do_timed_execsql_test 1.1 {
|
||||
SELECT count(*), depth FROM cx WHERE root=1 GROUP BY depth ORDER BY 1;
|
||||
} {/1 0 1 17 2 1 4 2 8 3 16 4 .* 65536 16/}
|
||||
do_timed_execsql_test 1.1-cte {
|
||||
WITH RECURSIVE
|
||||
below(id,depth) AS (
|
||||
VALUES(1,0)
|
||||
UNION ALL
|
||||
SELECT t1.x, below.depth+1
|
||||
FROM t1 JOIN below on t1.y=below.id
|
||||
)
|
||||
SELECT count(*), depth FROM below GROUP BY depth ORDER BY 1;
|
||||
} {/1 0 1 17 2 1 4 2 8 3 16 4 .* 65536 16/}
|
||||
|
||||
# descendents of 32768
|
||||
do_execsql_test 1.2 {
|
||||
do_timed_execsql_test 1.2 {
|
||||
SELECT * FROM cx WHERE root=32768 ORDER BY id;
|
||||
} {32768 0 65536 1 65537 1 131072 2}
|
||||
do_timed_execsql_test 1.2-cte {
|
||||
WITH RECURSIVE
|
||||
below(id,depth) AS (
|
||||
VALUES(32768,0)
|
||||
UNION ALL
|
||||
SELECT t1.x, below.depth+1
|
||||
FROM t1 JOIN below on t1.y=below.id
|
||||
WHERE below.depth<2
|
||||
)
|
||||
SELECT id, depth FROM below ORDER BY id;
|
||||
} {32768 0 65536 1 65537 1 131072 2}
|
||||
|
||||
# descendents of 16384
|
||||
do_execsql_test 1.3 {
|
||||
do_timed_execsql_test 1.3 {
|
||||
SELECT * FROM cx WHERE root=16384 AND depth<=2 ORDER BY id;
|
||||
} {16384 0 32768 1 32769 1 65536 2 65537 2 65538 2 65539 2}
|
||||
do_timed_execsql_test 1.3-cte {
|
||||
WITH RECURSIVE
|
||||
below(id,depth) AS (
|
||||
VALUES(16384,0)
|
||||
UNION ALL
|
||||
SELECT t1.x, below.depth+1
|
||||
FROM t1 JOIN below on t1.y=below.id
|
||||
WHERE below.depth<2
|
||||
)
|
||||
SELECT id, depth FROM below ORDER BY id;
|
||||
} {16384 0 32768 1 32769 1 65536 2 65537 2 65538 2 65539 2}
|
||||
|
||||
# children of 16384
|
||||
do_execsql_test 1.4 {
|
||||
@@ -70,19 +87,41 @@ do_execsql_test 1.4 {
|
||||
} {32768 1 {} t1 x y 32769 1 {} t1 x y}
|
||||
|
||||
# great-grandparent of 16384
|
||||
do_execsql_test 1.5 {
|
||||
do_timed_execsql_test 1.5 {
|
||||
SELECT id, depth, root, tablename, idcolumn, parentcolumn FROM cx
|
||||
WHERE root=16384
|
||||
AND depth=3
|
||||
AND idcolumn='Y'
|
||||
AND parentcolumn='X';
|
||||
} {2048 3 {} t1 Y X}
|
||||
do_timed_execsql_test 1.5-cte {
|
||||
WITH RECURSIVE
|
||||
above(id,depth) AS (
|
||||
VALUES(16384,0)
|
||||
UNION ALL
|
||||
SELECT t1.y, above.depth+1
|
||||
FROM t1 JOIN above ON t1.x=above.id
|
||||
WHERE above.depth<3
|
||||
)
|
||||
SELECT id FROM above WHERE depth=3;
|
||||
} {2048}
|
||||
|
||||
# depth<5
|
||||
do_execsql_test 1.6 {
|
||||
do_timed_execsql_test 1.6 {
|
||||
SELECT count(*), depth FROM cx WHERE root=1 AND depth<5
|
||||
GROUP BY depth ORDER BY 1;
|
||||
} {1 0 2 1 4 2 8 3 16 4}
|
||||
do_timed_execsql_test 1.6-cte {
|
||||
WITH RECURSIVE
|
||||
below(id,depth) AS (
|
||||
VALUES(1,0)
|
||||
UNION ALL
|
||||
SELECT t1.x, below.depth+1
|
||||
FROM t1 JOIN below ON t1.y=below.id
|
||||
WHERE below.depth<4
|
||||
)
|
||||
SELECT count(*), depth FROM below GROUP BY depth ORDER BY 1;
|
||||
} {1 0 2 1 4 2 8 3 16 4}
|
||||
|
||||
# depth<=5
|
||||
do_execsql_test 1.7 {
|
||||
@@ -103,9 +142,20 @@ do_execsql_test 1.9 {
|
||||
} {8 3 16 4 32 5}
|
||||
|
||||
# depth==5 with min() and max()
|
||||
do_execsql_test 1.10 {
|
||||
do_timed_execsql_test 1.10 {
|
||||
SELECT count(*), min(id), max(id) FROM cx WHERE root=1 AND depth=5;
|
||||
} {32 32 63}
|
||||
do_timed_execsql_test 1.10-cte {
|
||||
WITH RECURSIVE
|
||||
below(id,depth) AS (
|
||||
VALUES(1,0)
|
||||
UNION ALL
|
||||
SELECT t1.x, below.depth+1
|
||||
FROM t1 JOIN below ON t1.y=below.id
|
||||
WHERE below.depth<5
|
||||
)
|
||||
SELECT count(*), min(id), max(id) FROM below WHERE depth=5;
|
||||
} {32 32 63}
|
||||
|
||||
# Create a much smaller table t2 with only 32 elements
|
||||
db eval {
|
||||
|
||||
@@ -75,7 +75,6 @@ do_test collate1-1.1 {
|
||||
}
|
||||
} {{} 0x119 0x2D}
|
||||
do_test collate1-1.2 {
|
||||
breakpoint
|
||||
execsql {
|
||||
SELECT c2 FROM collate1t1 ORDER BY 1 COLLATE hex;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
# 2014-01-20
|
||||
#
|
||||
# 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 corruptH
|
||||
|
||||
# Do not use a codec for tests in this file, as the database file is
|
||||
# manipulated directly using tcl scripts (using the [hexio_write] command).
|
||||
#
|
||||
do_not_use_codec
|
||||
database_may_be_corrupt
|
||||
|
||||
# Initialize the database.
|
||||
#
|
||||
do_execsql_test 1.1 {
|
||||
PRAGMA page_size=1024;
|
||||
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, 'one');
|
||||
INSERT INTO t1 VALUES(2, 'two');
|
||||
|
||||
CREATE TABLE t2(x);
|
||||
INSERT INTO t2 VALUES(randomblob(200));
|
||||
INSERT INTO t2 SELECT randomblob(200) FROM t2;
|
||||
INSERT INTO t2 SELECT randomblob(200) FROM t2;
|
||||
INSERT INTO t2 SELECT randomblob(200) FROM t2;
|
||||
INSERT INTO t2 SELECT randomblob(200) FROM t2;
|
||||
INSERT INTO t2 SELECT randomblob(200) FROM t2;
|
||||
INSERT INTO t2 SELECT randomblob(200) FROM t2;
|
||||
} {}
|
||||
|
||||
# Corrupt the file so that the root page of t1 is also linked into t2 as
|
||||
# a leaf page.
|
||||
#
|
||||
do_test 1.2 {
|
||||
db eval { SELECT name, rootpage FROM sqlite_master } {
|
||||
set r($name) $rootpage
|
||||
}
|
||||
db close
|
||||
hexio_write test.db [expr {($r(t2)-1)*1024 + 11}] [format %.2X $r(t1)]
|
||||
sqlite3 db test.db
|
||||
} {}
|
||||
|
||||
do_test 1.3 {
|
||||
db eval { PRAGMA secure_delete=1 }
|
||||
list [catch {
|
||||
db eval { SELECT * FROM t1 WHERE a IN (1, 2) } {
|
||||
db eval { DELETE FROM t2 }
|
||||
}
|
||||
} msg] $msg
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
# Initialize the database.
|
||||
#
|
||||
do_execsql_test 2.1 {
|
||||
PRAGMA auto_vacuum=0;
|
||||
PRAGMA page_size=1024;
|
||||
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, 'one');
|
||||
INSERT INTO t1 VALUES(2, 'two');
|
||||
|
||||
CREATE TABLE t3(x);
|
||||
|
||||
CREATE TABLE t2(x PRIMARY KEY) WITHOUT ROWID;
|
||||
INSERT INTO t2 VALUES(randomblob(100));
|
||||
|
||||
DROP TABLE t3;
|
||||
} {}
|
||||
|
||||
do_test 2.2 {
|
||||
db eval { SELECT name, rootpage FROM sqlite_master } {
|
||||
set r($name) $rootpage
|
||||
}
|
||||
db close
|
||||
set fl [hexio_get_int [hexio_read test.db 32 4]]
|
||||
|
||||
hexio_write test.db [expr {($fl-1) * 1024 + 0}] 00000000
|
||||
hexio_write test.db [expr {($fl-1) * 1024 + 4}] 00000001
|
||||
hexio_write test.db [expr {($fl-1) * 1024 + 8}] [format %.8X $r(t1)]
|
||||
hexio_write test.db 36 00000002
|
||||
|
||||
sqlite3 db test.db
|
||||
} {}
|
||||
|
||||
|
||||
# The corruption migration caused by the test case below does not
|
||||
# cause corruption to be detected in mmap mode.
|
||||
#
|
||||
# The trick here is that the root page of the tree scanned by the outer
|
||||
# query is also currently on the free-list. So while the first seek on
|
||||
# the table (for a==1) works, by the time the second is attempted The
|
||||
# "INSERT INTO t2..." statements have recycled the root page of t1 and
|
||||
# used it as an index leaf. Normally, BtreeMovetoUnpacked() detects
|
||||
# that the PgHdr object associated with said root page does not match
|
||||
# the cursor (as it is now marked with PgHdr.intKey==0) and returns
|
||||
# SQLITE_CORRUPT.
|
||||
#
|
||||
# However, in mmap mode, the outer query and the inner queries use
|
||||
# different PgHdr objects (same data, but different PgHdr container
|
||||
# objects). And so the corruption is not detected. Instead, the second
|
||||
# seek fails to find anything and only a single row is returned.
|
||||
#
|
||||
set res23 {1 {database disk image is malformed}}
|
||||
if {[permutation]=="mmap"} {
|
||||
set res23 {0 one}
|
||||
}
|
||||
do_test 2.3 {
|
||||
list [catch {
|
||||
set res [list]
|
||||
db eval { SELECT * FROM t1 WHERE a IN (1, 2) } {
|
||||
db eval {
|
||||
INSERT INTO t2 SELECT randomblob(100) FROM t2;
|
||||
INSERT INTO t2 SELECT randomblob(100) FROM t2;
|
||||
INSERT INTO t2 SELECT randomblob(100) FROM t2;
|
||||
INSERT INTO t2 SELECT randomblob(100) FROM t2;
|
||||
INSERT INTO t2 SELECT randomblob(100) FROM t2;
|
||||
}
|
||||
lappend res $b
|
||||
}
|
||||
set res
|
||||
} msg] $msg
|
||||
} $res23
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
|
||||
# Initialize the database.
|
||||
#
|
||||
do_execsql_test 3.1 {
|
||||
PRAGMA page_size=1024;
|
||||
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, 'one');
|
||||
INSERT INTO t1 VALUES(2, 'two');
|
||||
|
||||
CREATE TABLE t2(c INTEGER PRAGMA KEY, d);
|
||||
INSERT INTO t2 VALUES(1, randomblob(1100));
|
||||
} {}
|
||||
|
||||
do_test 3.2 {
|
||||
db eval { SELECT name, rootpage FROM sqlite_master } {
|
||||
set r($name) $rootpage
|
||||
}
|
||||
db close
|
||||
|
||||
hexio_write test.db [expr {($r(t2)-1) * 1024 + 1020}] 00000002
|
||||
|
||||
sqlite3 db test.db
|
||||
} {}
|
||||
|
||||
do_test 3.3 {
|
||||
list [catch {
|
||||
db eval { SELECT * FROM t1 WHERE a IN (1, 2) } {
|
||||
db eval {
|
||||
DELETE FROM t2 WHERE c=1;
|
||||
}
|
||||
}
|
||||
} msg] $msg
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
finish_test
|
||||
|
||||
+39
-32
@@ -2946,38 +2946,45 @@ proc test_on_update_recursion {limit} {
|
||||
"
|
||||
}
|
||||
|
||||
do_test e_fkey-63.1.1 {
|
||||
test_on_delete_recursion $SQLITE_MAX_TRIGGER_DEPTH
|
||||
} {0 0}
|
||||
do_test e_fkey-63.1.2 {
|
||||
test_on_delete_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1]
|
||||
} {1 {too many levels of trigger recursion}}
|
||||
do_test e_fkey-63.1.3 {
|
||||
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5
|
||||
test_on_delete_recursion 5
|
||||
} {0 0}
|
||||
do_test e_fkey-63.1.4 {
|
||||
test_on_delete_recursion 6
|
||||
} {1 {too many levels of trigger recursion}}
|
||||
do_test e_fkey-63.1.5 {
|
||||
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000
|
||||
} {5}
|
||||
do_test e_fkey-63.2.1 {
|
||||
test_on_update_recursion $SQLITE_MAX_TRIGGER_DEPTH
|
||||
} {0 0}
|
||||
do_test e_fkey-63.2.2 {
|
||||
test_on_update_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1]
|
||||
} {1 {too many levels of trigger recursion}}
|
||||
do_test e_fkey-63.2.3 {
|
||||
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5
|
||||
test_on_update_recursion 5
|
||||
} {0 0}
|
||||
do_test e_fkey-63.2.4 {
|
||||
test_on_update_recursion 6
|
||||
} {1 {too many levels of trigger recursion}}
|
||||
do_test e_fkey-63.2.5 {
|
||||
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000
|
||||
} {5}
|
||||
# If the current build was created using clang with the -fsanitize=address
|
||||
# switch, then the library uses considerably more stack space than usual.
|
||||
# So much more, that some of the following tests cause stack overflows
|
||||
# if they are run under this configuration.
|
||||
#
|
||||
if {[clang_sanitize_address]==0} {
|
||||
do_test e_fkey-63.1.1 {
|
||||
test_on_delete_recursion $SQLITE_MAX_TRIGGER_DEPTH
|
||||
} {0 0}
|
||||
do_test e_fkey-63.1.2 {
|
||||
test_on_delete_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1]
|
||||
} {1 {too many levels of trigger recursion}}
|
||||
do_test e_fkey-63.1.3 {
|
||||
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5
|
||||
test_on_delete_recursion 5
|
||||
} {0 0}
|
||||
do_test e_fkey-63.1.4 {
|
||||
test_on_delete_recursion 6
|
||||
} {1 {too many levels of trigger recursion}}
|
||||
do_test e_fkey-63.1.5 {
|
||||
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000
|
||||
} {5}
|
||||
do_test e_fkey-63.2.1 {
|
||||
test_on_update_recursion $SQLITE_MAX_TRIGGER_DEPTH
|
||||
} {0 0}
|
||||
do_test e_fkey-63.2.2 {
|
||||
test_on_update_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1]
|
||||
} {1 {too many levels of trigger recursion}}
|
||||
do_test e_fkey-63.2.3 {
|
||||
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5
|
||||
test_on_update_recursion 5
|
||||
} {0 0}
|
||||
do_test e_fkey-63.2.4 {
|
||||
test_on_update_recursion 6
|
||||
} {1 {too many levels of trigger recursion}}
|
||||
do_test e_fkey-63.2.5 {
|
||||
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000
|
||||
} {5}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The setting of the recursive_triggers pragma does not affect foreign
|
||||
|
||||
+28
-30
@@ -333,9 +333,9 @@ do_select_tests e_select-1.1 {
|
||||
6 "SELECT count(*) WHERE 1" {1}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-48114-33255 If there is only a single table in the
|
||||
# join-source following the FROM clause, then the input data used by the
|
||||
# SELECT statement is the contents of the named table.
|
||||
# EVIDENCE-OF: R-45424-07352 If there is only a single table or subquery
|
||||
# in the FROM clause, then the input data used by the SELECT statement
|
||||
# is the contents of the named table.
|
||||
#
|
||||
# The results of the SELECT queries suggest that they are operating on the
|
||||
# contents of the table 'xx'.
|
||||
@@ -357,10 +357,10 @@ do_select_tests e_select-1.2 {
|
||||
3 "SELECT sum(x), sum(y) FROM xx" {-17.89 -16.87}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-23593-12456 If there is more than one table specified
|
||||
# as part of the join-source following the FROM keyword, then the
|
||||
# contents of each named table are joined into a single dataset for the
|
||||
# simple SELECT statement to operate on.
|
||||
# EVIDENCE-OF: R-28355-09804 If there is more than one table or subquery
|
||||
# in FROM clause then the contents of all tables and/or subqueries are
|
||||
# joined into a single dataset for the simple SELECT statement to
|
||||
# operate on.
|
||||
#
|
||||
# There are more detailed tests for subsequent requirements that add
|
||||
# more detail to this idea. We just add a single test that shows that
|
||||
@@ -383,10 +383,10 @@ do_select_tests e_select-1.3 {
|
||||
# of cartesian joins in the SELECT documentation is consistent with SQLite.
|
||||
# In doing so, we test the following three requirements as a side-effect:
|
||||
#
|
||||
# EVIDENCE-OF: R-46122-14930 If the join-op is "CROSS JOIN", "INNER
|
||||
# JOIN", "JOIN" or a comma (",") and there is no ON or USING clause,
|
||||
# then the result of the join is simply the cartesian product of the
|
||||
# left and right-hand datasets.
|
||||
# EVIDENCE-OF: R-49872-03192 If the join-operator is "CROSS JOIN",
|
||||
# "INNER JOIN", "JOIN" or a comma (",") and there is no ON or USING
|
||||
# clause, then the result of the join is simply the cartesian product of
|
||||
# the left and right-hand datasets.
|
||||
#
|
||||
# The tests are built on this assertion. Really, they test that the output
|
||||
# of a CROSS JOIN, JOIN, INNER JOIN or "," join matches the expected result
|
||||
@@ -513,11 +513,10 @@ do_select_tests e_select-1.4.5 [list \
|
||||
4 { SELECT * FROM t1 AS y INNER JOIN t1 AS x } $t1_cross_t1 \
|
||||
]
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-22775-56496 If there is an ON clause specified, then
|
||||
# the ON expression is evaluated for each row of the cartesian product
|
||||
# as a boolean expression. All rows for which the expression evaluates
|
||||
# to false are excluded from the dataset.
|
||||
# EVIDENCE-OF: R-38465-03616 If there is an ON clause then the ON
|
||||
# expression is evaluated for each row of the cartesian product as a
|
||||
# boolean expression. Only rows for which the expression evaluates to
|
||||
# true are included from the dataset.
|
||||
#
|
||||
foreach {tn select res} [list \
|
||||
1 { SELECT * FROM t1 %JOIN% t2 ON (1) } $t1_cross_t2 \
|
||||
@@ -540,9 +539,9 @@ foreach {tn select res} [list \
|
||||
do_join_test e_select-1.3.$tn $select $res
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-63358-54862 If there is a USING clause specified as
|
||||
# part of the join-constraint, then each of the column names specified
|
||||
# must exist in the datasets to both the left and right of the join-op.
|
||||
# EVIDENCE-OF: R-49933-05137 If there is a USING clause then each of the
|
||||
# column names specified must exist in the datasets to both the left and
|
||||
# right of the join-operator.
|
||||
#
|
||||
do_select_tests e_select-1.4 -error {
|
||||
cannot join using column %s - column not present in both tables
|
||||
@@ -552,10 +551,10 @@ do_select_tests e_select-1.4 -error {
|
||||
3 { SELECT * FROM t3, (SELECT a AS b, b AS c FROM t1) USING (a) } "a"
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-55987-04584 For each pair of namesake columns, the
|
||||
# EVIDENCE-OF: R-22776-52830 For each pair of named columns, the
|
||||
# expression "lhs.X = rhs.X" is evaluated for each row of the cartesian
|
||||
# product as a boolean expression. All rows for which one or more of the
|
||||
# expressions evaluates to false are excluded from the result set.
|
||||
# product as a boolean expression. Only rows for which all such
|
||||
# expressions evaluates to true are included from the result set.
|
||||
#
|
||||
do_select_tests e_select-1.5 {
|
||||
1 { SELECT * FROM t1, t3 USING (a) } {a one 1 b two 2}
|
||||
@@ -566,8 +565,8 @@ do_select_tests e_select-1.5 {
|
||||
# USING clause, the normal rules for handling affinities, collation
|
||||
# sequences and NULL values in comparisons apply.
|
||||
#
|
||||
# EVIDENCE-OF: R-35466-18578 The column from the dataset on the
|
||||
# left-hand side of the join operator is considered to be on the
|
||||
# EVIDENCE-OF: R-38422-04402 The column from the dataset on the
|
||||
# left-hand side of the join-operator is considered to be on the
|
||||
# left-hand side of the comparison operator (=) for the purposes of
|
||||
# collation sequence and affinity precedence.
|
||||
#
|
||||
@@ -622,10 +621,9 @@ foreach {tn select res} {
|
||||
} {
|
||||
do_join_test e_select-1.7.$tn $select $res
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-41434-12448 If the join-op is a "LEFT JOIN" or "LEFT
|
||||
# OUTER JOIN", then after the ON or USING filtering clauses have been
|
||||
# applied, an extra row is added to the output for each row in the
|
||||
# EVIDENCE-OF: R-42531-52874 If the join-operator is a "LEFT JOIN" or
|
||||
# "LEFT OUTER JOIN", then after the ON or USING filtering clauses have
|
||||
# been applied, an extra row is added to the output for each row in the
|
||||
# original left-hand input dataset that corresponds to no rows at all in
|
||||
# the composite dataset (if any).
|
||||
#
|
||||
@@ -660,8 +658,8 @@ do_select_tests e_select-1.9 {
|
||||
2b "SELECT * FROM t7 LEFT JOIN t8 USING (a)" {x ex 24 abc 24 y why 25 {} {}}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-01809-52134 If the NATURAL keyword is added to any of
|
||||
# the join-ops, then an implicit USING clause is added to the
|
||||
# EVIDENCE-OF: R-04932-55942 If the NATURAL keyword is in the
|
||||
# join-operator then an implicit USING clause is added to the
|
||||
# join-constraints. The implicit USING clause contains each of the
|
||||
# column names that appear in both the left and right-hand input
|
||||
# datasets.
|
||||
|
||||
+15
-15
@@ -344,10 +344,10 @@ foreach {tn indexes} {
|
||||
catchsql { DROP INDEX i3 }
|
||||
execsql $indexes
|
||||
|
||||
# EVIDENCE-OF: R-46122-14930 If the join-op is "CROSS JOIN", "INNER
|
||||
# JOIN", "JOIN" or a comma (",") and there is no ON or USING clause,
|
||||
# then the result of the join is simply the cartesian product of the
|
||||
# left and right-hand datasets.
|
||||
# EVIDENCE-OF: R-49872-03192 If the join-operator is "CROSS JOIN",
|
||||
# "INNER JOIN", "JOIN" or a comma (",") and there is no ON or USING
|
||||
# clause, then the result of the join is simply the cartesian product of
|
||||
# the left and right-hand datasets.
|
||||
#
|
||||
# EVIDENCE-OF: R-46256-57243 There is no difference between the "INNER
|
||||
# JOIN", "JOIN" and "," join operators.
|
||||
@@ -368,10 +368,10 @@ foreach {tn indexes} {
|
||||
test_join $tn.1.11 "t2 CROSS JOIN t2 AS x" {t2 t2}
|
||||
test_join $tn.1.12 "t2 JOIN t2 AS x" {t2 t2}
|
||||
|
||||
# EVIDENCE-OF: R-22775-56496 If there is an ON clause specified, then
|
||||
# the ON expression is evaluated for each row of the cartesian product
|
||||
# as a boolean expression. All rows for which the expression evaluates
|
||||
# to false are excluded from the dataset.
|
||||
# EVIDENCE-OF: R-38465-03616 If there is an ON clause then the ON
|
||||
# expression is evaluated for each row of the cartesian product as a
|
||||
# boolean expression. Only rows for which the expression evaluates to
|
||||
# true are included from the dataset.
|
||||
#
|
||||
test_join $tn.2.1 "t1, t2 ON (t1.a=t2.a)" {t1 t2 -on {te_equals a a}}
|
||||
test_join $tn.2.2 "t2, t1 ON (t1.a=t2.a)" {t2 t1 -on {te_equals a a}}
|
||||
@@ -504,14 +504,14 @@ do_execsql_test e_select-2.2.0 {
|
||||
INSERT INTO t5 VALUES(2, 'two');
|
||||
} {}
|
||||
|
||||
# EVIDENCE-OF: R-55824-40976 A sub-select specified in the join-source
|
||||
# following the FROM clause in a simple SELECT statement is handled as
|
||||
# if it was a table containing the data returned by executing the
|
||||
# sub-select statement.
|
||||
# EVIDENCE-OF: R-59237-46742 A subquery specified in the
|
||||
# table-or-subquery following the FROM clause in a simple SELECT
|
||||
# statement is handled as if it was a table containing the data returned
|
||||
# by executing the subquery statement.
|
||||
#
|
||||
# EVIDENCE-OF: R-42612-06757 Each column of the sub-select dataset
|
||||
# inherits the collation sequence and affinity of the corresponding
|
||||
# expression in the sub-select statement.
|
||||
# EVIDENCE-OF: R-27438-53558 Each column of the subquery has the
|
||||
# collation sequence and affinity of the corresponding expression in the
|
||||
# subquery statement.
|
||||
#
|
||||
foreach {tn subselect select spec} {
|
||||
1 "SELECT * FROM t2" "SELECT * FROM t1 JOIN %ss%"
|
||||
|
||||
@@ -301,7 +301,6 @@ do_test exclusive2-3.3 {
|
||||
readPagerChangeCounter test.db
|
||||
} {4}
|
||||
do_test exclusive2-3.4 {
|
||||
breakpoint
|
||||
execsql {
|
||||
INSERT INTO t1 VALUES(randstr(200, 200));
|
||||
}
|
||||
|
||||
@@ -146,7 +146,6 @@ do_test fts3aa-3.3 {
|
||||
execsql {SELECT rowid FROM t1 WHERE content MATCH '-two one'}
|
||||
} {1 5 9 13 17 21 25 29}
|
||||
|
||||
breakpoint
|
||||
do_test fts3aa-4.1 {
|
||||
execsql {SELECT rowid FROM t1 WHERE content MATCH 'one OR two'}
|
||||
} {1 2 3 5 6 7 9 10 11 13 14 15 17 18 19 21 22 23 25 26 27 29 30 31}
|
||||
|
||||
@@ -115,7 +115,6 @@ for {set i 1} {$i<=15} {incr i} {
|
||||
db eval "INSERT INTO t4(norm,plusone,invert) VALUES([join $vset ,]);"
|
||||
}
|
||||
|
||||
breakpoint
|
||||
do_test fts3ab-4.1 {
|
||||
execsql {SELECT rowid FROM t4 WHERE t4 MATCH 'norm:one'}
|
||||
} {1 3 5 7 9 11 13 15}
|
||||
|
||||
@@ -78,7 +78,6 @@ do_test fts3ag-1.10 {
|
||||
# Test that docListOrMerge() correctly handles reaching the end of one
|
||||
# doclist before it reaches the end of the other.
|
||||
do_test fts3ag-1.11 {
|
||||
breakpoint
|
||||
execsql {SELECT rowid FROM t1 WHERE t1 MATCH 'this OR also'}
|
||||
} {1 2}
|
||||
do_test fts3ag-1.12 {
|
||||
|
||||
@@ -253,7 +253,6 @@ check_doclist fts3d-4.4.10 1 0 was {[2 0[1]]}
|
||||
|
||||
# Optimize should leave the result in the level of the highest-level
|
||||
# prior segment.
|
||||
breakpoint
|
||||
do_test fts3d-4.5 {
|
||||
execsql {
|
||||
SELECT OPTIMIZE(t1) FROM t1 LIMIT 1;
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
# 2014 January 4
|
||||
#
|
||||
# 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. The
|
||||
# focus of this script is testing the FTS3 module.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix fts3join
|
||||
|
||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
ifcapable !fts3 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE ft1 USING fts4(x);
|
||||
INSERT INTO ft1 VALUES('aaa aaa');
|
||||
INSERT INTO ft1 VALUES('aaa bbb');
|
||||
INSERT INTO ft1 VALUES('bbb aaa');
|
||||
INSERT INTO ft1 VALUES('bbb bbb');
|
||||
|
||||
CREATE TABLE t1(id, y);
|
||||
INSERT INTO t1 VALUES(1, 'aaa');
|
||||
INSERT INTO t1 VALUES(2, 'bbb');
|
||||
}
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT docid FROM ft1, t1 WHERE ft1 MATCH y AND id=1;
|
||||
} {1 2 3}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
SELECT docid FROM ft1, t1 WHERE ft1 MATCH y AND id=1 ORDER BY docid;
|
||||
} {1 2 3}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE ft2 USING fts4(x);
|
||||
CREATE VIRTUAL TABLE ft3 USING fts4(y);
|
||||
|
||||
INSERT INTO ft2 VALUES('abc');
|
||||
INSERT INTO ft2 VALUES('def');
|
||||
INSERT INTO ft3 VALUES('ghi');
|
||||
INSERT INTO ft3 VALUES('abc');
|
||||
}
|
||||
|
||||
do_execsql_test 2.1 { SELECT * FROM ft2, ft3 WHERE x MATCH y; } {abc abc}
|
||||
do_execsql_test 2.2 { SELECT * FROM ft2, ft3 WHERE y MATCH x; } {abc abc}
|
||||
do_execsql_test 2.3 { SELECT * FROM ft3, ft2 WHERE x MATCH y; } {abc abc}
|
||||
do_execsql_test 2.4 { SELECT * FROM ft3, ft2 WHERE y MATCH x; } {abc abc}
|
||||
|
||||
do_catchsql_test 2.5 {
|
||||
SELECT * FROM ft3, ft2 WHERE y MATCH x AND x MATCH y;
|
||||
} {1 {unable to use function MATCH in the requested context}}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -165,7 +165,6 @@ do_test fts3near-3.6 {
|
||||
SELECT offsets(t1) FROM t1 WHERE content MATCH 'three NEAR/0 "two four"'
|
||||
}
|
||||
} {{0 0 8 5 0 1 14 3 0 2 18 4}}
|
||||
breakpoint
|
||||
do_test fts3near-3.7 {
|
||||
execsql {
|
||||
SELECT offsets(t1) FROM t1 WHERE content MATCH '"two four" NEAR/0 three'}
|
||||
|
||||
@@ -90,7 +90,6 @@ do_execsql_test 1.13.1 {
|
||||
INSERT INTO c1(x) VALUES('a b c');
|
||||
INSERT INTO c1(x) VALUES('d e f');
|
||||
}
|
||||
breakpoint
|
||||
do_execsql_test 1.13.2 {
|
||||
SELECT * FROM c1, t1 WHERE input = x AND c1.rowid=t1.rowid;
|
||||
} {
|
||||
|
||||
@@ -392,7 +392,6 @@ foreach T $tokenizers {
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that the private use ranges are treated as alphanumeric.
|
||||
#
|
||||
breakpoint
|
||||
foreach {tn1 c} {
|
||||
1 \ue000 2 \ue001 3 \uf000 4 \uf8fe 5 \uf8ff
|
||||
} {
|
||||
@@ -557,7 +556,3 @@ do_execsql_test 11.1 {
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+33
-3
@@ -9,13 +9,15 @@
|
||||
#
|
||||
#*************************************************************************
|
||||
#
|
||||
# Verify that constant string expressions that get factored into initializing
|
||||
# code are not reused between function parameters and other values in the
|
||||
# VDBE program, as the function might have changed the encoding.
|
||||
# Testing of function factoring and the SQLITE_DETERMINISTIC flag.
|
||||
#
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# Verify that constant string expressions that get factored into initializing
|
||||
# code are not reused between function parameters and other values in the
|
||||
# VDBE program, as the function might have changed the encoding.
|
||||
#
|
||||
do_execsql_test func5-1.1 {
|
||||
PRAGMA encoding=UTF16le;
|
||||
CREATE TABLE t1(x,a,b,c);
|
||||
@@ -30,4 +32,32 @@ do_execsql_test func5-1.2 {
|
||||
SELECT x FROM t1 WHERE a='abcdefg' OR c=instr('abcdefg',b) ORDER BY +x;
|
||||
} {2 4}
|
||||
|
||||
# Verify that SQLITE_DETERMINISTIC functions get factored out of the
|
||||
# evaluation loop whereas non-deterministic functions do not. counter1()
|
||||
# is marked as non-deterministic and so is not factored out of the loop,
|
||||
# and it really is non-deterministic, returning a different result each
|
||||
# time. But counter2() is marked as deterministic, so it does get factored
|
||||
# out of the loop. counter2() has the same implementation as counter1(),
|
||||
# returning a different result on each invocation, but because it is
|
||||
# only invoked once outside of the loop, it appears to return the same
|
||||
# result multiple times.
|
||||
#
|
||||
do_execsql_test func5-2.1 {
|
||||
CREATE TABLE t2(x,y);
|
||||
INSERT INTO t2 VALUES(1,2),(3,4),(5,6),(7,8);
|
||||
SELECT x, y FROM t2 WHERE x+5=5+x ORDER BY +x;
|
||||
} {1 2 3 4 5 6 7 8}
|
||||
sqlite3_create_function db
|
||||
do_execsql_test func5-2.2 {
|
||||
SELECT x, y FROM t2
|
||||
WHERE x+counter1('hello')=counter1('hello')+x
|
||||
ORDER BY +x;
|
||||
} {}
|
||||
do_execsql_test func5-2.3 {
|
||||
SELECT x, y FROM t2
|
||||
WHERE x+counter2('hello')=counter2('hello')+x
|
||||
ORDER BY +x;
|
||||
} {1 2 3 4 5 6 7 8}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -65,6 +65,7 @@ set kwlist {
|
||||
pragma
|
||||
query
|
||||
raise
|
||||
recursive
|
||||
regexp
|
||||
reindex
|
||||
release
|
||||
@@ -80,6 +81,8 @@ set kwlist {
|
||||
vacuum
|
||||
view
|
||||
virtual
|
||||
with
|
||||
without
|
||||
};
|
||||
set exprkw {
|
||||
cast
|
||||
|
||||
@@ -893,5 +893,60 @@ do_test like-11.10 {
|
||||
}
|
||||
} {abc abcd sort {} t11cb}
|
||||
|
||||
# A COLLATE clause on the pattern does not change the result of a
|
||||
# LIKE operator.
|
||||
#
|
||||
do_execsql_test like-12.1 {
|
||||
CREATE TABLE t12nc(id INTEGER, x TEXT UNIQUE COLLATE nocase);
|
||||
INSERT INTO t12nc VALUES(1,'abcde'),(2,'uvwxy'),(3,'ABCDEF');
|
||||
CREATE TABLE t12b(id INTEGER, x TEXT UNIQUE COLLATE binary);
|
||||
INSERT INTO t12b VALUES(1,'abcde'),(2,'uvwxy'),(3,'ABCDEF');
|
||||
SELECT id FROM t12nc WHERE x LIKE 'abc%' ORDER BY +id;
|
||||
} {1 3}
|
||||
do_execsql_test like-12.2 {
|
||||
SELECT id FROM t12b WHERE x LIKE 'abc%' ORDER BY +id;
|
||||
} {1 3}
|
||||
do_execsql_test like-12.3 {
|
||||
SELECT id FROM t12nc WHERE x LIKE 'abc%' COLLATE binary ORDER BY +id;
|
||||
} {1 3}
|
||||
do_execsql_test like-12.4 {
|
||||
SELECT id FROM t12b WHERE x LIKE 'abc%' COLLATE binary ORDER BY +id;
|
||||
} {1 3}
|
||||
do_execsql_test like-12.5 {
|
||||
SELECT id FROM t12nc WHERE x LIKE 'abc%' COLLATE nocase ORDER BY +id;
|
||||
} {1 3}
|
||||
do_execsql_test like-12.6 {
|
||||
SELECT id FROM t12b WHERE x LIKE 'abc%' COLLATE nocase ORDER BY +id;
|
||||
} {1 3}
|
||||
|
||||
# Adding a COLLATE clause to the pattern of a LIKE operator does nothing
|
||||
# to change the suitability of using an index to satisfy that LIKE
|
||||
# operator.
|
||||
#
|
||||
do_execsql_test like-12.11 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT id FROM t12nc WHERE x LIKE 'abc%' ORDER BY +id;
|
||||
} {/SEARCH/}
|
||||
do_execsql_test like-12.12 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT id FROM t12b WHERE x LIKE 'abc%' ORDER BY +id;
|
||||
} {/SCAN/}
|
||||
do_execsql_test like-12.13 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT id FROM t12nc WHERE x LIKE 'abc%' COLLATE nocase ORDER BY +id;
|
||||
} {/SEARCH/}
|
||||
do_execsql_test like-12.14 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT id FROM t12b WHERE x LIKE 'abc%' COLLATE nocase ORDER BY +id;
|
||||
} {/SCAN/}
|
||||
do_execsql_test like-12.15 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT id FROM t12nc WHERE x LIKE 'abc%' COLLATE binary ORDER BY +id;
|
||||
} {/SEARCH/}
|
||||
do_execsql_test like-12.16 {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT id FROM t12b WHERE x LIKE 'abc%' COLLATE binary ORDER BY +id;
|
||||
} {/SCAN/}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -592,4 +592,17 @@ do_test misc1-18.1 {
|
||||
expr {$n>=100}
|
||||
} {1}
|
||||
|
||||
# 2014-01-10: In a CREATE TABLE AS, if one or more of the column names
|
||||
# are an empty string, that is still OK.
|
||||
#
|
||||
do_execsql_test misc1-19.1 {
|
||||
CREATE TABLE t19 AS SELECT 1, 2 AS '', 3;
|
||||
SELECT * FROM t19;
|
||||
} {1 2 3}
|
||||
do_execsql_test misc1-19.2 {
|
||||
CREATE TABLE t19b AS SELECT 4 AS '', 5 AS '', 6 AS '';
|
||||
SELECT * FROM t19b;
|
||||
} {4 5 6}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+5
-3
@@ -15,9 +15,11 @@
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
do_test misc7-1-misuse {
|
||||
c_misuse_test
|
||||
} {}
|
||||
if {[clang_sanitize_address]==0} {
|
||||
do_test misc7-1-misuse {
|
||||
c_misuse_test
|
||||
} {}
|
||||
}
|
||||
|
||||
do_test misc7-2 {
|
||||
c_realloc_test
|
||||
|
||||
+32
-29
@@ -171,37 +171,40 @@ do_test misuse-4.3 {
|
||||
} msg]
|
||||
lappend v $msg $r
|
||||
} {0 {} SQLITE_BUSY}
|
||||
do_test misuse-4.4 {
|
||||
|
||||
if {[clang_sanitize_address]==0} {
|
||||
do_test misuse-4.4 {
|
||||
# Flush the TCL statement cache here, otherwise the sqlite3_close() will
|
||||
# fail because there are still un-finalized() VDBEs.
|
||||
db cache flush
|
||||
sqlite3_close $::DB
|
||||
catchsql2 {SELECT * FROM t1}
|
||||
} {1 {library routine called out of sequence}}
|
||||
do_test misuse-4.5 {
|
||||
catchsql {
|
||||
SELECT * FROM t1
|
||||
}
|
||||
} {1 {library routine called out of sequence}}
|
||||
db cache flush
|
||||
sqlite3_close $::DB
|
||||
catchsql2 {SELECT * FROM t1}
|
||||
} {1 {library routine called out of sequence}}
|
||||
do_test misuse-4.5 {
|
||||
catchsql {
|
||||
SELECT * FROM t1
|
||||
}
|
||||
} {1 {library routine called out of sequence}}
|
||||
|
||||
# Attempt to use a database after it has been closed.
|
||||
#
|
||||
do_test misuse-5.1 {
|
||||
db close
|
||||
sqlite3 db test2.db; set ::DB [sqlite3_connection_pointer db]
|
||||
execsql {
|
||||
SELECT * FROM t1
|
||||
}
|
||||
} {1 2}
|
||||
do_test misuse-5.2 {
|
||||
catchsql2 {SELECT * FROM t1}
|
||||
} {0 {a b 1 2}}
|
||||
do_test misuse-5.3 {
|
||||
db close
|
||||
set r [catch {
|
||||
sqlite3_prepare $::DB {SELECT * FROM t1} -1 TAIL
|
||||
} msg]
|
||||
lappend r $msg
|
||||
} {1 {(21) library routine called out of sequence}}
|
||||
# Attempt to use a database after it has been closed.
|
||||
#
|
||||
do_test misuse-5.1 {
|
||||
db close
|
||||
sqlite3 db test2.db; set ::DB [sqlite3_connection_pointer db]
|
||||
execsql {
|
||||
SELECT * FROM t1
|
||||
}
|
||||
} {1 2}
|
||||
do_test misuse-5.2 {
|
||||
catchsql2 {SELECT * FROM t1}
|
||||
} {0 {a b 1 2}}
|
||||
do_test misuse-5.3 {
|
||||
db close
|
||||
set r [catch {
|
||||
sqlite3_prepare $::DB {SELECT * FROM t1} -1 TAIL
|
||||
} msg]
|
||||
lappend r $msg
|
||||
} {1 {(21) library routine called out of sequence}}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -41,7 +41,6 @@ do_test 1-pre {
|
||||
do_faultsim_test 1 -prep {
|
||||
faultsim_restore_and_reopen
|
||||
db func a_string a_string
|
||||
breakpoint
|
||||
execsql {
|
||||
PRAGMA mmap_size = 1000000;
|
||||
PRAGMA cache_size = 5;
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
# 2013-12-06
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Tests for the SQLITE_READONLY_DBMOVED error condition: the database file
|
||||
# is unlinked or renamed out from under SQLite.
|
||||
#
|
||||
|
||||
if {$tcl_platform(platform)!="unix"} return
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
if {[permutation]=="inmemory_journal"} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# Create a database file for testing
|
||||
#
|
||||
do_execsql_test pager4-1.1 {
|
||||
CREATE TABLE t1(a,b,c);
|
||||
INSERT INTO t1 VALUES(673,'stone','philips');
|
||||
SELECT * FROM t1;
|
||||
} {673 stone philips}
|
||||
|
||||
# After renaming the database file while it is open, one can still
|
||||
# read from the database, but writing returns a READONLY error.
|
||||
#
|
||||
file delete -force test-xyz.db
|
||||
file rename test.db test-xyz.db
|
||||
do_catchsql_test pager4-1.2 {
|
||||
SELECT * FROM t1;
|
||||
} {0 {673 stone philips}}
|
||||
do_catchsql_test pager4-1.3 {
|
||||
UPDATE t1 SET a=537;
|
||||
} {1 {attempt to write a readonly database}}
|
||||
|
||||
# Creating a different database file with the same name of the original
|
||||
# is detected and still leaves the database read-only.
|
||||
#
|
||||
sqlite3 db2 test.db
|
||||
db2 eval {CREATE TABLE t2(x,y,z)}
|
||||
do_catchsql_test pager4-1.4 {
|
||||
UPDATE t1 SET a=948;
|
||||
} {1 {attempt to write a readonly database}}
|
||||
|
||||
# Changing the name back clears the READONLY error
|
||||
#
|
||||
db2 close
|
||||
file delete -force test.db
|
||||
file rename test-xyz.db test.db
|
||||
do_catchsql_test pager4-1.5 {
|
||||
SELECT * FROM t1;
|
||||
} {0 {673 stone philips}}
|
||||
do_catchsql_test pager4-1.6 {
|
||||
UPDATE t1 SET a=537;
|
||||
SELECT * FROM t1;
|
||||
} {0 {537 stone philips}}
|
||||
|
||||
# We can write to a renamed database if journal_mode=OFF or
|
||||
# journal_mode=MEMORY.
|
||||
#
|
||||
file rename test.db test-xyz.db
|
||||
do_catchsql_test pager4-1.7 {
|
||||
PRAGMA journal_mode=OFF;
|
||||
UPDATE t1 SET a=107;
|
||||
SELECT * FROM t1;
|
||||
} {0 {off 107 stone philips}}
|
||||
do_catchsql_test pager4-1.8 {
|
||||
PRAGMA journal_mode=MEMORY;
|
||||
UPDATE t1 SET b='magpie';
|
||||
SELECT * FROM t1;
|
||||
} {0 {memory 107 magpie philips}}
|
||||
|
||||
# Any other journal mode gives a READONLY error
|
||||
#
|
||||
do_catchsql_test pager4-1.9 {
|
||||
PRAGMA journal_mode=DELETE;
|
||||
UPDATE t1 SET c='jaguar';
|
||||
} {1 {attempt to write a readonly database}}
|
||||
do_catchsql_test pager4-1.10 {
|
||||
PRAGMA journal_mode=TRUNCATE;
|
||||
UPDATE t1 SET c='jaguar';
|
||||
} {1 {attempt to write a readonly database}}
|
||||
do_catchsql_test pager4-1.11 {
|
||||
PRAGMA journal_mode=PERSIST;
|
||||
UPDATE t1 SET c='jaguar';
|
||||
} {1 {attempt to write a readonly database}}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -1544,5 +1544,6 @@ do_faultsim_test pagerfault-36 -prep {
|
||||
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 0
|
||||
sqlite3_initialize
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
# 2013-12-17
|
||||
#
|
||||
# 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. The
|
||||
# focus of this file is testing the printf() SQL function.
|
||||
#
|
||||
#
|
||||
# EVIDENCE-OF: R-63057-40065 The printf(FORMAT,...) SQL function works
|
||||
# like the sqlite3_mprintf() C-language function and the printf()
|
||||
# function from the standard C library.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# EVIDENCE-OF: R-40086-60101 If the FORMAT argument is missing or NULL
|
||||
# then the result is NULL.
|
||||
#
|
||||
do_execsql_test printf2-1.1 {
|
||||
SELECT quote(printf()), quote(printf(NULL,1,2,3));
|
||||
} {NULL NULL}
|
||||
|
||||
|
||||
do_execsql_test printf2-1.2 {
|
||||
SELECT printf('hello');
|
||||
} {hello}
|
||||
do_execsql_test printf2-1.3 {
|
||||
SELECT printf('%d,%d,%d',55,-11,3421);
|
||||
} {55,-11,3421}
|
||||
do_execsql_test printf2-1.4 {
|
||||
SELECT printf('%d,%d,%d',55,'-11',3421);
|
||||
} {55,-11,3421}
|
||||
do_execsql_test printf2-1.5 {
|
||||
SELECT printf('%d,%d,%d,%d',55,'-11',3421);
|
||||
} {55,-11,3421,0}
|
||||
do_execsql_test printf2-1.6 {
|
||||
SELECT printf('%.2f',3.141592653);
|
||||
} {3.14}
|
||||
do_execsql_test printf2-1.7 {
|
||||
SELECT printf('%.*f',2,3.141592653);
|
||||
} {3.14}
|
||||
do_execsql_test printf2-1.8 {
|
||||
SELECT printf('%*.*f',5,2,3.141592653);
|
||||
} {{ 3.14}}
|
||||
do_execsql_test printf2-1.9 {
|
||||
SELECT printf('%d',314159.2653);
|
||||
} {314159}
|
||||
do_execsql_test printf2-1.10 {
|
||||
SELECT printf('%lld',314159.2653);
|
||||
} {314159}
|
||||
do_execsql_test printf2-1.11 {
|
||||
SELECT printf('%lld%n',314159.2653,'hi');
|
||||
} {314159}
|
||||
|
||||
# EVIDENCE-OF: R-17002-27534 The %z format is interchangeable with %s.
|
||||
#
|
||||
do_execsql_test printf2-1.12 {
|
||||
SELECT printf('%.*z',5,'abcdefghijklmnop');
|
||||
} {abcde}
|
||||
do_execsql_test printf2-1.13 {
|
||||
SELECT printf('%c','abcdefghijklmnop');
|
||||
} {a}
|
||||
|
||||
# EVIDENCE-OF: R-02347-27622 The %n format is silently ignored and does
|
||||
# not consume an argument.
|
||||
#
|
||||
do_execsql_test printf2-2.1 {
|
||||
CREATE TABLE t1(a,b,c);
|
||||
INSERT INTO t1 VALUES(1,2,3);
|
||||
INSERT INTO t1 VALUES(-1,-2,-3);
|
||||
INSERT INTO t1 VALUES('abc','def','ghi');
|
||||
INSERT INTO t1 VALUES(1.5,2.25,3.125);
|
||||
SELECT printf('(%s)-%n-(%s)',a,b,c) FROM t1 ORDER BY rowid;
|
||||
} {(1)--(2) (-1)--(-2) (abc)--(def) (1.5)--(2.25)}
|
||||
|
||||
# EVIDENCE-OF: R-56064-04001 The %p format is an alias for %X.
|
||||
#
|
||||
do_execsql_test printf2-2.2 {
|
||||
SELECT printf('%s=(%p)',a,a) FROM t1 ORDER BY a;
|
||||
} {-1=(FFFFFFFFFFFFFFFF) 1=(1) 1.5=(1) abc=(0)}
|
||||
|
||||
# EVIDENCE-OF: R-29410-53018 If there are too few arguments in the
|
||||
# argument list, missing arguments are assumed to have a NULL value,
|
||||
# which is translated into 0 or 0.0 for numeric formats or an empty
|
||||
# string for %s.
|
||||
#
|
||||
do_execsql_test printf2-2.3 {
|
||||
SELECT printf('%s=(%d/%g/%s)',a) FROM t1 ORDER BY a;
|
||||
} {-1=(0/0/) 1=(0/0/) 1.5=(0/0/) abc=(0/0/)}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -47,7 +47,6 @@ do_test securedel-1.3 {
|
||||
}
|
||||
} {0 0}
|
||||
do_test securedel-1.4 {
|
||||
breakpoint
|
||||
db eval {
|
||||
PRAGMA secure_delete=ON;
|
||||
PRAGMA db2.secure_delete;
|
||||
|
||||
+16
-14
@@ -138,21 +138,23 @@ ifcapable {subquery && compound} {
|
||||
# Verify that an error occurs if you have too many terms on a
|
||||
# compound select statement.
|
||||
#
|
||||
ifcapable compound {
|
||||
if {$SQLITE_MAX_COMPOUND_SELECT>0} {
|
||||
set sql {SELECT 0}
|
||||
set result 0
|
||||
for {set i 1} {$i<$SQLITE_MAX_COMPOUND_SELECT} {incr i} {
|
||||
append sql " UNION ALL SELECT $i"
|
||||
lappend result $i
|
||||
if {[clang_sanitize_address]==0} {
|
||||
ifcapable compound {
|
||||
if {$SQLITE_MAX_COMPOUND_SELECT>0} {
|
||||
set sql {SELECT 0}
|
||||
set result 0
|
||||
for {set i 1} {$i<$SQLITE_MAX_COMPOUND_SELECT} {incr i} {
|
||||
append sql " UNION ALL SELECT $i"
|
||||
lappend result $i
|
||||
}
|
||||
do_test select7-6.1 {
|
||||
catchsql $sql
|
||||
} [list 0 $result]
|
||||
append sql { UNION ALL SELECT 99999999}
|
||||
do_test select7-6.2 {
|
||||
catchsql $sql
|
||||
} {1 {too many terms in compound SELECT}}
|
||||
}
|
||||
do_test select7-6.1 {
|
||||
catchsql $sql
|
||||
} [list 0 $result]
|
||||
append sql { UNION ALL SELECT 99999999}
|
||||
do_test select7-6.2 {
|
||||
catchsql $sql
|
||||
} {1 {too many terms in compound SELECT}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -155,7 +155,8 @@ SELECT * FROM foo1;
|
||||
2
|
||||
SELECT * FROM foo2;
|
||||
1
|
||||
2}}
|
||||
2
|
||||
}}
|
||||
|
||||
# Test with echo on and headers on using dot command and
|
||||
# multiple commands per line.
|
||||
@@ -192,6 +193,7 @@ a
|
||||
SELECT * FROM foo2;
|
||||
b
|
||||
1
|
||||
2}}
|
||||
2
|
||||
}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -268,4 +268,23 @@ do_test shell5-1.9 {
|
||||
} {1 {} 11 | 2 x 22 | 3 {"} 33 | 4 hello 44 | 5 55 {} | 6 66 x | 7 77 {"} | 8 88 hello | {} 9 99 | x 10 110 | {"} 11 121 | hello 12 132 |}
|
||||
db close
|
||||
|
||||
# Import columns containing quoted strings
|
||||
do_test shell5-1.10 {
|
||||
set out [open shell5.csv w]
|
||||
fconfigure $out -translation lf
|
||||
puts $out {column1,column2,column3,column4}
|
||||
puts $out "field1,field2,\"x3 \"\"\r\ndata\"\" 3\",field4"
|
||||
puts $out "x1,x2,\"x3 \"\"\ndata\"\" 3\",x4"
|
||||
close $out
|
||||
forcedelete test.db
|
||||
catchcmd test.db {.mode csv
|
||||
CREATE TABLE t1(a,b,c,d);
|
||||
.import shell5.csv t1
|
||||
}
|
||||
sqlite3 db test.db
|
||||
db eval {SELECT hex(c) FROM t1 ORDER BY rowid}
|
||||
} {636F6C756D6E33 783320220D0A64617461222033 783320220A64617461222033}
|
||||
|
||||
db close
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -187,4 +187,26 @@ do_execsql_test skipscan1-3.2sort {
|
||||
SELECT a,b,c,d,'|' FROM t3 WHERE b=345 ORDER BY a;
|
||||
} {~/*ORDER BY*/}
|
||||
|
||||
# Ticket 520070ec7fbaac: Array overrun in the skip-scan optimization
|
||||
# 2013-12-22
|
||||
#
|
||||
do_execsql_test skipscan1-4.1 {
|
||||
CREATE TABLE t4(a,b,c,d,e,f,g,h,i);
|
||||
CREATE INDEX t4all ON t4(a,b,c,d,e,f,g,h);
|
||||
INSERT INTO t4 VALUES(1,2,3,4,5,6,7,8,9);
|
||||
ANALYZE;
|
||||
DELETE FROM sqlite_stat1;
|
||||
INSERT INTO sqlite_stat1
|
||||
VALUES('t4','t4all','655360 163840 40960 10240 2560 640 160 40 10');
|
||||
ANALYZE sqlite_master;
|
||||
SELECT i FROM t4 WHERE a=1;
|
||||
SELECT i FROM t4 WHERE b=2;
|
||||
SELECT i FROM t4 WHERE c=3;
|
||||
SELECT i FROM t4 WHERE d=4;
|
||||
SELECT i FROM t4 WHERE e=5;
|
||||
SELECT i FROM t4 WHERE f=6;
|
||||
SELECT i FROM t4 WHERE g=7;
|
||||
SELECT i FROM t4 WHERE h=8;
|
||||
} {9 9 9 9 9 9 9 9}
|
||||
|
||||
finish_test
|
||||
|
||||
+66
-21
@@ -9,6 +9,7 @@ static const char zHelp[] =
|
||||
" --autovacuum Enable AUTOVACUUM mode\n"
|
||||
" --cachesize N Set the cache size to N\n"
|
||||
" --exclusive Enable locking_mode=EXCLUSIVE\n"
|
||||
" --explain Like --sqlonly but with added EXPLAIN keywords\n"
|
||||
" --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n"
|
||||
" --incrvacuum Enable incremenatal vacuum mode\n"
|
||||
" --journalmode M Set the journal_mode to MODE\n"
|
||||
@@ -49,6 +50,7 @@ static struct Global {
|
||||
int bWithoutRowid; /* True for --without-rowid */
|
||||
int bReprepare; /* True to reprepare the SQL on each rerun */
|
||||
int bSqlOnly; /* True to print the SQL once only */
|
||||
int bExplain; /* Print SQL with EXPLAIN prefix */
|
||||
int szTest; /* Scale factor for test iterations */
|
||||
const char *zWR; /* Might be WITHOUT ROWID */
|
||||
const char *zNN; /* Might be NOT NULL */
|
||||
@@ -290,6 +292,24 @@ void speedtest1_final(void){
|
||||
}
|
||||
}
|
||||
|
||||
/* Print an SQL statement to standard output */
|
||||
static void printSql(const char *zSql){
|
||||
int n = (int)strlen(zSql);
|
||||
while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ){ n--; }
|
||||
if( g.bExplain ) printf("EXPLAIN ");
|
||||
printf("%.*s;\n", n, zSql);
|
||||
if( g.bExplain
|
||||
#if SQLITE_VERSION_NUMBER>=3007010
|
||||
&& ( sqlite3_strglob("CREATE *", zSql)==0
|
||||
|| sqlite3_strglob("DROP *", zSql)==0
|
||||
|| sqlite3_strglob("ALTER *", zSql)==0
|
||||
)
|
||||
#endif
|
||||
){
|
||||
printf("%.*s;\n", n, zSql);
|
||||
}
|
||||
}
|
||||
|
||||
/* Run SQL */
|
||||
void speedtest1_exec(const char *zFormat, ...){
|
||||
va_list ap;
|
||||
@@ -298,9 +318,7 @@ void speedtest1_exec(const char *zFormat, ...){
|
||||
zSql = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
if( g.bSqlOnly ){
|
||||
int n = (int)strlen(zSql);
|
||||
while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ){ n--; }
|
||||
printf("%.*s;\n", n, zSql);
|
||||
printSql(zSql);
|
||||
}else{
|
||||
char *zErrMsg = 0;
|
||||
int rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg);
|
||||
@@ -318,9 +336,7 @@ void speedtest1_prepare(const char *zFormat, ...){
|
||||
zSql = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
if( g.bSqlOnly ){
|
||||
int n = (int)strlen(zSql);
|
||||
while( n>0 && (zSql[n-1]==';' || isspace(zSql[n-1])) ){ n--; }
|
||||
printf("%.*s;\n", n, zSql);
|
||||
printSql(zSql);
|
||||
}else{
|
||||
int rc;
|
||||
if( g.pStmt ) sqlite3_finalize(g.pStmt);
|
||||
@@ -378,6 +394,19 @@ static void randomFunc(
|
||||
sqlite3_result_int64(context, (sqlite3_int64)speedtest1_random());
|
||||
}
|
||||
|
||||
/* Estimate the square root of an integer */
|
||||
static int est_square_root(int x){
|
||||
int y0 = x/2;
|
||||
int y1;
|
||||
int n;
|
||||
for(n=0; y0>0 && n<10; n++){
|
||||
y1 = (y0 + x/y0)/2;
|
||||
if( y1==y0 ) break;
|
||||
y0 = y1;
|
||||
}
|
||||
return y0;
|
||||
}
|
||||
|
||||
/*
|
||||
** The main and default testset
|
||||
*/
|
||||
@@ -484,15 +513,13 @@ void testset_main(void){
|
||||
|
||||
|
||||
speedtest1_begin_test(150, "CREATE INDEX five times");
|
||||
speedtest1_exec(
|
||||
"BEGIN;\n"
|
||||
"CREATE UNIQUE INDEX t1b ON t1(b);\n"
|
||||
"CREATE INDEX t1c ON t1(c);\n"
|
||||
"CREATE UNIQUE INDEX t2b ON t2(b);\n"
|
||||
"CREATE INDEX t2c ON t2(c DESC);\n"
|
||||
"CREATE INDEX t3bc ON t3(b,c);\n"
|
||||
"COMMIT;\n"
|
||||
);
|
||||
speedtest1_exec("BEGIN;");
|
||||
speedtest1_exec("CREATE UNIQUE INDEX t1b ON t1(b);");
|
||||
speedtest1_exec("CREATE INDEX t1c ON t1(c);");
|
||||
speedtest1_exec("CREATE UNIQUE INDEX t2b ON t2(b);");
|
||||
speedtest1_exec("CREATE INDEX t2c ON t2(c DESC);");
|
||||
speedtest1_exec("CREATE INDEX t3bc ON t3(b,c);");
|
||||
speedtest1_exec("COMMIT;");
|
||||
speedtest1_end_test();
|
||||
|
||||
|
||||
@@ -566,10 +593,8 @@ void testset_main(void){
|
||||
|
||||
n = sz;
|
||||
speedtest1_begin_test(190, "DELETE and REFILL one table", n);
|
||||
speedtest1_exec(
|
||||
"DELETE FROM t2;"
|
||||
"INSERT INTO t2 SELECT * FROM t1;"
|
||||
);
|
||||
speedtest1_exec("DELETE FROM t2;");
|
||||
speedtest1_exec("INSERT INTO t2 SELECT * FROM t1;");
|
||||
speedtest1_end_test();
|
||||
|
||||
|
||||
@@ -663,9 +688,17 @@ void testset_main(void){
|
||||
speedtest1_exec("REPLACE INTO t3(a,b,c) SELECT a,b,c FROM t1");
|
||||
speedtest1_end_test();
|
||||
|
||||
speedtest1_begin_test(300, "Refill a %d-row table using (b&1)==(a&1)", sz);
|
||||
speedtest1_exec("DELETE FROM t2;");
|
||||
speedtest1_exec("INSERT INTO t2(a,b,c)\n"
|
||||
" SELECT a,b,c FROM t1 WHERE (b&1)==(a&1);");
|
||||
speedtest1_exec("INSERT INTO t2(a,b,c)\n"
|
||||
" SELECT a,b,c FROM t1 WHERE (b&1)<>(a&1);");
|
||||
speedtest1_end_test();
|
||||
|
||||
|
||||
n = sz/5;
|
||||
speedtest1_begin_test(290, "%d four-ways joins", n);
|
||||
speedtest1_begin_test(310, "%d four-ways joins", n);
|
||||
speedtest1_exec("BEGIN");
|
||||
speedtest1_prepare(
|
||||
"SELECT t1.c FROM t1, t2, t3, t4\n"
|
||||
@@ -684,7 +717,15 @@ void testset_main(void){
|
||||
speedtest1_exec("COMMIT");
|
||||
speedtest1_end_test();
|
||||
|
||||
|
||||
speedtest1_begin_test(320, "subquery in result set", n);
|
||||
speedtest1_prepare(
|
||||
"SELECT sum(a), max(c),\n"
|
||||
" avg((SELECT a FROM t2 WHERE 5+t2.b=t1.b) AND rowid<?1), max(c)\n"
|
||||
" FROM t1 WHERE rowid<?1;"
|
||||
);
|
||||
sqlite3_bind_int(g.pStmt, 1, est_square_root(g.szTest)*50);
|
||||
speedtest1_run();
|
||||
speedtest1_end_test();
|
||||
|
||||
speedtest1_begin_test(980, "PRAGMA integrity_check");
|
||||
speedtest1_exec("PRAGMA integrity_check");
|
||||
@@ -757,6 +798,9 @@ int main(int argc, char **argv){
|
||||
cacheSize = integerValue(argv[i]);
|
||||
}else if( strcmp(z,"exclusive")==0 ){
|
||||
doExclusive = 1;
|
||||
}else if( strcmp(z,"explain")==0 ){
|
||||
g.bSqlOnly = 1;
|
||||
g.bExplain = 1;
|
||||
}else if( strcmp(z,"heap")==0 ){
|
||||
if( i>=argc-2 ) fatal_error("missing arguments on %s\n", argv[i]);
|
||||
nHeap = integerValue(argv[i+1]);
|
||||
@@ -896,6 +940,7 @@ int main(int argc, char **argv){
|
||||
speedtest1_exec("PRAGMA journal_mode=%s", zJMode);
|
||||
}
|
||||
|
||||
if( g.bExplain ) printf(".explain\n.echo on\n");
|
||||
if( strcmp(zTSet,"main")==0 ){
|
||||
testset_main();
|
||||
}else if( strcmp(zTSet,"debug1")==0 ){
|
||||
|
||||
@@ -221,6 +221,53 @@ foreach {tn word res} {
|
||||
} $res
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Try some queries by rowid.
|
||||
#
|
||||
do_execsql_test 6.1.1 {
|
||||
SELECT word FROM t3 WHERE rowid = 10;
|
||||
} {keener}
|
||||
do_execsql_test 6.1.2 {
|
||||
SELECT word, distance FROM t3 WHERE rowid = 10;
|
||||
} {keener {}}
|
||||
do_execsql_test 6.1.3 {
|
||||
SELECT word, distance FROM t3 WHERE rowid = 10 AND word MATCH 'kiiner';
|
||||
} {keener 300}
|
||||
|
||||
ifcapable trace {
|
||||
proc trace_callback {sql} {
|
||||
if {[string range $sql 0 2] == "-- "} {
|
||||
lappend ::trace [string range $sql 3 end]
|
||||
}
|
||||
}
|
||||
|
||||
proc do_tracesql_test {tn sql {res {}}} {
|
||||
set ::trace [list]
|
||||
uplevel [list do_test $tn [subst -nocommands {
|
||||
set vals [execsql {$sql}]
|
||||
concat [set vals] [set ::trace]
|
||||
}] [list {*}$res]]
|
||||
}
|
||||
|
||||
db trace trace_callback
|
||||
do_tracesql_test 6.2.1 {
|
||||
SELECT word FROM t3 WHERE rowid = 10;
|
||||
} {keener
|
||||
{SELECT word, rank, NULL, langid, id FROM "main"."t3_vocab" WHERE rowid=?}
|
||||
}
|
||||
do_tracesql_test 6.2.2 {
|
||||
SELECT word, distance FROM t3 WHERE rowid = 10;
|
||||
} {keener {}
|
||||
{SELECT word, rank, NULL, langid, id FROM "main"."t3_vocab" WHERE rowid=?}
|
||||
}
|
||||
do_tracesql_test 6.2.3 {
|
||||
SELECT word, distance FROM t3 WHERE rowid = 10 AND word MATCH 'kiiner';
|
||||
} {keener 300
|
||||
{SELECT id, word, rank, k1 FROM "main"."t3_vocab" WHERE langid=0 AND k2>=?1 AND k2<?2}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -164,7 +164,6 @@ db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
register_dbstat_vtab db
|
||||
breakpoint
|
||||
do_execsql_test stat-5.1 {
|
||||
PRAGMA auto_vacuum = OFF;
|
||||
CREATE VIRTUAL TABLE temp.stat USING dbstat;
|
||||
|
||||
+18
-1
@@ -59,6 +59,7 @@
|
||||
# do_test TESTNAME SCRIPT EXPECTED
|
||||
# do_execsql_test TESTNAME SQL EXPECTED
|
||||
# do_catchsql_test TESTNAME SQL EXPECTED
|
||||
# do_timed_execsql_test TESTNAME SQL EXPECTED
|
||||
#
|
||||
# Commands providing a lower level interface to the global test counters:
|
||||
#
|
||||
@@ -717,6 +718,11 @@ proc do_catchsql_test {testname sql result} {
|
||||
fix_testname testname
|
||||
uplevel do_test [list $testname] [list "catchsql {$sql}"] [list $result]
|
||||
}
|
||||
proc do_timed_execsql_test {testname sql {result {}}} {
|
||||
fix_testname testname
|
||||
uplevel do_test [list $testname] [list "execsql_timed {$sql}"]\
|
||||
[list [list {*}$result]]
|
||||
}
|
||||
proc do_eqp_test {name sql res} {
|
||||
uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] [list $res]
|
||||
}
|
||||
@@ -1013,6 +1019,14 @@ proc execsql {sql {db db}} {
|
||||
# puts "SQL = $sql"
|
||||
uplevel [list $db eval $sql]
|
||||
}
|
||||
proc execsql_timed {sql {db db}} {
|
||||
set tm [time {
|
||||
set x [uplevel [list $db eval $sql]]
|
||||
} 1]
|
||||
set tm [lindex $tm 0]
|
||||
puts -nonewline " ([expr {$tm*0.001}]ms) "
|
||||
set x
|
||||
}
|
||||
|
||||
# Execute SQL and catch exceptions.
|
||||
#
|
||||
@@ -1251,6 +1265,7 @@ proc crashsql {args} {
|
||||
set blocksize ""
|
||||
set crashdelay 1
|
||||
set prngseed 0
|
||||
set opendb { sqlite3 db test.db -vfs crash }
|
||||
set tclbody {}
|
||||
set crashfile ""
|
||||
set dc ""
|
||||
@@ -1262,6 +1277,7 @@ proc crashsql {args} {
|
||||
set z2 [lindex $args [expr $ii+1]]
|
||||
|
||||
if {$n>1 && [string first $z -delay]==0} {set crashdelay $z2} \
|
||||
elseif {$n>1 && [string first $z -opendb]==0} {set opendb $z2} \
|
||||
elseif {$n>1 && [string first $z -seed]==0} {set prngseed $z2} \
|
||||
elseif {$n>1 && [string first $z -file]==0} {set crashfile $z2} \
|
||||
elseif {$n>1 && [string first $z -tclbody]==0} {set tclbody $z2} \
|
||||
@@ -1283,7 +1299,7 @@ proc crashsql {args} {
|
||||
puts $f "sqlite3_crash_enable 1"
|
||||
puts $f "sqlite3_crashparams $blocksize $dc $crashdelay $cfile"
|
||||
puts $f "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
|
||||
puts $f "sqlite3 db test.db -vfs crash"
|
||||
puts $f $opendb
|
||||
|
||||
# This block sets the cache size of the main database to 10
|
||||
# pages. This is done in case the build is configured to omit
|
||||
@@ -1291,6 +1307,7 @@ proc crashsql {args} {
|
||||
puts $f {db eval {SELECT * FROM sqlite_master;}}
|
||||
puts $f {set bt [btree_from_db db]}
|
||||
puts $f {btree_set_cache_size $bt 10}
|
||||
|
||||
if {$prngseed} {
|
||||
set seed [expr {$prngseed%10007+1}]
|
||||
# puts seed=$seed
|
||||
|
||||
@@ -44,7 +44,6 @@ do_test tkt-94c94-2.1 {
|
||||
execsql { CREATE TABLE t2(x, y) } db
|
||||
} {}
|
||||
do_test tkt-94c94-2.2 {
|
||||
breakpoint
|
||||
execsql { INSERT INTO t2 VALUES(1, 2) } db2
|
||||
} {}
|
||||
do_test tkt-94c94-2.3 {
|
||||
|
||||
@@ -1376,4 +1376,23 @@ do_execsql_test 20.4 {
|
||||
ORDER BY 1, 2;
|
||||
} {5 5 6 6 11 11 12 12}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
do_execsql_test 21.1 {
|
||||
CREATE TABLE t9(a,b,c);
|
||||
CREATE VIRTUAL TABLE t9v USING echo(t9);
|
||||
|
||||
INSERT INTO t9 VALUES(1,2,3);
|
||||
INSERT INTO t9 VALUES(3,2,1);
|
||||
INSERT INTO t9 VALUES(2,2,2);
|
||||
}
|
||||
|
||||
do_execsql_test 21.2 {
|
||||
SELECT * FROM t9v WHERE a<b;
|
||||
} {1 2 3}
|
||||
|
||||
do_execsql_test 21.3 {
|
||||
SELECT * FROM t9v WHERE a=b;
|
||||
} {2 2 2}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -116,7 +116,6 @@ do_test vtab_shared-1.10 {
|
||||
} {1 {database table is locked: sqlite_master}}
|
||||
|
||||
do_test vtab_shared-1.11 {
|
||||
breakpoint
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE t2 USING echo(t0);
|
||||
CREATE VIRTUAL TABLE t3 USING echo(t0);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user