track 3.7.2

This commit is contained in:
Stephen Lombardo
2010-08-28 08:35:57 -04:00
parent 953ca18eb6
commit 92bc32215d
116 changed files with 7370 additions and 1862 deletions
+4 -4
View File
@@ -103,15 +103,15 @@ SHPREFIX =
#
#TCL_FLAGS =
#TCL_FLAGS = -DSTATIC_BUILD=1
TCL_FLAGS = -I/home/drh/tcltk/8.4linux
#TCL_FLAGS = -I/home/drh/tcltk/8.4win -DSTATIC_BUILD=1
TCL_FLAGS = -I/home/drh/tcltk/8.5linux
#TCL_FLAGS = -I/home/drh/tcltk/8.5win -DSTATIC_BUILD=1
#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux
#### Linker options needed to link against the TCL library.
#
#LIBTCL = -ltcl -lm -ldl
LIBTCL = /home/drh/tcltk/8.4linux/libtcl8.4g.a -lm -ldl
#LIBTCL = /home/drh/tcltk/8.4win/libtcl84s.a -lmsvcrt
LIBTCL = /home/drh/tcltk/8.5linux/libtcl8.5g.a -lm -ldl
#LIBTCL = /home/drh/tcltk/8.5win/libtcl85s.a -lmsvcrt
#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc
#### Additional objects for SQLite library when TCL support is enabled.
+1 -1
View File
@@ -748,7 +748,7 @@ tclsqlite-shell.lo: $(TOP)/src/tclsqlite.c $(HDR)
$(LTCOMPILE) -DTCLSH=1 -o $@ -c $(TOP)/src/tclsqlite.c
tclsqlite-stubs.lo: $(TOP)/src/tclsqlite.c $(HDR)
$(LTCOMPILE) -DTCL_USE_STUBS=1 -o $@ -c $(TOP)/src/tclsqlite.c
$(LTCOMPILE) -DUSE_TCL_STUBS=1 -o $@ -c $(TOP)/src/tclsqlite.c
tclsqlite3$(TEXE): tclsqlite-shell.lo libsqlite3.la
$(LTLINK) -o $@ tclsqlite-shell.lo \
+4 -4
View File
@@ -93,15 +93,15 @@ SHPREFIX = lib
#
#TCL_FLAGS =
#TCL_FLAGS = -DSTATIC_BUILD=1
TCL_FLAGS = -I/home/drh/tcltk/8.4linux
#TCL_FLAGS = -I/home/drh/tcltk/8.4win -DSTATIC_BUILD=1
TCL_FLAGS = -I/home/drh/tcltk/8.5linux
#TCL_FLAGS = -I/home/drh/tcltk/8.5win -DSTATIC_BUILD=1
#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux
#### Linker options needed to link against the TCL library.
#
#LIBTCL = -ltcl -lm -ldl
LIBTCL = /home/drh/tcltk/8.4linux/libtcl8.4g.a -lm -ldl
#LIBTCL = /home/drh/tcltk/8.4win/libtcl84s.a -lmsvcrt
LIBTCL = /home/drh/tcltk/8.5linux/libtcl8.5g.a -lm -ldl
#LIBTCL = /home/drh/tcltk/8.5win/libtcl85s.a -lmsvcrt
#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc
#### Additional objects for SQLite library when TCL support is enabled.
+4 -4
View File
@@ -110,15 +110,15 @@ SHPREFIX = lib
#
#TCL_FLAGS =
#TCL_FLAGS = -DSTATIC_BUILD=1
TCL_FLAGS = -I/home/drh/tcltk/8.4linux
#TCL_FLAGS = -I/home/drh/tcltk/8.4win -DSTATIC_BUILD=1
TCL_FLAGS = -I/home/drh/tcltk/8.5linux
#TCL_FLAGS = -I/home/drh/tcltk/8.5win -DSTATIC_BUILD=1
#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux
#### Linker options needed to link against the TCL library.
#
#LIBTCL = -ltcl -lm -ldl
LIBTCL = /home/drh/tcltk/8.4linux/libtcl8.4g.a -lm -ldl
#LIBTCL = /home/drh/tcltk/8.4win/libtcl84s.a -lmsvcrt
LIBTCL = /home/drh/tcltk/8.5linux/libtcl8.5g.a -lm -ldl
#LIBTCL = /home/drh/tcltk/8.5win/libtcl85s.a -lmsvcrt
#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc
#### Additional objects for SQLite library when TCL support is enabled.
+1 -1
View File
@@ -1 +1 @@
3.7.0.1
3.7.2
Vendored
+10 -10
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.62 for sqlite 3.7.0.1.
# Generated by GNU Autoconf 2.62 for sqlite 3.7.2.
#
# 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.7.0.1'
PACKAGE_STRING='sqlite 3.7.0.1'
PACKAGE_VERSION='3.7.2'
PACKAGE_STRING='sqlite 3.7.2'
PACKAGE_BUGREPORT=''
# Factoring default headers for most tests.
@@ -1487,7 +1487,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.7.0.1 to adapt to many kinds of systems.
\`configure' configures sqlite 3.7.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1552,7 +1552,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.7.0.1:";;
short | recursive ) echo "Configuration of sqlite 3.7.2:";;
esac
cat <<\_ACEOF
@@ -1670,7 +1670,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.7.0.1
sqlite configure 3.7.2
generated by GNU Autoconf 2.62
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1684,7 +1684,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.7.0.1, which was
It was created by sqlite $as_me 3.7.2, which was
generated by GNU Autoconf 2.62. Invocation command line was
$ $0 $@
@@ -12259,7 +12259,7 @@ USE_AMALGAMATION=1
# if not, then we fall back to plain tclsh.
# TODO: try other versions before falling back?
#
for ac_prog in tclsh8.4 tclsh
for ac_prog in tclsh8.5 tclsh
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
@@ -13972,7 +13972,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.7.0.1, which was
This file was extended by sqlite $as_me 3.7.2, which was
generated by GNU Autoconf 2.62. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14025,7 +14025,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_version="\\
sqlite config.status 3.7.0.1
sqlite config.status 3.7.2
configured by $0, generated by GNU Autoconf 2.62,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+1 -1
View File
@@ -139,7 +139,7 @@ USE_AMALGAMATION=1
# if not, then we fall back to plain tclsh.
# TODO: try other versions before falling back?
#
AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.4 tclsh], none)
AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.5 tclsh], none)
if test "$TCLSH_CMD" = "none"; then
# If we can't find a local tclsh, then building the amalgamation will fail.
# We act as though --disable-amalgamation has been used.
+1 -1
View File
@@ -2653,7 +2653,7 @@ static void hashDestroy(void *p){
** used to retrieve the respective implementations.
**
** Calling sqlite3Fts3SimpleTokenizerModule() sets the value pointed
** to by the argument to point a the "simple" tokenizer implementation.
** to by the argument to point to the "simple" tokenizer implementation.
** Function ...PorterTokenizerModule() sets *pModule to point to the
** porter tokenizer/stemmer implementation.
*/
+1 -2
View File
@@ -78,7 +78,6 @@ int sqlite3_fts3_enable_parentheses = 0;
#define SQLITE_FTS3_DEFAULT_NEAR_PARAM 10
#include "fts3Int.h"
#include <ctype.h>
#include <string.h>
#include <assert.h>
@@ -104,7 +103,7 @@ struct ParseContext {
** negative values).
*/
static int fts3isspace(char c){
return (c&0x80)==0 ? isspace(c) : 0;
return c==' ' || c=='\t' || c=='\n' || c=='\r' || c=='\v' || c=='\f';
}
/*
-1
View File
@@ -30,7 +30,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "fts3_tokenizer.h"
-1
View File
@@ -16,7 +16,6 @@
#include "fts3Int.h"
#include <string.h>
#include <assert.h>
#include <ctype.h>
/*
-1
View File
@@ -32,7 +32,6 @@
#include "fts3Int.h"
#include <assert.h>
#include <ctype.h>
#include <string.h>
/*
+5 -3
View File
@@ -30,7 +30,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "fts3_tokenizer.h"
@@ -53,6 +52,9 @@ typedef struct simple_tokenizer_cursor {
static int simpleDelim(simple_tokenizer *t, unsigned char c){
return c<0x80 && t->delim[c];
}
static int fts3_isalnum(int x){
return (x>='0' && x<='9') || (x>='A' && x<='Z') || (x>='a' && x<='z');
}
/*
** Create a new tokenizer instance.
@@ -87,7 +89,7 @@ static int simpleCreate(
/* Mark non-alphanumeric ASCII characters as delimiters */
int i;
for(i=1; i<0x80; i++){
t->delim[i] = !isalnum(i) ? -1 : 0;
t->delim[i] = !fts3_isalnum(i) ? -1 : 0;
}
}
@@ -193,7 +195,7 @@ static int simpleNext(
** case-insensitivity.
*/
unsigned char ch = p[iStartOffset+i];
c->pToken[i] = (char)(ch<0x80 ? tolower(ch) : ch);
c->pToken[i] = (char)((ch>='A' && ch<='Z') ? ch-'A'+'a' : ch);
}
*ppToken = c->pToken;
*pnBytes = n;
+1 -2
View File
@@ -139,7 +139,7 @@ SQLite. Documentation follows.
3.2 The SQLITE_MAX_LIKE_PATTERN_LENGTH Macro
Passing very long patterns to the built-in SQLite LIKE operator can
cause a stack overflow. To curb this problem, SQLite defines the
cause excessive CPU usage. To curb this problem, SQLite defines the
SQLITE_MAX_LIKE_PATTERN_LENGTH macro as the maximum length of a
pattern in bytes (irrespective of encoding). The default value is
defined in internal header file "limits.h".
@@ -167,4 +167,3 @@ SQLite. Documentation follows.
malicious users may execute arbitrary SQL (i.e. gears), they
should be prevented from invoking the icu_load_collation() function,
possibly using the authorisation callback.
+2 -3
View File
@@ -1072,11 +1072,10 @@ static int rtreeFilter(
** idxNum idxStr Strategy
** ------------------------------------------------
** 1 Unused Direct lookup by rowid.
** 2 See below R-tree query.
** 3 Unused Full table scan.
** 2 See below R-tree query or full-table scan.
** ------------------------------------------------
**
** If strategy 1 or 3 is used, then idxStr is not meaningful. If strategy
** If strategy 1 is used, then idxStr is not meaningful. If strategy
** 2 is used, idxStr is formatted to contain 2 bytes for each
** constraint used. The first two bytes of idxStr correspond to
** the constraint in sqlite3_index_info.aConstraintUsage[] with
+4 -4
View File
@@ -88,8 +88,8 @@ do_test rtree6.2.2 {
do_test rtree6.2.3 {
query_plan {SELECT * FROM t1,t2 WHERE k=ii}
} [list \
{TABLE t2} \
{TABLE t1 VIRTUAL TABLE INDEX 1:} \
{TABLE t1 VIRTUAL TABLE INDEX 2:} \
{TABLE t2 USING PRIMARY KEY} \
]
do_test rtree6.2.4 {
@@ -102,8 +102,8 @@ do_test rtree6.2.4 {
do_test rtree6.2.5 {
query_plan {SELECT * FROM t1,t2 WHERE k=ii AND x1<v}
} [list \
{TABLE t2} \
{TABLE t1 VIRTUAL TABLE INDEX 1:} \
{TABLE t1 VIRTUAL TABLE INDEX 2:} \
{TABLE t2 USING PRIMARY KEY} \
]
finish_test
+122 -113
View File
@@ -1,14 +1,14 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
C Backport\sfix\s[a6bb2108bfb56]\sfor\sa\stypo\sin\sthe\sOS/2\sinterface.
D 2010-08-04T12:31:11
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F Makefile.vxworks 4314cde20a1d9460ec5083526ea975442306ae7e
C Version\s3.7.2\srelease\scandidate\s1
D 2010-08-23T18:52:01
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 543f91f24cd7fee774ecc0a61c19704c0c3e78fd
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.vxworks c85ec1d8597fe2f7bc225af12ac1666e21379151
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
F VERSION 84a3e1c74ef99b2c08ceb1142780ac63d6e44c3d
F VERSION 6062e0026a5ab33dabb4efae38604d40115819ec
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F addopcodes.awk 17dc593f791f874d2c23a0f9360850ded0286531
F art/2005osaward.gif 0d1851b2a7c1c9d0ccce545f3e14bca42d7fd248
@@ -24,8 +24,8 @@ F art/src_logo.gif 9341ef09f0e53cd44c0c9b6fc3c16f7f3d6c2ad9
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 868fdb48c028421a203470e15c69ada15b9ba673
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure 37e90c7b9b88007f064f690ed79e64e228a51158 x
F configure.ac 14740970ddb674d92a9f5da89083dff1179014ff
F configure a5dab32df872ed3fe248c7f0cbc324595c169781 x
F configure.ac 699040cc9abb7465dca5a2972bc89d227fd8f734
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
F doc/pager-invariants.txt 870107036470d7c419e93768676fae2f8749cf9e
@@ -63,32 +63,32 @@ F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c 9dec342fa1cf0914da679a3b7c0d4b53a27883ba
F ext/fts3/fts3.c e818310c473d7703f7818887a3537ec42ae0d528
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 70528ba8c33991699f96ecc64112122833cdbdb5
F ext/fts3/fts3_expr.c f4ff02ebe854e97ac03ff00b38b728a9ab57fd4b
F ext/fts3/fts3_expr.c 42d5697731cd30fbeabd081bb3e6d3df5531f606
F ext/fts3/fts3_hash.c 3c8f6387a4a7f5305588b203fa7c887d753e1f1c
F ext/fts3/fts3_hash.h 8331fb2206c609f9fc4c4735b9ab5ad6137c88ec
F ext/fts3/fts3_icu.c ac494aed69835008185299315403044664bda295
F ext/fts3/fts3_porter.c 7546e4503e286a67fd4f2a82159620e3e9c7a1bc
F ext/fts3/fts3_snippet.c bc582c38e194b48818da862f9e6f293cc44e29ee
F ext/fts3/fts3_tokenizer.c 1a49ee3d79cbf0b9386250370d9cbfe4bb89c8ff
F ext/fts3/fts3_porter.c 8df6f6efcc4e9e31f8bf73a4007c2e9abca1dfba
F ext/fts3/fts3_snippet.c 2c4c921155e4b6befd272041fb903d999ac07d30
F ext/fts3/fts3_tokenizer.c b4f2d01c24573852755bc92864816785dae39318
F ext/fts3/fts3_tokenizer.h 13ffd9fcb397fec32a05ef5cd9e0fa659bf3dbd3
F ext/fts3/fts3_tokenizer1.c b6d86d1d750787db5c168c73da4e87670ed890a1
F ext/fts3/fts3_tokenizer1.c 6e5cbaa588924ac578263a598e4fb9f5c9bb179d
F ext/fts3/fts3_write.c 4b21a0c6f2772b261f14e3a2e80e1e3e849268b0
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/icu/README.txt 3b130aa66e7a681136f6add198b076a2f90d1e33
F ext/icu/README.txt bf8461d8cdc6b8f514c080e4e10dc3b2bbdfefa9
F ext/icu/icu.c 850e9a36567bbcce6bd85a4b68243cad8e3c2de2
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c c7a18311f2d6ae9a42838e9c04b9e670483b4feb
F ext/rtree/rtree.c f2fbb6470155316027a8b888e8623bc1819fe443
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F ext/rtree/rtree1.test 51bb0cd0405970501e63258401ae5ad235a4f468
F ext/rtree/rtree2.test 7b665c44d25e51b3098068d983a39902b2e2d7a1
F ext/rtree/rtree3.test dece988c363368af8c11862995c762071894918f
F ext/rtree/rtree4.test 94fdd570ab5bc47244d87d4590023be43ac786bd
F ext/rtree/rtree5.test 92508f5152a50110af6551fa5b769d1bbd7c4ef3
F ext/rtree/rtree6.test 11aade5311789068ca659be24a47cc0d852b1971
F ext/rtree/rtree6.test 903720aaab819764c3693aaac0affe8174104ac8
F ext/rtree/rtree7.test 6fd29fb8e13795c822f4ceeea92ab5d61c96976d
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
@@ -109,40 +109,40 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c a9ff6f14b3935502537e90194b66c7bc79bed317
F src/analyze.c 3457a2af126eb78f20ad239c225a2c8ed61b78b6
F src/alter.c 8dc27638e7e2553e80b2b621f232be5eb1e85ef3
F src/analyze.c da65ce99bb159b10e85a1e460adbe53a88062500
F src/attach.c 17bec1f18254d9341369f20f90ba24ce35d20d10
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 51d83300fe0baee39405c416ceb19a58ed30a8ed
F src/bitvec.c 06ad2c36a9c3819c0b9cbffec7b15f58d5d834e0
F src/backup.c 8ff0b7018df253c7f30d3f9702b0b16f19209d5c
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff
F src/btree.c 0de928e4da0fb4ef15e33bf3ff13656d0bc98e73
F src/btree.h dd83041eda10c17daf023257c1fc883b5f71f85a
F src/btreeInt.h b0c87f6725b06a0aa194a6d25d54b16ce9d6e291
F src/build.c 559d38b48f79bc92370c082f4606eefe1e8f94ac
F src/callback.c 01843bdf4b0420fd28046525d150fcd9802931a9
F src/btree.c 5047fb303cdf6806a42676a6f513c57e15b7d69b
F src/btree.h b4ba2fdf6b64c7c376bdfffa826af6b786b151d9
F src/btreeInt.h 5b034ff54800046cc5870605d683ac1f9134bd99
F src/build.c 0018d49629fc4807100c988dd191dd95e185bb38
F src/callback.c da3c38d0ef5d7f04fae371e519bda61aa9cb1704
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 4f3aadad62c6c9f0d4e5a96718516ac4e3c598df
F src/date.c 5dd8448a0bfea8d31fb14cff487d0c06ff8c8b20
F src/delete.c 41cb4f78557810eecc167b7e2317de7e12d20929
F src/expr.c 96bda574284ead53ba7af6334414b4e958cc866a
F src/delete.c 7ed8a8c8b5f748ece92df173d7e0f7810c899ebd
F src/expr.c 9ee507c3dc6eaa5657cbd1dad026cdeda89c559f
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c e2116672a6bd610dc888e27df292ebc7999c9bb0
F src/func.c 0c28599430856631216b6c0131c51c89bf516026
F src/fkey.c 58bbf52c6ddd3f64ca40a3230f9e548a83a5cb16
F src/func.c 464b0dc70618b896c402c574eb04bc5eacf35341
F src/global.c 02335177cf6946fe5525c6f0755cf181140debf3
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c d9476f23f85a20eea3cc25a4b9f9cbae77a33bf2
F src/insert.c a4995747c062256582a90b4f87f716e11b067050
F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
F src/loadext.c 1c7a61ce1281041f437333f366a96aa0d29bb581
F src/main.c a487fe90aecaccb142e4a6b738c7e26e99145bcd
F src/malloc.c 09c3777bf733a387bec6aa344e455eb4e8ecf47e
F src/loadext.c 6d422ea91cf3d2d00408c5a8f2391cd458da85f8
F src/main.c 99622181f36d68e9f2a851c7b34263b3dcd03470
F src/malloc.c 19a468460c7df72de245f10c06bd0625777b7c83
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 89d4ea8d5cdd55635cbaa48ad53132af6294cbb2
F src/mem2.c 2ee7bdacda8299b5a91cff9f7ee3e46573195c38
F src/mem2.c 9e5f72e38573db9598fe60d3fa530d473cc8714e
F src/mem3.c 9b237d911ba9904142a804be727cc6664873f8a3
F src/mem5.c eb7a5cb98915dd7a086fa415ce3a5a0f20d0acff
F src/memjournal.c 4a93a25ad9f76c40afa070ffd7187eb3a5fd7aee
@@ -150,90 +150,90 @@ F src/mutex.c 6949180803ff05a7d0e2b9334a95b4fb5a00e23f
F src/mutex.h 6fde601e55fa6c3fae768783c439797ab84c87c6
F src/mutex_noop.c d5cfbca87168c661a0b118cd8e329a908e453151
F src/mutex_os2.c 6a62583e374ba3ac1a3fcc0da2bfdac7d3942689
F src/mutex_unix.c cf84466b4fdd2baa0d5a10bb19f08b2abc1ce42e
F src/mutex_w32.c 1fe0e735897be20e09dd6f53c3fb516c6b48c0eb
F src/notify.c cbfa66a836da3a51567209636e6a94059c137930
F src/mutex_unix.c abb8c98a6c27c57280e71522d059e929c708d019
F src/mutex_w32.c b7ed3366a1d44a62a17d4eaefdaa2e7c25f944c2
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
F src/os.c 60178f518c4d6c0dcb59f7292232281d7bea2dcf
F src/os.h 9dbed8c2b9c1f2f2ebabc09e49829d4777c26bf9
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e
F src/os_unix.c 3109e0e5a0d5551bab2e8c7322b20a3b8b171248
F src/os_win.c 1f8b0a1a5bcf6289e7754d0d3c16cec16d4c93ab
F src/pager.c 78ca1e1f3315c8227431c403c04d791dccf242fb
F src/pager.h 879fdde5a102d2f21a3135d6f647530b21c2796c
F src/parse.y 220a11ac72e2c9dffbf4cbe5fe462f328bd8d884
F src/os_unix.c 11194cbcf6a57456e58022dc537ab8c3497d9bb9
F src/os_win.c 51cb62f76262d961ea4249489383d714501315a7
F src/pager.c a5f5d9787b11dfb0b6082e6f5846d00b459a8e19
F src/pager.h ef8c8f71ab022cc2fff768a1175dd32355be9dcd
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
F src/pcache.c 1e9aa2dbc0845b52e1b51cc39753b6d1e041cb07
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
F src/pcache1.c 3a7c28f46a61b43ff0b5c087a7983c154f4b264c
F src/pragma.c 4a79269ea6f86150fb8e44688c753989fc7238dd
F src/prepare.c f045aeff869d6409a2eae2fe08f7dc2df9528195
F src/printf.c 5f5b65a83e63f2096a541a340722a509fa0240a7
F src/pcache1.c e921e8a1d52c93abde63cb6dad1fa39770410c52
F src/pragma.c 8b24ce00a93de345b6c3bd1e1e2cfba9f63d2325
F src/prepare.c ce4c35a2b1d5fe916e4a46b70d24a6e997d7c4c6
F src/printf.c 8ae5082dd38a1b5456030c3755ec3a392cd51506
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c 1c0f32b64f8e3f555fe1f732f9d6f501a7f05706
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c 4903ff1bbd08b55cbce00ea43c645530de41b362
F src/shell.c fd4ccdb37c3b68de0623eb938a649e0990710714
F src/sqlite.h.in 8b05aef506d9bc7fc7da1572744e3174cb16ed59
F src/select.c 8add6cab889fc02e1492eda8dba462ccf11f51dd
F src/shell.c 8517fc1f9c59ae4007e6cc8b9af91ab231ea2056
F src/sqlite.h.in 2d72a6242df41c517e38eec8791abcf5484a36f1
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
F src/sqliteInt.h d9e42f2029d4c526f9ba960bda1980ef17429c30
F src/sqliteLimit.h 196e2f83c3b444c4548fc1874f52f84fdbda40f3
F src/status.c 4df6fe7dce2d256130b905847c6c60055882bdbe
F src/sqliteInt.h e33b15e8176442bf7484f0e716edfd1ce03b2979
F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44
F src/status.c 496913d4e8441195f6f2a75b1c95993a45b9b30b
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c ae1e4fb653c91ddad7e2534d209711a12604ccc4
F src/test1.c ff3b4533fc4d78d1bff2ef831a5791db55096ed3
F src/test2.c e3f564ab1e9fd0b47b0c9e23e7054e38bf0836cf
F src/tclsqlite.c cacee9482417b6fc6043f6bb831ff9496d46242d
F src/test1.c 55005c9781b157b1d215ba145768783b9abae78c
F src/test2.c 80d323d11e909cf0eb1b6fbb4ac22276483bcf31
F src/test3.c 4c21700c73a890a47fc685c1097bfb661346ac94
F src/test4.c ad03bb987ddedce928f4258c1e7fa4109a73497d
F src/test5.c cc55900118fa4add8ec9cf69fc4225a4662f76b1
F src/test4.c 0528360b5025688002a5feb6be906ddce52eaaee
F src/test5.c e1a19845625144caf038031234a12185e40d315c
F src/test6.c c7256cc21d2409486d094277d5b017e8eced44ba
F src/test7.c 3f2d63e4ccf97f8c2cf1a7fa0a3c8e2e2a354e6e
F src/test8.c f959db9a22d882013b64c92753fa793b2ce3bdea
F src/test7.c d67f65d82815eb0b57699b122ca0145dbea55bbb
F src/test8.c 6b1d12912a04fe6fca8c45bb9c3ea022f4352228
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
F src/test_async.c 0612a752896fad42d55c3999a5122af10dcf22ad
F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e
F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de
F src/test_btree.c 47cd771250f09cdc6e12dda5bc71bc0b3abc96e2
F src/test_config.c 5a11c51af2156e2d07186930b36f2b8239a4393f
F src/test_demovfs.c da81a5f7785bb352bda7911c332a983ec4f17f27
F src/test_demovfs.c 0aed671636735116fc872c5b03706fd5612488b5
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_func.c 13b582345fb1185a93e46c53310fae8547dcce20
F src/test_hexio.c 1237f000ec7a491009b1233f5c626ea71bce1ea2
F src/test_init.c 5d624ffd0409d424cf9adbfe1f056b200270077c
F src/test_intarray.c d879bbf8e4ce085ab966d1f3c896a7c8b4f5fc99
F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
F src/test_journal.c 424a334cdfdc8a6f975abe3641440147bded3185
F src/test_journal.c 785edd54f963aefb3c1628124170a56697c68c70
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
F src/test_malloc.c 4ab85f2b8ae3a237f4e6557b0a641181a19ffab1
F src/test_malloc.c 09a88f0c111201dc4f8c20470aa1b5f611d59200
F src/test_mutex.c ce06b59aca168cd8c520b77159a24352a7469bd3
F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
F src/test_osinst.c f408c6a181f2fb04c56273afd5c3e1e82f60392c
F src/test_pcache.c 7bf828972ac0d2403f5cfa4cd14da41f8ebe73d8
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
F src/test_stat.c 6ebaf2a86d01ccda24e49c148f1d33e8badda06e
F src/test_stat.c f682704b5d1ba8e1d4e7e882a6d7922e2dcf066c
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
F src/test_thread.c bedd05cad673dba53326f3aa468cc803038896c0
F src/test_vfs.c 7e291f85256516ebde6633bc381ff7eedfa30234
F src/test_vfs.c 702e52636113f6b9721da90ef1bf26e07fff414d
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c 25ceb0f0a746ea1d0f9553787f3f0a56853cfaeb
F src/trigger.c 67e95c76d625b92d43409ace771c8e0d02a09ac2
F src/update.c 19c899c23cd29fd102c9068e0b0ff5b087204beb
F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080
F src/trigger.c b8bedb9c0084ceb51a40f54fcca2ce048c8de852
F src/update.c 1521162d20c2994af1fdc8833e1a88dae09052c8
F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685
F src/util.c 32aebf04c10e51ad3977a928b7416bed671b620b
F src/vacuum.c 241a8386727c1497eba4955933356dfba6ff8c9f
F src/vdbe.c 6294de3327e09d14e9c06ecfd10e57c2d8e85307
F src/vdbe.h 471f6a3dcec4817ca33596fe7f6654d56c0e75f3
F src/vdbeInt.h 19ebc8c2a2e938340051ee65af3f377fb99102d1
F src/vdbeapi.c dc3138f10afbc95ed3c21dd25abb154504b1db9d
F src/vdbeaux.c 7f99c1f00e4b31e8b28d8a87ecc2322bb46ae99c
F src/vdbe.c 66c262a923915e596379b1d597178e04c5d719e4
F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2
F src/vdbeInt.h ffd68c4d4229227a5089bec53a1c635146177abc
F src/vdbeapi.c d0f4407e465f261780ad725c1caece7d66a6aa35
F src/vdbeaux.c c73bcefcebfd3d2cf91bf6a41ef0fb0d884814c6
F src/vdbeblob.c 258a6010ba7a82b72b327fb24c55790655689256
F src/vdbemem.c 5e579abf6532001dfbee0e640dc34eae897a9807
F src/vdbemem.c e5673f81a2381b35c60e73ef0a8502be2ab1041e
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
F src/vtab.c a0f8a40274e4261696ef57aa806de2776ab72cda
F src/wal.c 0925601f3299c2941a67c9cfff41ee710f70ca82
F src/wal.h 906c85760598b18584921fe08008435aa4eeeeb2
F src/vtab.c 0e8e0cb30dffb078367e843e84e37ef99236c7e4
F src/wal.c 5ac2119e23ee4424599d4275b66dc88d612a0543
F src/wal.h 96669b645e27cd5a111ba59f0cae7743a207bc3c
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c 903a7828a0a7de03b5d0f1b5eff222d8d5b138f1
F src/where.c 7db3e41c2a846f9deeb24f1bbb75461b4010b7b5
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 6745008c144bd2956d58864d21f7b304689c1cce
@@ -244,7 +244,7 @@ F test/alter4.test 9386ffd1e9c7245f43eca412b2058d747509cc1f
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
F test/analyze.test bf692e7db414f268a136bade16c03a1bdbb9240c
F test/analyze2.test 59dac6c399c0c5d1a90a11ee7cc606743fb6db93
F test/analyze3.test 506203875258ffd8ffa879b9c3c5432022d2b6d8
F test/analyze3.test 6d4f4b0929545a9d1af803a0608a0c51b92a3537
F test/async.test ad4ba51b77cd118911a3fe1356b0809da9c108c3
F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
@@ -262,6 +262,7 @@ F test/autoindex1.test 7df441bf0e7a88644eb80993339dbf1db3a12c68
F test/autovacuum.test bb7c0885e6f8f1d633045de48f2b66082162766d
F test/autovacuum_ioerr2.test 598b0663074d3673a9c1bc9a16e80971313bafe6
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
F test/backcompat.test 49bd844eb245f0b2b6f2a3f8bebad0065403a9a7
F test/backup.test 200e64bd91244b73ca8094bc1e03dfc83cc94c2e
F test/backup2.test b7c69f937c912e85ac8a5dbd1e1cf290302b2d49
F test/backup_ioerr.test 1f012e692f42c0442ae652443258f70e9f20fa38
@@ -304,7 +305,7 @@ F test/collate9.test 3adcc799229545940df2f25308dd1ad65869145a
F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6
F test/colmeta.test 087c42997754b8c648819832241daf724f813322
F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b
F test/conflict.test 0ed68b11f22721052d880ee80bd528a0e0828236
F test/conflict.test f2f2b2950730a9532e11e468070cebf389f5c375
F test/corrupt.test 1a5bef8b2d178859af69814ecedcd37219a89968
F test/corrupt2.test 808a28d0ca3b97e9aa8c91cd2b485ea2700b76d1
F test/corrupt3.test a399dacccb91c732f6b071c913e70d195af8c058
@@ -333,7 +334,7 @@ F test/createtab.test 199cf68f44e5d9e87a0b8afc7130fdeb4def3272
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
F test/date.test 6354b883f922c38046a8efbad187cc95df6da023
F test/dbstatus.test 838447a0ecca1232675b025c0a518a9ef0f8057e
F test/dbstatus.test 946e1399d4574fc5dac934cceedbc76924af3f5a
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
F test/delete.test f7629d9eb245dfca170169cc5c7a735dec34aeb4
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
@@ -343,21 +344,22 @@ F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
F test/descidx3.test fe720e8b37d59f4cef808b0bf4e1b391c2e56b6f
F test/diskfull.test 0cede7ef9d8f415d9d3944005c76be7589bb5ebb
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
F test/e_expr.test 141e53fea525bce4f5403fcb0067b88e64fec5eb
F test/e_expr.test 8a35ce2718c61e871970bda09f4f3e549067c1ba
F test/e_fkey.test 6721a741c6499b3ab7e5385923233343c8f1ad05
F test/e_fts3.test 75bb0aee26384ef586165e21018a17f7cd843469
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 6d91a5286f59add0cfcbb2d0da913b76f2242398
F test/enc3.test 5c550d59ff31dccdba5d1a02ae11c7047d77c041
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
F test/exclusive.test 5fe18e10a159342dd52ca14b1554e33f98734267
F test/exclusive.test b1f9012cabc124af947165d15ffa62ad20f63db8
F test/exclusive2.test fcbb1c9ca9739292a0a22a3763243ad6d868086b
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/expr.test 9f521ae22f00e074959f72ce2e55d46b9ed23f68
F test/fallocate.test 43dc34b8c24be6baffadc3b4401ee15710ce83c6
F test/filectrl.test 97003734290887566e01dded09dc9e99cb937e9e
F test/filefmt.test f77c92141960b7933bc6691631d2ad62257ef40a
F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da
F test/fkey2.test 098c06c139a79f690301a43511cd1f6420ae5433
F test/fkey2.test e028cd80aa0bd38541c99214e3ba2dfccadffe6f
F test/fkey3.test 42f88d6048d8dc079e2a8cf7baad1cc1483a7620
F test/fkey_malloc.test a5ede29bd2f6e56dea78c3d43fb86dd696c068c8
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
@@ -434,7 +436,7 @@ F test/fuzz3.test aec64345184d1662bd30e6a17851ff659d596dc5
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test dd7001ac86d09c154a7dff064f4739c60e2b312c
F test/hook.test f04c3412463f8ec117c1c704c74ca0f627ce733a
F test/icu.test 1fc0ff9a3bafc80abf679b11afc0f8a3ce995abd
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
F test/in.test d49419c6df515852f477fa513f3317181d46bc92
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
@@ -448,7 +450,7 @@ F test/incrvacuum_ioerr.test 57d2f5777ab13fa03b87b262a4ea1bad5cfc0291
F test/index.test cbf301cdb2da43e4eac636c3400c2439af1834ad
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
F test/index3.test 423a25c789fc8cc51aaf2a4370bbdde2d9e9eed7
F test/indexedby.test 946ca2628a521f4ced0520421a0788345abaf3dc
F test/indexedby.test 5a1180602f2e72c481467bd4cae05dae5dc36f47
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test aef273dd1cee84cc92407469e6bd1b3cdcb76908
F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
@@ -463,7 +465,7 @@ F test/ioerr.test 390785ec65f10aa58a82b048ee12e9052d783fa8
F test/ioerr2.test 1b56cb80d5b0726ee3ba325ca175734541e32955
F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
F test/ioerr4.test fc6eddfec2efc2f1ed217b9eae4c1c1d3516ce86
F test/ioerr5.test 89f69b09a6b5d4f5bbfe58d4231f28236d842dcb
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/join.test 8d63cc4d230a7affafa4b6ab0b97c49b8ccb365c
F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
@@ -473,13 +475,13 @@ F test/join6.test bf82cf3f979e9eade83ad0d056a66c5ed71d1901
F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19
F test/journal2.test 50a3604768494d4a337f194f0a9480e7c57dcb72
F test/journal3.test ff175219be1b02d2f7e54297ad7e491b7533edb6
F test/jrnlmode.test 2d5a8b6d68de8512f522532731d90ca96912f3b7
F test/jrnlmode.test e3fe6c4a2c3213d285650dc8e33aab7eaaa5ce53
F test/jrnlmode2.test a19e28de1a6ec898067e46a122f1b71c9323bf00
F test/jrnlmode3.test cfcdb12b90e640a23b92785a002d96c0624c8710
F test/keyword1.test a2400977a2e4fde43bf33754c2929fda34dbca05
F test/lastinsert.test 474d519c68cb79d07ecae56a763aa7f322c72f51
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
F test/like.test 4b594af9eddfd01018df1e9b1d18721aff619fa7
F test/like.test 565d240313f15a8afa8d7098dc9fe303c1e2a496
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
F test/limit.test 2db7b3b34fb925b8e847d583d2eb67531d0ce67e
F test/loadext.test 0393ce12d9616aa87597dd0ec88181de181f6db0
@@ -491,7 +493,7 @@ F test/lock4.test c82268c031d39345d05efa672f80b025481b3ae5
F test/lock5.test b2abb5e711bc59b0eae00f6c97a36ec9f458fada
F test/lock6.test 8df56060f396151777390982422c800d026e1722
F test/lock7.test 64006c84c1c616657e237c7ad6532b765611cf64
F test/lock_common.tcl e7013c6208f5fa818735c324eb0249b4c0f317cf
F test/lock_common.tcl 18c637fc89e12f1ac0d27d2186f12c3d3f789e3e
F test/lookaside.test 382e7bc2fab23d902c8eafb1b9ed7ababfff75a6
F test/main.test 9d7bbfcc1b52c88ba7b2ba6554068ecf9939f252
F test/make-where7.tcl 05c16b5d4f5d6512881dfec560cb793915932ef9
@@ -537,19 +539,20 @@ F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test a44e04df1486fcfb02d32468cbcd3c8e1e433723
F test/notify1.test 8433bc74bd952fb8a6e3f8d7a4c2b28dfd69e310
F test/notify2.test 195a467e021f74197be2c4fb02d6dee644b8d8db
F test/notify3.test 7eeba3628c4e707c004b72a2489c48fbdbc5c2ee
F test/notify3.test d60923e186e0900f4812a845fcdfd8eea096e33a
F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
F test/null.test a8b09b8ed87852742343b33441a9240022108993
F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
F test/pager1.test d8e4b2bc8164c920e6ea0572c9e13576d6e4f3fa
F test/pager2.test f5c757c271ce642d36a393ecbfb3aef1c240dcef
F test/pagerfault.test c1d176326ce244db157ce9c3ba128be2a9b172d6
F test/pager1.test 6922029d71a8090169c71a67a141b6b94ad17d50
F test/pager2.test 0fbb6b6dc40ce1fecfe758c555a748ad2e9beaa3
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
F test/pagerfault.test 84c6a4fcfe1a9e450fc1cec86f5baebfb017e53e
F test/pagerfault2.test 1f79ea40d1133b2683a2f811b00f2399f7ec2401
F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806
F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb
F test/pcache.test 4118a183908ecaed343a06fcef3ba82e87e0129d
F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16
F test/permutations.test 3fe47c21c32b294b2354e702a25bfbff65747bb1
F test/permutations.test 17498d1219f922d5a6da893a94c4dc7766fb2426
F test/pragma.test ed78d200f65c6998df51196cb8c39d5300570f24
F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
@@ -586,9 +589,9 @@ F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
F test/select9.test 74c0fb2c6eecb0219cbed0cbe3df136f8fbf9343
F test/selectA.test 06d1032fa9009314c95394f2ca2e60d9f7ae8532
F test/selectB.test f305cc6660804cb239aab4e2f26b0e288b59958b
F test/selectC.test 33bb5673a8141df193c6fd56e6de7fea38b8d2ee
F test/selectC.test f9bf1bc4581b5b8158caa6e4e4f682acb379fb25
F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c
F test/shared.test 3b448dc0f7a9356e641894ed81c27599f39d809d
F test/shared.test b9114eaea7e748a3a4c8ff7b9ca806c8f95cef3e
F test/shared2.test d6ba4ca1827ea36a1ac23a99e3c36eeac9165450
F test/shared3.test d69bdd5f156580876c5345652d21dc2092e85962
F test/shared4.test d0fadacb50bb6981b2fb9dc6d1da30fa1edddf83
@@ -622,7 +625,7 @@ F test/tclsqlite.test 8c154101e704170c2be10f137a5499ac2c6da8d3
F test/tempdb.test 800c36623d67a2ad1f58784b9c5644e0405af6e6
F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a
F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05
F test/tester.tcl 295800403a36c4319354482749e9282ce47b7edc
F test/tester.tcl 6135019fcfac363ea0e11aee670cc97080ab578e
F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f
F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db
F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca
@@ -633,12 +636,14 @@ F test/thread2.test e08034b83fe9693ade77049732518e5b3d2d700d
F test/thread_common.tcl 2aa6f2fdcd4d6e461169c3e5ca098eebf643b863
F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b
F test/threadtest2.c ace893054fa134af3fc8d6e7cfecddb8e3acefb9
F test/threadtest3.c 58df1e3c060f534fd7fb0702331b0acc41c381d8
F test/tkt-02a8e81d44.test 58494de77be2cf249228ada3f313fa399821c6ab
F test/tkt-26ff0c2d1e.test 888324e751512972c6e0d1a09df740d8f5aaf660
F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
F test/tkt-31338dca7e.test 5741cd48de500347a437ba1be58c8335e83c5a5e
F test/tkt-3fe897352e.test 10de1a67bd5c66b238a4c96abe55531b37bb4f00
F test/tkt-4a03edc4c8.test 2865e4edbc075b954daa82f8da7cc973033ec76e
F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
F test/tkt-5ee23731f.test 3581260f2a71e51db94e1506ba6b0f7311d002a9
F test/tkt-78e04e52ea.test fb5430c675e708f5cbafdf3e7e5593da5145a527
F test/tkt-80e031a00f.test 9a154173461a4dbe2de49cda73963e04842d52f7
@@ -647,6 +652,7 @@ F test/tkt-9d68c883.test 458f7d82a523d7644b54b497c986378a7d8c8b67
F test/tkt-cbd054fa6b.test f14f97ea43662e6f70c9e63287081e8be5d9d589
F test/tkt-d11f09d36e.test fb44f7961aa6d4b632fb7b9768239832210b5fc7
F test/tkt-d82e3f3721.test 731359dfdcdb36fea0559cd33fec39dd0ceae8e6
F test/tkt-f3e5abed55.test 91713833e266fbdc60f2030e05647ad4762073f6
F test/tkt-f777251dc7a.test 6f24c053bc5cdb7e1e19be9a72c8887cf41d5e87
F test/tkt-f973c7ac31.test 1da0ed15ec2c7749fb5ce2828cd69d07153ad9f4
F test/tkt-fc62af4523.test 72825d3febdedcd5593a27989fc05accdbfc2bb4
@@ -749,7 +755,7 @@ F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
F test/trigger9.test 5b0789f1c5c4600961f8e68511b825b87be53e31
F test/triggerA.test eaf11a29db2a11967d2d4b49d37f92bce598194e
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
F test/triggerC.test cac41fe31adc1abb9fa08532762fc2b4f662ab03
F test/triggerC.test 2a23edcc00684d084902ba5ec93e721775c3a70a
F test/triggerD.test c6add3817351451e419f6ff9e9a259b02b6e2de7
F test/types.test 9a825ec8eea4e965d7113b74c76a78bb5240f2ac
F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
@@ -781,9 +787,9 @@ F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
F test/wal.test 1891e6f72dd437a1c2a48091aa9182ba17a8f780
F test/wal2.test fa6dc4457b46988f46cf6c68ea51ebe341765f4a
F test/wal3.test d2ae7e66f973bd6b58ce49e546b2c00f44fe0485
F test/wal.test 70227190e713b3e7eb2a7d5ec3510b66db01f327
F test/wal2.test 223f3e14d475730af772a7f5862d4bcfa7565c3a
F test/wal3.test 695ea0f6c516423c611891df9a285aacd33344e3
F test/wal4.test 3404b048fa5e10605facaf70384e6d2943412e30
F test/wal_common.tcl 895d76138043b86bdccf36494054bdabcf65837b
F test/walbak.test 4df1c7369da0301caeb9a48fa45997fd592380e4
@@ -793,12 +799,13 @@ F test/walcrash.test e763841551d6b23677ccb419797c1589dcbdbaf5
F test/walcrash2.test 019d60b89d96c1937adb2b30b850ac7e86e5a142
F test/walfault.test 05c470688d742688e455dd56816bd6bcffa298f8
F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
F test/walmode.test 5dc3008ef71988ecdd949ea16e5750e325b92b54
F test/walmode.test 4ecd37284f245247f7935896ab66f6943f0432a0
F test/walshared.test 985b4a3406b2b2dace1d52a42d26a11dd6900981
F test/walslow.test d21625e2e99e11c032ce949e8a94661576548933
F test/walthread.test a25a393c068a2b42b44333fa3fdaae9072f1617c
F test/where.test de337a3fe0a459ec7c93db16a519657a90552330
F test/where2.test 43d4becaf5a5df854e6c21d624a1cb84c6904554
F test/where3.test aa44a9b29e8c9f3d7bb94a3bb3a95b31627d520d
F test/where3.test 3bf8006d441b66a57bee02bb420423f84eb8fde3
F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
@@ -825,10 +832,12 @@ F tool/mksqlite3internalh.tcl 7b43894e21bcb1bb39e11547ce7e38a063357e87
F tool/omittest.tcl 27d6f6e3b1e95aeb26a1c140e6eb57771c6d794a
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/shell1.test a738c71bc08ea9162baee9a14b3cf9994f181921
F tool/shell1.test 930444cadb71ce9ce78bc6cd14ec21e6b69776ea
F tool/shell2.test 5dc76b8005b465f420fed8241621da7513060ff3
F tool/shell3.test 4fad469e8003938426355afdf34155f08c587836
F tool/showdb.c 01c20e8181941b714fe07f72c64a7560fee17ff9
F tool/shell4.test 35f9c3d452b4e76d5013c63e1fd07478a62f14ce
F tool/shell5.test 62bfaf9267296da1b91e4b1c03e44e7b393f6a94
F tool/showdb.c c7a978cf525ef0f8bc2fd29cd52108dd1dfa605a
F tool/showjournal.c ec3b171be148656827c4949fbfb8ab4370822f87
F tool/showwal.c f09e5a80a293919290ec85a6a37c85a5ddcf37d9
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
@@ -840,14 +849,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P 5074b85967df8f55739ba790924347c764288a88
R f5778ea9917b1adb206cc22be6e49c29
P 21a1e5961bba148fda50cc0b7d472ca74f90808a
R aa9cc30f9dbcb7ea427137065cf4e4be
U drh
Z 60fae2989ec1bf91141b6299767f6365
Z e73ee740c6593b4458c2d23b6fa7b923
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFMWV2SoxKgR168RlERAiENAJ9TfAN62Ul3mO+iNQD+b8HJNbjgOwCeIZwB
BZSXOygjVggzK2g+JjZSHP8=
=3zag
iD8DBQFMcsNUoxKgR168RlERApyRAKCOHvk0Gn1uE2F8YVm3k/w13/3UugCeOh16
bApiXjM1a7FP+Qr1HX5kWTQ=
=L2Lf
-----END PGP SIGNATURE-----
+1 -1
View File
@@ -1 +1 @@
042a1abb030a0711386add7eb6e10832cc8b0f57
42537b60566f288167f1b5864a5435986838e3a3
-1
View File
@@ -769,7 +769,6 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
if( !pNew ) goto exit_begin_add_column;
pParse->pNewTable = pNew;
pNew->nRef = 1;
pNew->dbMem = pTab->dbMem;
pNew->nCol = pTab->nCol;
assert( pNew->nCol>0 );
nAlloc = (((pNew->nCol-1)/8)*8)+8;
+10 -13
View File
@@ -490,21 +490,20 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
** If the Index.aSample variable is not NULL, delete the aSample[] array
** and its contents.
*/
void sqlite3DeleteIndexSamples(Index *pIdx){
void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
#ifdef SQLITE_ENABLE_STAT2
if( pIdx->aSample ){
int j;
sqlite3 *dbMem = pIdx->pTable->dbMem;
for(j=0; j<SQLITE_INDEX_SAMPLES; j++){
IndexSample *p = &pIdx->aSample[j];
if( p->eType==SQLITE_TEXT || p->eType==SQLITE_BLOB ){
sqlite3DbFree(pIdx->pTable->dbMem, p->u.z);
sqlite3DbFree(db, p->u.z);
}
}
sqlite3DbFree(dbMem, pIdx->aSample);
pIdx->aSample = 0;
sqlite3DbFree(db, pIdx->aSample);
}
#else
UNUSED_PARAMETER(db);
UNUSED_PARAMETER(pIdx);
#endif
}
@@ -543,7 +542,8 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
sqlite3DefaultRowEst(pIdx);
sqlite3DeleteIndexSamples(pIdx);
sqlite3DeleteIndexSamples(db, pIdx);
pIdx->aSample = 0;
}
/* Check to make sure the sqlite_stat1 table exists */
@@ -587,18 +587,17 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
Index *pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase);
if( pIdx ){
int iSample = sqlite3_column_int(pStmt, 1);
sqlite3 *dbMem = pIdx->pTable->dbMem;
assert( dbMem==db || dbMem==0 );
if( iSample<SQLITE_INDEX_SAMPLES && iSample>=0 ){
int eType = sqlite3_column_type(pStmt, 2);
if( pIdx->aSample==0 ){
static const int sz = sizeof(IndexSample)*SQLITE_INDEX_SAMPLES;
pIdx->aSample = (IndexSample *)sqlite3DbMallocZero(dbMem, sz);
pIdx->aSample = (IndexSample *)sqlite3DbMallocRaw(0, sz);
if( pIdx->aSample==0 ){
db->mallocFailed = 1;
break;
}
memset(pIdx->aSample, 0, sz);
}
assert( pIdx->aSample );
@@ -621,10 +620,8 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
if( n < 1){
pSample->u.z = 0;
}else{
pSample->u.z = sqlite3DbMallocRaw(dbMem, n);
if( pSample->u.z ){
memcpy(pSample->u.z, z, n);
}else{
pSample->u.z = sqlite3DbStrNDup(0, z, n);
if( pSample->u.z==0 ){
db->mallocFailed = 1;
break;
}
+9
View File
@@ -221,6 +221,15 @@ static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
rc = SQLITE_READONLY;
}
#ifdef SQLITE_HAS_CODEC
/* Backup is not possible if the page size of the destination is changing
** a a codec is in use.
*/
if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){
rc = SQLITE_READONLY;
}
#endif
/* This loop runs once for each destination page spanned by the source
** page. For each iteration, variable iOff is set to the byte offset
** of the destination page.
+1 -1
View File
@@ -37,7 +37,7 @@
#include "sqliteInt.h"
/* Size of the Bitvec structure in bytes. */
#define BITVEC_SZ (sizeof(void*)*128) /* 512 on 32bit. 1024 on 64bit */
#define BITVEC_SZ 512
/* Round the union size down to the nearest pointer boundary, since that's how
** it will be aligned within the Bitvec struct. */
+99 -54
View File
@@ -32,7 +32,16 @@ int sqlite3BtreeTrace=1; /* True to enable tracing */
# define TRACE(X)
#endif
/*
** Extract a 2-byte big-endian integer from an array of unsigned bytes.
** But if the value is zero, make it 65536.
**
** This routine is used to extract the "offset to cell content area" value
** from the header of a btree page. If the page size is 65536 and the page
** is empty, the offset should be 65536, but the 2-byte value stores zero.
** This routine makes the necessary adjustment to 65536.
*/
#define get2byteNotZero(X) (((((int)get2byte(X))-1)&0xffff)+1)
#ifndef SQLITE_OMIT_SHARED_CACHE
/*
@@ -721,11 +730,16 @@ int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){
** Given a page number of a regular database page, return the page
** number for the pointer-map page that contains the entry for the
** input page number.
**
** Return 0 (not a valid page) for pgno==1 since there is
** no pointer map associated with page 1. The integrity_check logic
** requires that ptrmapPageno(*,1)!=1.
*/
static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){
int nPagesPerMapPage;
Pgno iPtrMap, ret;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pgno<2 ) return 0;
nPagesPerMapPage = (pBt->usableSize/5)+1;
iPtrMap = (pgno-2)/nPagesPerMapPage;
ret = (iPtrMap*nPagesPerMapPage) + 2;
@@ -1154,7 +1168,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
nFrag = data[hdr+7];
assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf );
gap = pPage->cellOffset + 2*pPage->nCell;
top = get2byte(&data[hdr+5]);
top = get2byteNotZero(&data[hdr+5]);
if( gap>top ) return SQLITE_CORRUPT_BKPT;
testcase( gap+2==top );
testcase( gap+1==top );
@@ -1164,7 +1178,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
/* Always defragment highly fragmented pages */
rc = defragmentPage(pPage);
if( rc ) return rc;
top = get2byte(&data[hdr+5]);
top = get2byteNotZero(&data[hdr+5]);
}else if( gap+2<=top ){
/* Search the freelist looking for a free slot big enough to satisfy
** the request. The allocation is made from the first free slot in
@@ -1206,7 +1220,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
if( gap+2+nByte>top ){
rc = defragmentPage(pPage);
if( rc ) return rc;
top = get2byte(&data[hdr+5]);
top = get2byteNotZero(&data[hdr+5]);
assert( gap+nByte<=top );
}
@@ -1372,10 +1386,10 @@ static int btreeInitPage(MemPage *pPage){
u8 hdr; /* Offset to beginning of page header */
u8 *data; /* Equal to pPage->aData */
BtShared *pBt; /* The main btree structure */
u16 usableSize; /* Amount of usable space on each page */
int usableSize; /* Amount of usable space on each page */
u16 cellOffset; /* Offset from start of page to first cell pointer */
u16 nFree; /* Number of unused bytes on the page */
u16 top; /* First byte of the cell content area */
int nFree; /* Number of unused bytes on the page */
int top; /* First byte of the cell content area */
int iCellFirst; /* First allowable cell or freeblock offset */
int iCellLast; /* Last possible cell or freeblock offset */
@@ -1384,12 +1398,12 @@ static int btreeInitPage(MemPage *pPage){
hdr = pPage->hdrOffset;
data = pPage->aData;
if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT;
assert( pBt->pageSize>=512 && pBt->pageSize<=32768 );
pPage->maskPage = pBt->pageSize - 1;
assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
pPage->maskPage = (u16)(pBt->pageSize - 1);
pPage->nOverflow = 0;
usableSize = pBt->usableSize;
pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf;
top = get2byte(&data[hdr+5]);
top = get2byteNotZero(&data[hdr+5]);
pPage->nCell = get2byte(&data[hdr+3]);
if( pPage->nCell>MX_CELL(pBt) ){
/* To many cells for a single page. The page must be corrupt */
@@ -1488,13 +1502,13 @@ static void zeroPage(MemPage *pPage, int flags){
memset(&data[hdr+1], 0, 4);
data[hdr+7] = 0;
put2byte(&data[hdr+5], pBt->usableSize);
pPage->nFree = pBt->usableSize - first;
pPage->nFree = (u16)(pBt->usableSize - first);
decodeFlags(pPage, flags);
pPage->hdrOffset = hdr;
pPage->cellOffset = first;
pPage->nOverflow = 0;
assert( pBt->pageSize>=512 && pBt->pageSize<=32768 );
pPage->maskPage = pBt->pageSize - 1;
assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
pPage->maskPage = (u16)(pBt->pageSize - 1);
pPage->nCell = 0;
pPage->isInit = 1;
}
@@ -1802,7 +1816,7 @@ int sqlite3BtreeOpen(
#ifdef SQLITE_SECURE_DELETE
pBt->secureDelete = 1;
#endif
pBt->pageSize = get2byte(&zDbHeader[16]);
pBt->pageSize = (zDbHeader[16]<<8) | (zDbHeader[17]<<16);
if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE
|| ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
pBt->pageSize = 0;
@@ -2004,7 +2018,7 @@ int sqlite3BtreeClose(Btree *p){
if( pBt->xFreeSchema && pBt->pSchema ){
pBt->xFreeSchema(pBt->pSchema);
}
sqlite3_free(pBt->pSchema);
sqlite3DbFree(0, pBt->pSchema);
freeTempSpace(pBt);
sqlite3_free(pBt);
}
@@ -2116,7 +2130,7 @@ int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
((pageSize-1)&pageSize)==0 ){
assert( (pageSize & 7)==0 );
assert( !pBt->pPage1 && !pBt->pCursor );
pBt->pageSize = (u16)pageSize;
pBt->pageSize = (u32)pageSize;
freeTempSpace(pBt);
}
rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve);
@@ -2251,15 +2265,13 @@ static int lockBtree(BtShared *pBt){
** a valid database file.
*/
nPage = nPageHeader = get4byte(28+(u8*)pPage1->aData);
if( (rc = sqlite3PagerPagecount(pBt->pPager, &nPageFile))!=SQLITE_OK ){;
goto page1_init_failed;
}
sqlite3PagerPagecount(pBt->pPager, &nPageFile);
if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
nPage = nPageFile;
}
if( nPage>0 ){
int pageSize;
int usableSize;
u32 pageSize;
u32 usableSize;
u8 *page1 = pPage1->aData;
rc = SQLITE_NOTADB;
if( memcmp(page1, zMagicHeader, 16)!=0 ){
@@ -2310,15 +2322,16 @@ static int lockBtree(BtShared *pBt){
if( memcmp(&page1[21], "\100\040\040",3)!=0 ){
goto page1_init_failed;
}
pageSize = get2byte(&page1[16]);
if( ((pageSize-1)&pageSize)!=0 || pageSize<512 ||
(SQLITE_MAX_PAGE_SIZE<32768 && pageSize>SQLITE_MAX_PAGE_SIZE)
pageSize = (page1[16]<<8) | (page1[17]<<16);
if( ((pageSize-1)&pageSize)!=0
|| pageSize>SQLITE_MAX_PAGE_SIZE
|| pageSize<=256
){
goto page1_init_failed;
}
assert( (pageSize & 7)==0 );
usableSize = pageSize - page1[20];
if( pageSize!=pBt->pageSize ){
if( (u32)pageSize!=pBt->pageSize ){
/* After reading the first page of the database assuming a page size
** of BtShared.pageSize, we have discovered that the page-size is
** actually pageSize. Unlock the database, leave pBt->pPage1 at
@@ -2326,8 +2339,8 @@ static int lockBtree(BtShared *pBt){
** again with the correct page-size.
*/
releasePage(pPage1);
pBt->usableSize = (u16)usableSize;
pBt->pageSize = (u16)pageSize;
pBt->usableSize = usableSize;
pBt->pageSize = pageSize;
freeTempSpace(pBt);
rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize,
pageSize-usableSize);
@@ -2340,8 +2353,8 @@ static int lockBtree(BtShared *pBt){
if( usableSize<480 ){
goto page1_init_failed;
}
pBt->pageSize = (u16)pageSize;
pBt->usableSize = (u16)usableSize;
pBt->pageSize = pageSize;
pBt->usableSize = usableSize;
#ifndef SQLITE_OMIT_AUTOVACUUM
pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0);
pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0);
@@ -2357,14 +2370,14 @@ static int lockBtree(BtShared *pBt){
** 9-byte nKey value
** 4-byte nData value
** 4-byte overflow page pointer
** So a cell consists of a 2-byte poiner, a header which is as much as
** So a cell consists of a 2-byte pointer, a header which is as much as
** 17 bytes long, 0 to N bytes of payload, and an optional 4 byte overflow
** page pointer.
*/
pBt->maxLocal = (pBt->usableSize-12)*64/255 - 23;
pBt->minLocal = (pBt->usableSize-12)*32/255 - 23;
pBt->maxLeaf = pBt->usableSize - 35;
pBt->minLeaf = (pBt->usableSize-12)*32/255 - 23;
pBt->maxLocal = (u16)((pBt->usableSize-12)*64/255 - 23);
pBt->minLocal = (u16)((pBt->usableSize-12)*32/255 - 23);
pBt->maxLeaf = (u16)(pBt->usableSize - 35);
pBt->minLeaf = (u16)((pBt->usableSize-12)*32/255 - 23);
assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) );
pBt->pPage1 = pPage1;
pBt->nPage = nPage;
@@ -2417,7 +2430,8 @@ static int newDatabase(BtShared *pBt){
if( rc ) return rc;
memcpy(data, zMagicHeader, sizeof(zMagicHeader));
assert( sizeof(zMagicHeader)==16 );
put2byte(&data[16], pBt->pageSize);
data[16] = (u8)((pBt->pageSize>>8)&0xff);
data[17] = (u8)((pBt->pageSize>>16)&0xff);
data[18] = 1;
data[19] = 1;
assert( pBt->usableSize<=pBt->pageSize && pBt->usableSize+255>=pBt->pageSize);
@@ -3328,9 +3342,11 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
if( iSavepoint<0 && pBt->initiallyEmpty ) pBt->nPage = 0;
rc = newDatabase(pBt);
pBt->nPage = get4byte(28 + pBt->pPage1->aData);
if( pBt->nPage==0 ){
sqlite3PagerPagecount(pBt->pPager, (int*)&pBt->nPage);
}
/* The database size was written into the offset 28 of the header
** when the transaction started, so we know that the value at offset
** 28 is nonzero. */
assert( pBt->nPage>0 );
}
sqlite3BtreeLeave(p);
}
@@ -4426,9 +4442,9 @@ int sqlite3BtreeMovetoUnpacked(
pCur->validNKey = 1;
pCur->info.nKey = nCellKey;
}else{
/* The maximum supported page-size is 32768 bytes. This means that
/* The maximum supported page-size is 65536 bytes. This means that
** the maximum number of record bytes stored on an index B-Tree
** page is at most 8198 bytes, which may be stored as a 2-byte
** page is less than 16384 bytes and may be stored as a 2-byte
** varint. This information is used to attempt to avoid parsing
** the entire cell by checking for the cases where the record is
** stored entirely within the b-tree page by inspecting the first
@@ -4791,6 +4807,10 @@ static int allocateBtreePage(
if( !pPrevTrunk ){
memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
}else{
rc = sqlite3PagerWrite(pPrevTrunk->pDbPage);
if( rc!=SQLITE_OK ){
goto end_allocate_page;
}
memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4);
}
}else{
@@ -5097,7 +5117,7 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
Pgno ovflPgno;
int rc;
int nOvfl;
u16 ovflPageSize;
u32 ovflPageSize;
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
btreeParseCellPtr(pPage, pCell, &info);
@@ -5322,7 +5342,7 @@ static int fillInCell(
*/
static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
int i; /* Loop counter */
int pc; /* Offset to cell content of cell being deleted */
u32 pc; /* Offset to cell content of cell being deleted */
u8 *data; /* pPage->aData */
u8 *ptr; /* Used to move bytes around within data[] */
int rc; /* The return code */
@@ -5340,7 +5360,7 @@ static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
hdr = pPage->hdrOffset;
testcase( pc==get2byte(&data[hdr+5]) );
testcase( pc+sz==pPage->pBt->usableSize );
if( pc < get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){
if( pc < (u32)get2byte(&data[hdr+5]) || pc+sz > pPage->pBt->usableSize ){
*pRC = SQLITE_CORRUPT_BKPT;
return;
}
@@ -5397,7 +5417,7 @@ static void insertCell(
if( *pRC ) return;
assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=5460 );
assert( pPage->nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=10921 );
assert( pPage->nOverflow<=ArraySize(pPage->aOvfl) );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
/* The cell should normally be sized correctly. However, when moving a
@@ -5477,12 +5497,12 @@ static void assemblePage(
assert( pPage->nOverflow==0 );
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
assert( nCell>=0 && nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=5460 );
assert( nCell>=0 && nCell<=MX_CELL(pPage->pBt) && MX_CELL(pPage->pBt)<=10921);
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
/* Check that the page has just been zeroed by zeroPage() */
assert( pPage->nCell==0 );
assert( get2byte(&data[hdr+5])==nUsable );
assert( get2byteNotZero(&data[hdr+5])==nUsable );
pCellptr = &data[pPage->cellOffset + nCell*2];
cellbody = nUsable;
@@ -5548,6 +5568,7 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
assert( pPage->nOverflow==1 );
/* This error condition is now caught prior to reaching this function */
if( pPage->nCell<=0 ) return SQLITE_CORRUPT_BKPT;
/* Allocate a new page. This page will become the right-sibling of
@@ -5877,7 +5898,7 @@ static int balance_nonroot(
** is allocated. */
if( pBt->secureDelete ){
int iOff = SQLITE_PTR_TO_INT(apDiv[i]) - SQLITE_PTR_TO_INT(pParent->aData);
if( (iOff+szNew[i])>pBt->usableSize ){
if( (iOff+szNew[i])>(int)pBt->usableSize ){
rc = SQLITE_CORRUPT_BKPT;
memset(apOld, 0, (i+1)*sizeof(MemPage*));
goto balance_cleanup;
@@ -5956,7 +5977,7 @@ static int balance_nonroot(
szCell[nCell] = sz;
pTemp = &aSpace1[iSpace1];
iSpace1 += sz;
assert( sz<=pBt->pageSize/4 );
assert( sz<=pBt->maxLocal+23 );
assert( iSpace1<=pBt->pageSize );
memcpy(pTemp, apDiv[i], sz);
apCell[nCell] = pTemp+leafCorrection;
@@ -6202,7 +6223,7 @@ static int balance_nonroot(
}
}
iOvflSpace += sz;
assert( sz<=pBt->pageSize/4 );
assert( sz<=pBt->maxLocal+23 );
assert( iOvflSpace<=pBt->pageSize );
insertCell(pParent, nxDiv, pCell, sz, pTemp, pNew->pgno, &rc);
if( rc!=SQLITE_OK ) goto balance_cleanup;
@@ -7446,7 +7467,7 @@ static void checkList(
checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0, zContext);
}
#endif
if( n>pCheck->pBt->usableSize/4-2 ){
if( n>(int)pCheck->pBt->usableSize/4-2 ){
checkAppendMsg(pCheck, zContext,
"freelist leaf count too big on page %d", iPage);
N--;
@@ -7657,7 +7678,7 @@ static int checkTreePage(
if( hit==0 ){
pCheck->mallocFailed = 1;
}else{
u16 contentOffset = get2byte(&data[hdr+5]);
int contentOffset = get2byteNotZero(&data[hdr+5]);
assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
memset(hit+contentOffset, 0, usableSize-contentOffset);
memset(hit, 1, contentOffset);
@@ -7665,12 +7686,12 @@ static int checkTreePage(
cellStart = hdr + 12 - 4*pPage->leaf;
for(i=0; i<nCell; i++){
int pc = get2byte(&data[cellStart+i*2]);
u16 size = 1024;
u32 size = 65536;
int j;
if( pc<=usableSize-4 ){
size = cellSizePtr(pPage, &data[pc]);
}
if( (pc+size-1)>=usableSize ){
if( (int)(pc+size-1)>=usableSize ){
checkAppendMsg(pCheck, 0,
"Corruption detected in cell %d on page %d",i,iPage);
}else{
@@ -7763,6 +7784,7 @@ char *sqlite3BtreeIntegrityCheck(
sCheck.anRef[i] = 1;
}
sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000);
sCheck.errMsg.useMalloc = 2;
/* Check the integrity of the freelist
*/
@@ -7861,6 +7883,29 @@ int sqlite3BtreeIsInTrans(Btree *p){
return (p && (p->inTrans==TRANS_WRITE));
}
#ifndef SQLITE_OMIT_WAL
/*
** Run a checkpoint on the Btree passed as the first argument.
**
** Return SQLITE_LOCKED if this or any other connection has an open
** transaction on the shared-cache the argument Btree is connected to.
*/
int sqlite3BtreeCheckpoint(Btree *p){
int rc = SQLITE_OK;
if( p ){
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
if( pBt->inTransaction!=TRANS_NONE ){
rc = SQLITE_LOCKED;
}else{
rc = sqlite3PagerCheckpoint(pBt->pPager);
}
sqlite3BtreeLeave(p);
}
return rc;
}
#endif
/*
** Return non-zero if a read (or write) transaction is active.
*/
@@ -7900,7 +7945,7 @@ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
BtShared *pBt = p->pBt;
sqlite3BtreeEnter(p);
if( !pBt->pSchema && nBytes ){
pBt->pSchema = sqlite3MallocZero(nBytes);
pBt->pSchema = sqlite3DbMallocZero(0, nBytes);
pBt->xFreeSchema = xFree;
}
sqlite3BtreeLeave(p);
+4
View File
@@ -201,6 +201,10 @@ int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
void sqlite3BtreeCursorList(Btree*);
#endif
#ifndef SQLITE_OMIT_WAL
int sqlite3BtreeCheckpoint(Btree*);
#endif
/*
** If we are not using shared cache, then there is no need to
** use mutexes to access the BtShared structures. So make the
+3 -3
View File
@@ -46,7 +46,7 @@
**
** The file is divided into pages. The first page is called page 1,
** the second is page 2, and so forth. A page number of zero indicates
** "no such page". The page size can be any power of 2 between 512 and 32768.
** "no such page". The page size can be any power of 2 between 512 and 65536.
** Each page can be either a btree page, a freelist page, an overflow
** page, or a pointer-map page.
**
@@ -413,14 +413,14 @@ struct BtShared {
u8 autoVacuum; /* True if auto-vacuum is enabled */
u8 incrVacuum; /* True if incr-vacuum is enabled */
#endif
u16 pageSize; /* Total number of bytes on a page */
u16 usableSize; /* Number of usable bytes on each page */
u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
u16 maxLeaf; /* Maximum local payload in a LEAFDATA table */
u16 minLeaf; /* Minimum local payload in a LEAFDATA table */
u8 inTransaction; /* Transaction state */
u8 doNotUseWAL; /* If true, do not open write-ahead-log file */
u32 pageSize; /* Total number of bytes on a page */
u32 usableSize; /* Number of usable bytes on each page */
int nTransaction; /* Number of open transactions (read + write) */
u32 nPage; /* Number of pages in the database */
void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
+33 -52
View File
@@ -345,33 +345,14 @@ Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
/*
** Reclaim the memory used by an index
*/
static void freeIndex(Index *p){
sqlite3 *db = p->pTable->dbMem;
static void freeIndex(sqlite3 *db, Index *p){
#ifndef SQLITE_OMIT_ANALYZE
sqlite3DeleteIndexSamples(p);
sqlite3DeleteIndexSamples(db, p);
#endif
sqlite3DbFree(db, p->zColAff);
sqlite3DbFree(db, p);
}
/*
** Remove the given index from the index hash table, and free
** its memory structures.
**
** The index is removed from the database hash tables but
** it is not unlinked from the Table that it indexes.
** Unlinking from the Table must be done by the calling function.
*/
static void sqlite3DeleteIndex(Index *p){
Index *pOld;
const char *zName = p->zName;
pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName,
sqlite3Strlen30(zName), 0);
assert( pOld==0 || pOld==p );
freeIndex(p);
}
/*
** For the index called zIdxName which is found in the database iDb,
** unlike that index from its Table then remove the index from
@@ -398,7 +379,7 @@ void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){
p->pNext = pIndex->pNext;
}
}
freeIndex(pIndex);
freeIndex(db, pIndex);
}
db->flags |= SQLITE_InternChanges;
}
@@ -469,13 +450,12 @@ void sqlite3CommitInternalChanges(sqlite3 *db){
}
/*
** Clear the column names from a table or view.
** Delete memory allocated for the column names of a table or view (the
** Table.aCol[] array).
*/
static void sqliteResetColumnNames(Table *pTable){
static void sqliteDeleteColumnNames(sqlite3 *db, Table *pTable){
int i;
Column *pCol;
sqlite3 *db = pTable->dbMem;
testcase( db==0 );
assert( pTable!=0 );
if( (pCol = pTable->aCol)!=0 ){
for(i=0; i<pTable->nCol; i++, pCol++){
@@ -487,8 +467,6 @@ static void sqliteResetColumnNames(Table *pTable){
}
sqlite3DbFree(db, pTable->aCol);
}
pTable->aCol = 0;
pTable->nCol = 0;
}
/*
@@ -500,42 +478,44 @@ static void sqliteResetColumnNames(Table *pTable){
** memory structures of the indices and foreign keys associated with
** the table.
*/
void sqlite3DeleteTable(Table *pTable){
void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
Index *pIndex, *pNext;
sqlite3 *db;
if( pTable==0 ) return;
db = pTable->dbMem;
testcase( db==0 );
assert( !pTable || pTable->nRef>0 );
/* Do not delete the table until the reference count reaches zero. */
pTable->nRef--;
if( pTable->nRef>0 ){
return;
}
assert( pTable->nRef==0 );
if( !pTable ) return;
if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return;
/* Delete all indices associated with this table
*/
/* Delete all indices associated with this table. */
for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
pNext = pIndex->pNext;
assert( pIndex->pSchema==pTable->pSchema );
sqlite3DeleteIndex(pIndex);
if( !db || db->pnBytesFreed==0 ){
char *zName = pIndex->zName;
TESTONLY ( Index *pOld = ) sqlite3HashInsert(
&pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0
);
assert( pOld==pIndex || pOld==0 );
}
freeIndex(db, pIndex);
}
/* Delete any foreign keys attached to this table. */
sqlite3FkDelete(pTable);
sqlite3FkDelete(db, pTable);
/* Delete the Table structure itself.
*/
sqliteResetColumnNames(pTable);
sqliteDeleteColumnNames(db, pTable);
sqlite3DbFree(db, pTable->zName);
sqlite3DbFree(db, pTable->zColAff);
sqlite3SelectDelete(db, pTable->pSelect);
#ifndef SQLITE_OMIT_CHECK
sqlite3ExprDelete(db, pTable->pCheck);
#endif
sqlite3VtabClear(pTable);
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3VtabClear(db, pTable);
#endif
sqlite3DbFree(db, pTable);
}
@@ -554,7 +534,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
pDb = &db->aDb[iDb];
p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName,
sqlite3Strlen30(zTabName),0);
sqlite3DeleteTable(p);
sqlite3DeleteTable(db, p);
db->flags |= SQLITE_InternChanges;
}
@@ -822,7 +802,6 @@ void sqlite3StartTable(
pTable->iPKey = -1;
pTable->pSchema = db->aDb[iDb].pSchema;
pTable->nRef = 1;
pTable->dbMem = 0;
assert( pParse->pNewTable==0 );
pParse->pNewTable = pTable;
@@ -1374,7 +1353,7 @@ static char *createTableStmt(sqlite3 *db, Table *p){
zEnd = "\n)";
}
n += 35 + 6*p->nCol;
zStmt = sqlite3Malloc( n );
zStmt = sqlite3DbMallocRaw(0, n);
if( zStmt==0 ){
db->mallocFailed = 1;
return 0;
@@ -1555,7 +1534,7 @@ void sqlite3EndTable(
p->aCol = pSelTab->aCol;
pSelTab->nCol = 0;
pSelTab->aCol = 0;
sqlite3DeleteTable(pSelTab);
sqlite3DeleteTable(db, pSelTab);
}
}
@@ -1799,7 +1778,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
pTable->aCol = pSelTab->aCol;
pSelTab->nCol = 0;
pSelTab->aCol = 0;
sqlite3DeleteTable(pSelTab);
sqlite3DeleteTable(db, pSelTab);
pTable->pSchema->flags |= DB_UnresetViews;
}else{
pTable->nCol = 0;
@@ -1824,7 +1803,9 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){
for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){
Table *pTab = sqliteHashData(i);
if( pTab->pSelect ){
sqliteResetColumnNames(pTab);
sqliteDeleteColumnNames(db, pTab);
pTab->aCol = 0;
pTab->nCol = 0;
}
}
DbClearProperty(db, idx, DB_UnresetViews);
@@ -2821,7 +2802,7 @@ Index *sqlite3CreateIndex(
/* Clean up before exiting */
exit_create_index:
if( pIndex ){
sqlite3_free(pIndex->zColAff);
sqlite3DbFree(db, pIndex->zColAff);
sqlite3DbFree(db, pIndex);
}
sqlite3ExprListDelete(db, pList);
@@ -3200,7 +3181,7 @@ void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
sqlite3DbFree(db, pItem->zName);
sqlite3DbFree(db, pItem->zAlias);
sqlite3DbFree(db, pItem->zIndex);
sqlite3DeleteTable(pItem->pTab);
sqlite3DeleteTable(db, pItem->pTab);
sqlite3SelectDelete(db, pItem->pSelect);
sqlite3ExprDelete(db, pItem->pOn);
sqlite3IdListDelete(db, pItem->pUsing);
+2 -3
View File
@@ -422,8 +422,7 @@ void sqlite3SchemaFree(void *p){
sqlite3HashInit(&pSchema->tblHash);
for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
Table *pTab = sqliteHashData(pElem);
assert( pTab->dbMem==0 );
sqlite3DeleteTable(pTab);
sqlite3DeleteTable(0, pTab);
}
sqlite3HashClear(&temp1);
sqlite3HashClear(&pSchema->fkeyHash);
@@ -440,7 +439,7 @@ Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
if( pBt ){
p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaFree);
}else{
p = (Schema *)sqlite3MallocZero(sizeof(Schema));
p = (Schema *)sqlite3DbMallocZero(0, sizeof(Schema));
}
if( !p ){
db->mallocFailed = 1;
+1 -1
View File
@@ -24,7 +24,7 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
Table *pTab;
assert( pItem && pSrc->nSrc==1 );
pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
sqlite3DeleteTable(pItem->pTab);
sqlite3DeleteTable(pParse->db, pItem->pTab);
pItem->pTab = pTab;
if( pTab ){
pTab->nRef++;
+19 -11
View File
@@ -55,6 +55,18 @@ char sqlite3ExprAffinity(Expr *pExpr){
return pExpr->affinity;
}
/*
** Set the explicit collating sequence for an expression to the
** collating sequence supplied in the second argument.
*/
Expr *sqlite3ExprSetColl(Expr *pExpr, CollSeq *pColl){
if( pExpr && pColl ){
pExpr->pColl = pColl;
pExpr->flags |= EP_ExpCollate;
}
return pExpr;
}
/*
** Set the collating sequence for expression pExpr to be the collating
** sequence named by pToken. Return a pointer to the revised expression.
@@ -62,18 +74,13 @@ char sqlite3ExprAffinity(Expr *pExpr){
** flag. An explicit collating sequence will override implicit
** collating sequences.
*/
Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pCollName){
Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){
char *zColl = 0; /* Dequoted name of collation sequence */
CollSeq *pColl;
sqlite3 *db = pParse->db;
zColl = sqlite3NameFromToken(db, pCollName);
if( pExpr && zColl ){
pColl = sqlite3LocateCollSeq(pParse, zColl);
if( pColl ){
pExpr->pColl = pColl;
pExpr->flags |= EP_ExpCollate;
}
}
pColl = sqlite3LocateCollSeq(pParse, zColl);
sqlite3ExprSetColl(pExpr, pColl);
sqlite3DbFree(db, zColl);
return pExpr;
}
@@ -547,18 +554,19 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
}else if( z[0]=='?' ){
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
** use it as the variable number */
int i = atoi((char*)&z[1]);
i64 i;
int bOk = sqlite3Atoi64(&z[1], &i);
pExpr->iColumn = (ynVar)i;
testcase( i==0 );
testcase( i==1 );
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] );
if( i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
}
if( i>pParse->nVar ){
pParse->nVar = i;
pParse->nVar = (int)i;
}
}else{
/* Wildcards like ":aaa", "$aaa" or "@aaa". Reuse the same variable
+22 -23
View File
@@ -500,7 +500,8 @@ static void fkScanChildren(
if( pIdx ){
Column *pCol;
iCol = pIdx->aiColumn[i];
pCol = &pIdx->pTable->aCol[iCol];
pCol = &pTab->aCol[iCol];
if( pTab->iPKey==iCol ) iCol = -1;
pLeft->iTable = regData+iCol+1;
pLeft->affinity = pCol->affinity;
pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl);
@@ -1061,11 +1062,7 @@ static Trigger *fkActionTrigger(
pWhere = 0;
}
/* In the current implementation, pTab->dbMem==0 for all tables except
** for temporary tables used to describe subqueries. And temporary
** tables do not have foreign key constraints. Hence, pTab->dbMem
** should always be 0 there.
*/
/* Disable lookaside memory allocation */
enableLookaside = db->lookaside.bEnabled;
db->lookaside.bEnabled = 0;
@@ -1155,37 +1152,39 @@ void sqlite3FkActions(
** table pTab. Remove the deleted foreign keys from the Schema.fkeyHash
** hash table.
*/
void sqlite3FkDelete(Table *pTab){
void sqlite3FkDelete(sqlite3 *db, Table *pTab){
FKey *pFKey; /* Iterator variable */
FKey *pNext; /* Copy of pFKey->pNextFrom */
for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){
/* Remove the FK from the fkeyHash hash table. */
if( pFKey->pPrevTo ){
pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
}else{
void *data = (void *)pFKey->pNextTo;
const char *z = (data ? pFKey->pNextTo->zTo : pFKey->zTo);
sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, sqlite3Strlen30(z), data);
if( !db || db->pnBytesFreed==0 ){
if( pFKey->pPrevTo ){
pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
}else{
void *p = (void *)pFKey->pNextTo;
const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo);
sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, sqlite3Strlen30(z), p);
}
if( pFKey->pNextTo ){
pFKey->pNextTo->pPrevTo = pFKey->pPrevTo;
}
}
if( pFKey->pNextTo ){
pFKey->pNextTo->pPrevTo = pFKey->pPrevTo;
}
/* Delete any triggers created to implement actions for this FK. */
#ifndef SQLITE_OMIT_TRIGGER
fkTriggerDelete(pTab->dbMem, pFKey->apTrigger[0]);
fkTriggerDelete(pTab->dbMem, pFKey->apTrigger[1]);
#endif
/* EV: R-30323-21917 Each foreign key constraint in SQLite is
** classified as either immediate or deferred.
*/
assert( pFKey->isDeferred==0 || pFKey->isDeferred==1 );
/* Delete any triggers created to implement actions for this FK. */
#ifndef SQLITE_OMIT_TRIGGER
fkTriggerDelete(db, pFKey->apTrigger[0]);
fkTriggerDelete(db, pFKey->apTrigger[1]);
#endif
pNext = pFKey->pNextFrom;
sqlite3DbFree(pTab->dbMem, pFKey);
sqlite3DbFree(db, pFKey);
}
}
#endif /* ifndef SQLITE_OMIT_FOREIGN_KEY */
+10 -7
View File
@@ -788,8 +788,10 @@ static void compileoptionusedFunc(
const char *zOptName;
assert( argc==1 );
UNUSED_PARAMETER(argc);
/* IMP: R-xxxx This function is an SQL wrapper around the
** sqlite3_compileoption_used() C interface. */
/* IMP: R-39564-36305 The sqlite_compileoption_used() SQL
** function is a wrapper around the sqlite3_compileoption_used() C/C++
** function.
*/
if( (zOptName = (const char*)sqlite3_value_text(argv[0]))!=0 ){
sqlite3_result_int(context, sqlite3_compileoption_used(zOptName));
}
@@ -810,8 +812,9 @@ static void compileoptiongetFunc(
int n;
assert( argc==1 );
UNUSED_PARAMETER(argc);
/* IMP: R-xxxx This function is an SQL wrapper around the
** sqlite3_compileoption_get() C interface. */
/* IMP: R-04922-24076 The sqlite_compileoption_get() SQL function
** is a wrapper around the sqlite3_compileoption_get() C/C++ function.
*/
n = sqlite3_value_int(argv[0]);
sqlite3_result_text(context, sqlite3_compileoption_get(n), -1, SQLITE_STATIC);
}
@@ -1010,14 +1013,14 @@ static void replaceFunc(
testcase( nOut-2==db->aLimit[SQLITE_LIMIT_LENGTH] );
if( nOut-1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
sqlite3_result_error_toobig(context);
sqlite3DbFree(db, zOut);
sqlite3_free(zOut);
return;
}
zOld = zOut;
zOut = sqlite3_realloc(zOut, (int)nOut);
if( zOut==0 ){
sqlite3_result_error_nomem(context);
sqlite3DbFree(db, zOld);
sqlite3_free(zOld);
return;
}
memcpy(&zOut[j], zRep, nRep);
@@ -1378,7 +1381,7 @@ static void groupConcatStep(
if( pAccum ){
sqlite3 *db = sqlite3_context_db_handle(context);
int firstTerm = pAccum->useMalloc==0;
pAccum->useMalloc = 1;
pAccum->useMalloc = 2;
pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
if( !firstTerm ){
if( argc==2 ){
+3 -2
View File
@@ -67,7 +67,7 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
int n;
Table *pTab = pIdx->pTable;
sqlite3 *db = sqlite3VdbeDb(v);
pIdx->zColAff = (char *)sqlite3Malloc(pIdx->nColumn+2);
pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+2);
if( !pIdx->zColAff ){
db->mallocFailed = 1;
return 0;
@@ -109,7 +109,7 @@ void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
int i;
sqlite3 *db = sqlite3VdbeDb(v);
zColAff = (char *)sqlite3Malloc(pTab->nCol+1);
zColAff = (char *)sqlite3DbMallocRaw(0, pTab->nCol+1);
if( !zColAff ){
db->mallocFailed = 1;
return;
@@ -1220,6 +1220,7 @@ void sqlite3GenerateConstraintChecks(
if( onError==OE_Ignore ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
}else{
if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */
sqlite3HaltConstraint(pParse, onError, 0, 0);
}
sqlite3VdbeResolveLabel(v, allOk);
+2 -6
View File
@@ -376,13 +376,11 @@ static int sqlite3LoadExtension(
handle = sqlite3OsDlOpen(pVfs, zFile);
if( handle==0 ){
if( pzErrMsg ){
zErrmsg = sqlite3StackAllocZero(db, nMsg);
*pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
if( zErrmsg ){
sqlite3_snprintf(nMsg, zErrmsg,
"unable to open shared library [%s]", zFile);
sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
*pzErrMsg = sqlite3DbStrDup(0, zErrmsg);
sqlite3StackFree(db, zErrmsg);
}
}
return SQLITE_ERROR;
@@ -391,13 +389,11 @@ static int sqlite3LoadExtension(
sqlite3OsDlSym(pVfs, handle, zProc);
if( xInit==0 ){
if( pzErrMsg ){
zErrmsg = sqlite3StackAllocZero(db, nMsg);
*pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
if( zErrmsg ){
sqlite3_snprintf(nMsg, zErrmsg,
"no entry point [%s] in shared library [%s]", zProc,zFile);
sqlite3OsDlError(pVfs, nMsg-1, zErrmsg);
*pzErrMsg = sqlite3DbStrDup(0, zErrmsg);
sqlite3StackFree(db, zErrmsg);
}
sqlite3OsDlClose(pVfs, handle);
}
+1 -10
View File
@@ -1308,16 +1308,7 @@ int sqlite3Checkpoint(sqlite3 *db, int iDb){
for(i=0; i<db->nDb && rc==SQLITE_OK; i++){
if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
if( sqlite3BtreeIsInReadTrans(pBt) ){
rc = SQLITE_LOCKED;
}else{
sqlite3BtreeEnter(pBt);
rc = sqlite3PagerCheckpoint(sqlite3BtreePager(pBt));
sqlite3BtreeLeave(pBt);
}
}
rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt);
}
}
+37 -18
View File
@@ -251,6 +251,7 @@ static int mallocWithAlarm(int n, void **pp){
if( p ){
nFull = sqlite3MallocSize(p);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
}
*pp = p;
return nFull;
@@ -368,12 +369,14 @@ void sqlite3ScratchFree(void *p){
|| p<sqlite3GlobalConfig.pScratch
|| p>=(void*)mem0.aScratchFree ){
assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
assert( sqlite3MemdebugNoType(p, ~MEMTYPE_SCRATCH) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
if( sqlite3GlobalConfig.bMemstat ){
int iSize = sqlite3MallocSize(p);
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
sqlite3GlobalConfig.m.xFree(p);
sqlite3_mutex_leave(mem0.mutex);
}else{
@@ -408,7 +411,7 @@ void sqlite3ScratchFree(void *p){
*/
#ifndef SQLITE_OMIT_LOOKASIDE
static int isLookaside(sqlite3 *db, void *p){
return db && p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
return p && p>=db->lookaside.pStart && p<db->lookaside.pEnd;
}
#else
#define isLookaside(A,B) 0
@@ -420,15 +423,17 @@ static int isLookaside(sqlite3 *db, void *p){
*/
int sqlite3MallocSize(void *p){
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
return sqlite3GlobalConfig.m.xSize(p);
}
int sqlite3DbMallocSize(sqlite3 *db, void *p){
assert( db==0 || sqlite3_mutex_held(db->mutex) );
if( isLookaside(db, p) ){
if( db && isLookaside(db, p) ){
return db->lookaside.sz;
}else{
assert( sqlite3MemdebugHasType(p,
db ? (MEMTYPE_DB|MEMTYPE_HEAP) : MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
return sqlite3GlobalConfig.m.xSize(p);
}
}
@@ -438,10 +443,12 @@ int sqlite3DbMallocSize(sqlite3 *db, void *p){
*/
void sqlite3_free(void *p){
if( p==0 ) return;
assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
sqlite3GlobalConfig.m.xFree(p);
sqlite3_mutex_leave(mem0.mutex);
}else{
@@ -455,16 +462,24 @@ void sqlite3_free(void *p){
*/
void sqlite3DbFree(sqlite3 *db, void *p){
assert( db==0 || sqlite3_mutex_held(db->mutex) );
if( isLookaside(db, p) ){
LookasideSlot *pBuf = (LookasideSlot*)p;
pBuf->pNext = db->lookaside.pFree;
db->lookaside.pFree = pBuf;
db->lookaside.nOut--;
}else{
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB|MEMTYPE_HEAP) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
sqlite3_free(p);
if( db ){
if( db->pnBytesFreed ){
*db->pnBytesFreed += sqlite3DbMallocSize(db, p);
return;
}
if( isLookaside(db, p) ){
LookasideSlot *pBuf = (LookasideSlot*)p;
pBuf->pNext = db->lookaside.pFree;
db->lookaside.pFree = pBuf;
db->lookaside.nOut--;
return;
}
}
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
sqlite3_free(p);
}
/*
@@ -496,6 +511,7 @@ void *sqlite3Realloc(void *pOld, int nBytes){
sqlite3MallocAlarm(nNew-nOld);
}
assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
if( pNew==0 && mem0.alarmCallback ){
sqlite3MallocAlarm(nBytes);
@@ -568,6 +584,7 @@ void *sqlite3DbMallocZero(sqlite3 *db, int n){
void *sqlite3DbMallocRaw(sqlite3 *db, int n){
void *p;
assert( db==0 || sqlite3_mutex_held(db->mutex) );
assert( db==0 || db->pnBytesFreed==0 );
#ifndef SQLITE_OMIT_LOOKASIDE
if( db ){
LookasideSlot *pBuf;
@@ -593,8 +610,8 @@ void *sqlite3DbMallocRaw(sqlite3 *db, int n){
if( !p && db ){
db->mallocFailed = 1;
}
sqlite3MemdebugSetType(p,
(db && db->lookaside.bEnabled) ? MEMTYPE_DB : MEMTYPE_HEAP);
sqlite3MemdebugSetType(p, MEMTYPE_DB |
((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
return p;
}
@@ -620,14 +637,16 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){
sqlite3DbFree(db, p);
}
}else{
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB|MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_DB) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_LOOKASIDE|MEMTYPE_HEAP) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
pNew = sqlite3_realloc(p, n);
if( !pNew ){
sqlite3MemdebugSetType(p, MEMTYPE_DB|MEMTYPE_HEAP);
db->mallocFailed = 1;
}
sqlite3MemdebugSetType(pNew,
db->lookaside.bEnabled ? MEMTYPE_DB : MEMTYPE_HEAP);
sqlite3MemdebugSetType(pNew, MEMTYPE_DB |
(db->lookaside.bEnabled ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
}
}
return pNew;
+24 -9
View File
@@ -378,7 +378,7 @@ void sqlite3MemSetDefault(void){
** Set the "type" of an allocation.
*/
void sqlite3MemdebugSetType(void *p, u8 eType){
if( p ){
if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
struct MemBlockHdr *pHdr;
pHdr = sqlite3MemsysGetHeader(p);
assert( pHdr->iForeGuard==FOREGUARD );
@@ -397,23 +397,38 @@ void sqlite3MemdebugSetType(void *p, u8 eType){
*/
int sqlite3MemdebugHasType(void *p, u8 eType){
int rc = 1;
if( p ){
if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
struct MemBlockHdr *pHdr;
pHdr = sqlite3MemsysGetHeader(p);
assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
assert( (pHdr->eType & (pHdr->eType-1))==0 ); /* Only one type bit set */
if( (pHdr->eType&eType)==0 ){
void **pBt;
pBt = (void**)pHdr;
pBt -= pHdr->nBacktraceSlots;
backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(stderr));
fprintf(stderr, "\n");
rc = 0;
}
}
return rc;
}
/*
** Return TRUE if the mask of type in eType matches no bits of the type of the
** allocation p. Also return true if p==NULL.
**
** This routine is designed for use within an assert() statement, to
** verify the type of an allocation. For example:
**
** assert( sqlite3MemdebugNoType(p, MEMTYPE_DB) );
*/
int sqlite3MemdebugNoType(void *p, u8 eType){
int rc = 1;
if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
struct MemBlockHdr *pHdr;
pHdr = sqlite3MemsysGetHeader(p);
assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
if( (pHdr->eType&eType)!=0 ){
rc = 0;
}
}
return rc;
}
/*
** Set the number of backtrace levels kept for each allocation.
+2
View File
@@ -235,6 +235,7 @@ static void pthreadMutexEnter(sqlite3_mutex *p){
*/
pthread_mutex_lock(&p->mutex);
#if SQLITE_MUTEX_NREF
assert( p->nRef>0 || p->owner==0 );
p->owner = pthread_self();
p->nRef++;
#endif
@@ -307,6 +308,7 @@ static void pthreadMutexLeave(sqlite3_mutex *p){
assert( pthreadMutexHeld(p) );
#if SQLITE_MUTEX_NREF
p->nRef--;
if( p->nRef==0 ) p->owner = 0;
#endif
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
+3 -1
View File
@@ -220,7 +220,7 @@ static sqlite3_mutex *winMutexAlloc(int iType){
*/
static void winMutexFree(sqlite3_mutex *p){
assert( p );
assert( p->nRef==0 );
assert( p->nRef==0 && p->owner==0 );
assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
DeleteCriticalSection(&p->mutex);
sqlite3_free(p);
@@ -244,6 +244,7 @@ static void winMutexEnter(sqlite3_mutex *p){
#endif
EnterCriticalSection(&p->mutex);
#ifdef SQLITE_DEBUG
assert( p->nRef>0 || p->owner==0 );
p->owner = tid;
p->nRef++;
if( p->trace ){
@@ -297,6 +298,7 @@ static void winMutexLeave(sqlite3_mutex *p){
assert( p->nRef>0 );
assert( p->owner==tid );
p->nRef--;
if( p->nRef==0 ) p->owner = 0;
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
#endif
LeaveCriticalSection(&p->mutex);
+1 -1
View File
@@ -255,7 +255,7 @@ void sqlite3ConnectionUnlocked(sqlite3 *db){
assert( aArg==aDyn || (aDyn==0 && aArg==aStatic) );
assert( nArg<=(int)ArraySize(aStatic) || aArg==aDyn );
if( (!aDyn && nArg==(int)ArraySize(aStatic))
|| (aDyn && nArg==(int)(sqlite3DbMallocSize(db, aDyn)/sizeof(void*)))
|| (aDyn && nArg==(int)(sqlite3MallocSize(aDyn)/sizeof(void*)))
){
/* The aArg[] array needs to grow. */
void **pNew = (void **)sqlite3Malloc(nArg*sizeof(void *)*2);
+75 -14
View File
@@ -210,6 +210,7 @@ struct unixFile {
int fileFlags; /* Miscellanous flags */
const char *zPath; /* Name of the file */
unixShm *pShm; /* Shared memory segment information */
int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
#if SQLITE_ENABLE_LOCKING_STYLE
int openFlags; /* The flags specified at open() */
#endif
@@ -2763,6 +2764,7 @@ static int unixWrite(
}
SimulateIOError(( wrote=(-1), amt=1 ));
SimulateDiskfullError(( wrote=0, amt=1 ));
if( amt>0 ){
if( wrote<0 ){
/* lastErrno set by seekAndWrite */
@@ -2772,6 +2774,7 @@ static int unixWrite(
return SQLITE_FULL;
}
}
return SQLITE_OK;
}
@@ -2973,12 +2976,23 @@ static int unixSync(sqlite3_file *id, int flags){
** Truncate an open file to a specified size
*/
static int unixTruncate(sqlite3_file *id, i64 nByte){
unixFile *pFile = (unixFile *)id;
int rc;
assert( id );
assert( pFile );
SimulateIOError( return SQLITE_IOERR_TRUNCATE );
rc = ftruncate(((unixFile*)id)->h, (off_t)nByte);
/* If the user has configured a chunk-size for this file, truncate the
** file so that it consists of an integer number of chunks (i.e. the
** actual file size after the operation may be larger than the requested
** size).
*/
if( pFile->szChunk ){
nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
}
rc = ftruncate(pFile->h, (off_t)nByte);
if( rc ){
((unixFile*)id)->lastErrno = errno;
pFile->lastErrno = errno;
return SQLITE_IOERR_TRUNCATE;
}else{
#ifndef NDEBUG
@@ -2989,8 +3003,8 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
** when restoring a database using the backup API from a zero-length
** source.
*/
if( ((unixFile*)id)->inNormalWrite && nByte==0 ){
((unixFile*)id)->transCntrChng = 1;
if( pFile->inNormalWrite && nByte==0 ){
pFile->transCntrChng = 1;
}
#endif
@@ -3033,6 +3047,54 @@ static int unixFileSize(sqlite3_file *id, i64 *pSize){
static int proxyFileControl(sqlite3_file*,int,void*);
#endif
/*
** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
** file-control operation.
**
** If the user has configured a chunk-size for this file, it could be
** that the file needs to be extended at this point. Otherwise, the
** SQLITE_FCNTL_SIZE_HINT operation is a no-op for Unix.
*/
static int fcntlSizeHint(unixFile *pFile, i64 nByte){
if( pFile->szChunk ){
i64 nSize; /* Required file size */
struct stat buf; /* Used to hold return values of fstat() */
if( fstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
if( nSize>(i64)buf.st_size ){
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
if( posix_fallocate(pFile->h, buf.st_size, nSize-buf.st_size) ){
return SQLITE_IOERR_WRITE;
}
#else
/* If the OS does not have posix_fallocate(), fake it. First use
** ftruncate() to set the file size, then write a single byte to
** the last byte in each block within the extended region. This
** is the same technique used by glibc to implement posix_fallocate()
** on systems that do not have a real fallocate() system call.
*/
int nBlk = buf.st_blksize; /* File-system block size */
i64 iWrite; /* Next offset to write to */
int nWrite; /* Return value from seekAndWrite() */
if( ftruncate(pFile->h, nSize) ){
pFile->lastErrno = errno;
return SQLITE_IOERR_TRUNCATE;
}
iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
do {
nWrite = seekAndWrite(pFile, iWrite, "", 1);
iWrite += nBlk;
} while( nWrite==1 && iWrite<nSize );
if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
#endif
}
}
return SQLITE_OK;
}
/*
** Information and control of an open file handle.
@@ -3047,14 +3109,13 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
*(int*)pArg = ((unixFile*)id)->lastErrno;
return SQLITE_OK;
}
case SQLITE_FCNTL_SIZE_HINT: {
#if 0 /* No performance advantage seen on Linux */
sqlite3_int64 szFile = *(sqlite3_int64*)pArg;
unixFile *pFile = (unixFile*)id;
ftruncate(pFile->h, szFile);
#endif
case SQLITE_FCNTL_CHUNK_SIZE: {
((unixFile*)id)->szChunk = *(int *)pArg;
return SQLITE_OK;
}
case SQLITE_FCNTL_SIZE_HINT: {
return fcntlSizeHint((unixFile *)id, *(i64 *)pArg);
}
#ifndef NDEBUG
/* The pager calls this method to signal that it has done
** a rollback and that the database is therefore unchanged and
@@ -5918,7 +5979,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
sqlite3_free(pCtx->conchFile);
}
sqlite3_free(pCtx->lockProxyPath);
sqlite3DbFree(0, pCtx->lockProxyPath);
sqlite3_free(pCtx->conchFilePath);
sqlite3_free(pCtx);
}
@@ -6109,9 +6170,9 @@ static int proxyClose(sqlite3_file *id) {
if( rc ) return rc;
sqlite3_free(conchFile);
}
sqlite3_free(pCtx->lockProxyPath);
sqlite3DbFree(0, pCtx->lockProxyPath);
sqlite3_free(pCtx->conchFilePath);
sqlite3_free(pCtx->dbPath);
sqlite3DbFree(0, pCtx->dbPath);
/* restore the original locking context and pMethod then close it */
pFile->lockingContext = pCtx->oldLockingContext;
pFile->pMethod = pCtx->pOldMethod;
+95 -65
View File
@@ -108,6 +108,7 @@ struct winFile {
DWORD sectorSize; /* Sector size of the device file is on */
winShm *pShm; /* Instance of shared memory on this file */
const char *zPath; /* Full pathname of this file */
int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
#if SQLITE_OS_WINCE
WCHAR *zDeleteOnClose; /* Name of file to delete when closing */
HANDLE hMutex; /* Mutex used to control access to shared lock */
@@ -620,6 +621,42 @@ static BOOL winceLockFileEx(
** by the sqlite3_io_methods object.
******************************************************************************/
/*
** Some microsoft compilers lack this definition.
*/
#ifndef INVALID_SET_FILE_POINTER
# define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif
/*
** Move the current position of the file handle passed as the first
** argument to offset iOffset within the file. If successful, return 0.
** Otherwise, set pFile->lastErrno and return non-zero.
*/
static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
LONG upperBits; /* Most sig. 32 bits of new offset */
LONG lowerBits; /* Least sig. 32 bits of new offset */
DWORD dwRet; /* Value returned by SetFilePointer() */
upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
lowerBits = (LONG)(iOffset & 0xffffffff);
/* API oddity: If successful, SetFilePointer() returns a dword
** containing the lower 32-bits of the new file-offset. Or, if it fails,
** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
** whether an error has actually occured, it is also necessary to call
** GetLastError().
*/
dwRet = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
if( (dwRet==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR) ){
pFile->lastErrno = GetLastError();
return 1;
}
return 0;
}
/*
** Close a file.
**
@@ -662,13 +699,6 @@ static int winClose(sqlite3_file *id){
return rc ? SQLITE_OK : SQLITE_IOERR;
}
/*
** Some microsoft compilers lack this definition.
*/
#ifndef INVALID_SET_FILE_POINTER
# define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif
/*
** Read data from a file into a buffer. Return SQLITE_OK if all
** bytes were read successfully and SQLITE_IOERR if anything goes
@@ -680,32 +710,27 @@ static int winRead(
int amt, /* Number of bytes to read */
sqlite3_int64 offset /* Begin reading at this offset */
){
LONG upperBits = (LONG)((offset>>32) & 0x7fffffff);
LONG lowerBits = (LONG)(offset & 0xffffffff);
DWORD rc;
winFile *pFile = (winFile*)id;
DWORD error;
DWORD got;
winFile *pFile = (winFile*)id; /* file handle */
DWORD nRead; /* Number of bytes actually read from file */
assert( id!=0 );
SimulateIOError(return SQLITE_IOERR_READ);
OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){
pFile->lastErrno = error;
if( seekWinFile(pFile, offset) ){
return SQLITE_FULL;
}
if( !ReadFile(pFile->h, pBuf, amt, &got, 0) ){
if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
pFile->lastErrno = GetLastError();
return SQLITE_IOERR_READ;
}
if( got==(DWORD)amt ){
return SQLITE_OK;
}else{
if( nRead<(DWORD)amt ){
/* Unread parts of the buffer must be zero-filled */
memset(&((char*)pBuf)[got], 0, amt-got);
memset(&((char*)pBuf)[nRead], 0, amt-nRead);
return SQLITE_IOERR_SHORT_READ;
}
return SQLITE_OK;
}
/*
@@ -713,47 +738,42 @@ static int winRead(
** or some other error code on failure.
*/
static int winWrite(
sqlite3_file *id, /* File to write into */
const void *pBuf, /* The bytes to be written */
int amt, /* Number of bytes to write */
sqlite3_int64 offset /* Offset into the file to begin writing at */
sqlite3_file *id, /* File to write into */
const void *pBuf, /* The bytes to be written */
int amt, /* Number of bytes to write */
sqlite3_int64 offset /* Offset into the file to begin writing at */
){
LONG upperBits = (LONG)((offset>>32) & 0x7fffffff);
LONG lowerBits = (LONG)(offset & 0xffffffff);
DWORD rc;
winFile *pFile = (winFile*)id;
DWORD error;
DWORD wrote = 0;
int rc; /* True if error has occured, else false */
winFile *pFile = (winFile*)id; /* File handle */
assert( id!=0 );
assert( amt>0 );
assert( pFile );
SimulateIOError(return SQLITE_IOERR_WRITE);
SimulateDiskfullError(return SQLITE_FULL);
OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));
rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){
pFile->lastErrno = error;
if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){
return SQLITE_FULL;
}else{
return SQLITE_IOERR_WRITE;
rc = seekWinFile(pFile, offset);
if( rc==0 ){
u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
int nRem = amt; /* Number of bytes yet to be written */
DWORD nWrite; /* Bytes written by each WriteFile() call */
while( nRem>0 && WriteFile(pFile->h, aRem, nRem, &nWrite, 0) && nWrite>0 ){
aRem += nWrite;
nRem -= nWrite;
}
if( nRem>0 ){
pFile->lastErrno = GetLastError();
rc = 1;
}
}
assert( amt>0 );
while(
amt>0
&& (rc = WriteFile(pFile->h, pBuf, amt, &wrote, 0))!=0
&& wrote>0
){
amt -= wrote;
pBuf = &((char*)pBuf)[wrote];
}
if( !rc || amt>(int)wrote ){
pFile->lastErrno = GetLastError();
if( rc ){
if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){
return SQLITE_FULL;
}else{
return SQLITE_IOERR_WRITE;
}
return SQLITE_IOERR_WRITE;
}
return SQLITE_OK;
}
@@ -762,26 +782,32 @@ static int winWrite(
** Truncate an open file to a specified size
*/
static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
LONG upperBits = (LONG)((nByte>>32) & 0x7fffffff);
LONG lowerBits = (LONG)(nByte & 0xffffffff);
DWORD dwRet;
winFile *pFile = (winFile*)id;
DWORD error;
int rc = SQLITE_OK;
winFile *pFile = (winFile*)id; /* File handle object */
int rc = SQLITE_OK; /* Return code for this function */
assert( pFile );
assert( id!=0 );
OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte));
SimulateIOError(return SQLITE_IOERR_TRUNCATE);
dwRet = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
if( dwRet==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){
pFile->lastErrno = error;
/* If the user has configured a chunk-size for this file, truncate the
** file so that it consists of an integer number of chunks (i.e. the
** actual file size after the operation may be larger than the requested
** size).
*/
if( pFile->szChunk ){
nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
}
/* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
if( seekWinFile(pFile, nByte) ){
rc = SQLITE_IOERR_TRUNCATE;
/* SetEndOfFile will fail if nByte is negative */
}else if( !SetEndOfFile(pFile->h) ){
}else if( 0==SetEndOfFile(pFile->h) ){
pFile->lastErrno = GetLastError();
rc = SQLITE_IOERR_TRUNCATE;
}
OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc==SQLITE_OK ? "ok" : "failed"));
OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok"));
return rc;
}
@@ -1146,6 +1172,10 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
*(int*)pArg = (int)((winFile*)id)->lastErrno;
return SQLITE_OK;
}
case SQLITE_FCNTL_CHUNK_SIZE: {
((winFile*)id)->szChunk = *(int *)pArg;
return SQLITE_OK;
}
case SQLITE_FCNTL_SIZE_HINT: {
sqlite3_int64 sz = *(sqlite3_int64*)pArg;
SimulateIOErrorBenign(1);
+1498 -975
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -99,7 +99,7 @@ int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
/* Functions used to configure a Pager object. */
void sqlite3PagerSetBusyhandler(Pager*, int(*)(void *), void *);
int sqlite3PagerSetPagesize(Pager*, u16*, int);
int sqlite3PagerSetPagesize(Pager*, u32*, int);
int sqlite3PagerMaxPageCount(Pager*, int);
void sqlite3PagerSetCachesize(Pager*, int);
void sqlite3PagerSetSafetyLevel(Pager*,int,int);
@@ -126,9 +126,10 @@ void *sqlite3PagerGetData(DbPage *);
void *sqlite3PagerGetExtra(DbPage *);
/* Functions used to manage pager transactions and savepoints. */
int sqlite3PagerPagecount(Pager*, int*);
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 sqlite3PagerCommitPhaseTwo(Pager*);
int sqlite3PagerRollback(Pager*);
+3 -3
View File
@@ -780,7 +780,7 @@ expr(A) ::= VARIABLE(X). {
spanSet(&A, &X, &X);
}
expr(A) ::= expr(E) COLLATE ids(C). {
A.pExpr = sqlite3ExprSetColl(pParse, E.pExpr, &C);
A.pExpr = sqlite3ExprSetCollByToken(pParse, E.pExpr, &C);
A.zStart = E.zStart;
A.zEnd = &C.z[C.n];
}
@@ -1108,7 +1108,7 @@ idxlist(A) ::= idxlist(X) COMMA nm(Y) collate(C) sortorder(Z). {
Expr *p = 0;
if( C.n>0 ){
p = sqlite3Expr(pParse->db, TK_COLUMN, 0);
sqlite3ExprSetColl(pParse, p, &C);
sqlite3ExprSetCollByToken(pParse, p, &C);
}
A = sqlite3ExprListAppend(pParse,X, p);
sqlite3ExprListSetName(pParse,A,&Y,1);
@@ -1119,7 +1119,7 @@ idxlist(A) ::= nm(Y) collate(C) sortorder(Z). {
Expr *p = 0;
if( C.n>0 ){
p = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
sqlite3ExprSetColl(pParse, p, &C);
sqlite3ExprSetCollByToken(pParse, p, &C);
}
A = sqlite3ExprListAppend(pParse,0, p);
sqlite3ExprListSetName(pParse, A, &Y, 1);
+21 -2
View File
@@ -152,11 +152,11 @@ void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
static void *pcache1Alloc(int nByte){
void *p;
assert( sqlite3_mutex_held(pcache1.mutex) );
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
if( nByte<=pcache1.szSlot && pcache1.pFree ){
assert( pcache1.isInit );
p = (PgHdr1 *)pcache1.pFree;
pcache1.pFree = pcache1.pFree->pNext;
sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
}else{
@@ -200,6 +200,25 @@ static void pcache1Free(void *p){
}
}
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
/*
** Return the size of a pache allocation
*/
static int pcache1MemSize(void *p){
assert( sqlite3_mutex_held(pcache1.mutex) );
if( p>=pcache1.pStart && p<pcache1.pEnd ){
return pcache1.szSlot;
}else{
int iSize;
assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
iSize = sqlite3MallocSize(p);
sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
return iSize;
}
}
#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
/*
** Allocate a new page object initially associated with cache pCache.
*/
@@ -748,7 +767,7 @@ int sqlite3PcacheReleaseMemory(int nReq){
PgHdr1 *p;
pcache1EnterMutex();
while( (nReq<0 || nFree<nReq) && (p=pcache1.pLruTail) ){
nFree += sqlite3MallocSize(PGHDR1_TO_PAGE(p));
nFree += pcache1MemSize(PGHDR1_TO_PAGE(p));
pcache1PinPage(p);
pcache1RemoveFromHash(p);
pcache1FreePage(p);
+1 -1
View File
@@ -765,7 +765,7 @@ void sqlite3Pragma(
}
sqlite3_free(sqlite3_temp_directory);
if( zRight[0] ){
sqlite3_temp_directory = sqlite3DbStrDup(0, zRight);
sqlite3_temp_directory = sqlite3_mprintf("%s", zRight);
}else{
sqlite3_temp_directory = 0;
}
-1
View File
@@ -670,7 +670,6 @@ static int sqlite3Prepare(
while( pParse->pTriggerPrg ){
TriggerPrg *pT = pParse->pTriggerPrg;
pParse->pTriggerPrg = pT->pNext;
sqlite3VdbeProgramDelete(db, pT->pProgram, 0);
sqlite3DbFree(db, pT);
}
+16 -3
View File
@@ -772,7 +772,11 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
}else{
p->nAlloc = (int)szNew;
}
zNew = sqlite3DbMallocRaw(p->db, p->nAlloc );
if( p->useMalloc==1 ){
zNew = sqlite3DbMallocRaw(p->db, p->nAlloc );
}else{
zNew = sqlite3_malloc(p->nAlloc);
}
if( zNew ){
memcpy(zNew, p->zText, p->nChar);
sqlite3StrAccumReset(p);
@@ -797,7 +801,11 @@ char *sqlite3StrAccumFinish(StrAccum *p){
if( p->zText ){
p->zText[p->nChar] = 0;
if( p->useMalloc && p->zText==p->zBase ){
p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
if( p->useMalloc==1 ){
p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
}else{
p->zText = sqlite3_malloc(p->nChar+1);
}
if( p->zText ){
memcpy(p->zText, p->zBase, p->nChar+1);
}else{
@@ -813,7 +821,11 @@ char *sqlite3StrAccumFinish(StrAccum *p){
*/
void sqlite3StrAccumReset(StrAccum *p){
if( p->zText!=p->zBase ){
sqlite3DbFree(p->db, p->zText);
if( p->useMalloc==1 ){
sqlite3DbFree(p->db, p->zText);
}else{
sqlite3_free(p->zText);
}
}
p->zText = 0;
}
@@ -895,6 +907,7 @@ char *sqlite3_vmprintf(const char *zFormat, va_list ap){
if( sqlite3_initialize() ) return 0;
#endif
sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
acc.useMalloc = 2;
sqlite3VXPrintf(&acc, 0, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
return z;
+13 -14
View File
@@ -1298,16 +1298,15 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
return 0;
}
/* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
** is disabled, so we might as well hard-code pTab->dbMem to NULL. */
** is disabled */
assert( db->lookaside.bEnabled==0 );
pTab->dbMem = 0;
pTab->nRef = 1;
pTab->zName = 0;
selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
pTab->iPKey = -1;
if( db->mallocFailed ){
sqlite3DeleteTable(pTab);
sqlite3DeleteTable(db, pTab);
return 0;
}
return pTab;
@@ -1799,7 +1798,7 @@ multi_select_end:
** regReturn is the number of the register holding the subroutine
** return address.
**
** If regPrev>0 then it is a the first register in a vector that
** If regPrev>0 then it is the first register in a vector that
** records the previous output. mem[regPrev] is a flag that is false
** if there has been no previous output. If regPrev>0 then code is
** generated to suppress duplicates. pKeyInfo is used for comparing
@@ -2496,12 +2495,13 @@ static void substSelect(
** (2) The subquery is not an aggregate or the outer query is not a join.
**
** (3) The subquery is not the right operand of a left outer join
** (Originally ticket #306. Strenghtened by ticket #3300)
** (Originally ticket #306. Strengthened by ticket #3300)
**
** (4) The subquery is not DISTINCT or the outer query is not a join.
** (4) The subquery is not DISTINCT.
**
** (5) The subquery is not DISTINCT or the outer query does not use
** aggregates.
** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT
** sub-queries that were excluded from this optimization. Restriction
** (4) has since been expanded to exclude all DISTINCT subqueries.
**
** (6) The subquery does not use aggregates or the outer query is not
** DISTINCT.
@@ -2521,9 +2521,9 @@ static void substSelect(
** (**) Not implemented. Subsumed into restriction (3). Was previously
** a separate restriction deriving from ticket #350.
**
** (13) The subquery and outer query do not both use LIMIT
** (13) The subquery and outer query do not both use LIMIT.
**
** (14) The subquery does not use OFFSET
** (14) The subquery does not use OFFSET.
**
** (15) The outer query is not part of a compound select or the
** subquery does not have a LIMIT clause.
@@ -2614,9 +2614,9 @@ static int flattenSubquery(
return 0; /* Restriction (15) */
}
if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
if( ((pSub->selFlags & SF_Distinct)!=0 || pSub->pLimit)
&& (pSrc->nSrc>1 || isAgg) ){ /* Restrictions (4)(5)(8)(9) */
return 0;
if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (5) */
if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){
return 0; /* Restrictions (8)(9) */
}
if( (p->selFlags & SF_Distinct)!=0 && subqueryIsAgg ){
return 0; /* Restriction (6) */
@@ -3096,7 +3096,6 @@ static int selectExpander(Walker *pWalker, Select *p){
sqlite3WalkSelect(pWalker, pSel);
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ) return WRC_Abort;
pTab->dbMem = db->lookaside.bEnabled ? db : 0;
pTab->nRef = 1;
pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
while( pSel->pPrior ){ pSel = pSel->pPrior; }
+108 -10
View File
@@ -398,6 +398,7 @@ struct previous_mode_data {
struct callback_data {
sqlite3 *db; /* The database */
int echoOn; /* True to echo input commands */
int statsOn; /* True to display memory stats before each finalize */
int cnt; /* Number of records displayed so far */
FILE *out; /* Write results here */
int mode; /* An output mode setting */
@@ -961,6 +962,86 @@ static char *save_err_msg(
return zErrMsg;
}
/*
** Display memory stats.
*/
static int display_stats(
sqlite3 *db, /* Database to query */
struct callback_data *pArg, /* Pointer to struct callback_data */
int bReset /* True to reset the stats */
){
int iCur;
int iHiwtr;
if( pArg && pArg->out ){
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Memory Used: %d (max %d) bytes\n", iCur, iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_MALLOC_COUNT, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Number of Allocations: %d (max %d)\n", iCur, iHiwtr);
/*
** Not currently used by the CLI.
** iHiwtr = iCur = -1;
** sqlite3_status(SQLITE_STATUS_PAGECACHE_USED, &iCur, &iHiwtr, bReset);
** fprintf(pArg->out, "Number of Pcache Pages Used: %d (max %d) pages\n", iCur, iHiwtr);
*/
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Number of Pcache Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr);
/*
** Not currently used by the CLI.
** iHiwtr = iCur = -1;
** sqlite3_status(SQLITE_STATUS_SCRATCH_USED, &iCur, &iHiwtr, bReset);
** fprintf(pArg->out, "Number of Scratch Allocations Used: %d (max %d)\n", iCur, iHiwtr);
*/
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_SCRATCH_OVERFLOW, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Number of Scratch Overflow Bytes: %d (max %d) bytes\n", iCur, iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_MALLOC_SIZE, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Largest Allocation: %d bytes\n", iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_PAGECACHE_SIZE, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Largest Pcache Allocation: %d bytes\n", iHiwtr);
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_SCRATCH_SIZE, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Largest Scratch Allocation: %d bytes\n", iHiwtr);
#ifdef YYTRACKMAXSTACKDEPTH
iHiwtr = iCur = -1;
sqlite3_status(SQLITE_STATUS_PARSER_STACK, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Deepest Parser Stack: %d (max %d)\n", iCur, iHiwtr);
#endif
}
if( pArg && pArg->out && db ){
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_LOOKASIDE_USED, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Lookaside Slots Used: %d (max %d)\n", iCur, iHiwtr);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_CACHE_USED, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Pager Heap Usage: %d bytes\n", iCur);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_SCHEMA_USED, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Schema Heap Usage: %d bytes\n", iCur);
iHiwtr = iCur = -1;
sqlite3_db_status(db, SQLITE_DBSTATUS_STMT_USED, &iCur, &iHiwtr, bReset);
fprintf(pArg->out, "Statement Heap/Lookaside Usage: %d bytes\n", iCur);
}
if( pArg && pArg->out && db && pArg->pStmt ){
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_FULLSCAN_STEP, bReset);
fprintf(pArg->out, "Fullscan Steps: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
fprintf(pArg->out, "Sort Operations: %d\n", iCur);
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX, bReset);
fprintf(pArg->out, "Autoindex Inserts: %d\n", iCur);
}
return 0;
}
/*
** Execute a statement or set of statements. Print
** any result rows/columns depending on the current mode
@@ -1000,10 +1081,16 @@ static int shell_exec(
continue;
}
/* save off the prepared statment handle and reset row count */
if( pArg ){
pArg->pStmt = pStmt;
pArg->cnt = 0;
}
/* echo the sql statement if echo on */
if( pArg->echoOn ){
if( pArg && pArg->echoOn ){
const char *zStmtSql = sqlite3_sql(pStmt);
fprintf(pArg->out,"%s\n", zStmtSql ? zStmtSql : zSql);
fprintf(pArg->out, "%s\n", zStmtSql ? zStmtSql : zSql);
}
/* perform the first step. this will tell us if we
@@ -1029,11 +1116,6 @@ static int shell_exec(
for(i=0; i<nCol; i++){
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
}
/* save off the prepared statment handle and reset row count */
if( pArg ){
pArg->pStmt = pStmt;
pArg->cnt = 0;
}
do{
/* extract the data and data types */
for(i=0; i<nCol; i++){
@@ -1056,9 +1138,6 @@ static int shell_exec(
}
} while( SQLITE_ROW == rc );
sqlite3_free(pData);
if( pArg ){
pArg->pStmt = NULL;
}
}
}else{
do{
@@ -1067,6 +1146,11 @@ static int shell_exec(
}
}
/* print usage stats if stats on */
if( pArg && pArg->statsOn ){
display_stats(db, pArg, 0);
}
/* Finalize the statement just executed. If this fails, save a
** copy of the error message. Otherwise, set zSql to point to the
** next statement to execute. */
@@ -1077,6 +1161,11 @@ static int shell_exec(
}else if( pzErrMsg ){
*pzErrMsg = save_err_msg(db);
}
/* clear saved stmt handle */
if( pArg ){
pArg->pStmt = NULL;
}
}
} /* end while */
@@ -1256,6 +1345,7 @@ static char zHelp[] =
" LIKE pattern TABLE.\n"
".separator STRING Change separator used by output mode and .import\n"
".show Show the current values for various settings\n"
".stats ON|OFF Turn stats on or off\n"
".tables ?TABLE? List names of tables\n"
" If TABLE specified, only list tables matching\n"
" LIKE pattern TABLE.\n"
@@ -2001,6 +2091,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
fprintf(p->out,"%9.9s: ", "separator");
output_c_string(p->out, p->separator);
fprintf(p->out, "\n");
fprintf(p->out,"%9.9s: %s\n","stats", p->statsOn ? "on" : "off");
fprintf(p->out,"%9.9s: ","width");
for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) {
fprintf(p->out,"%d ",p->colWidth[i]);
@@ -2008,6 +2099,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
fprintf(p->out,"\n");
}else
if( c=='s' && strncmp(azArg[0], "stats", n)==0 && nArg>1 && nArg<3 ){
p->statsOn = booleanValue(azArg[1]);
}else
if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 && nArg<3 ){
char **azResult;
int nRow;
@@ -2391,6 +2486,7 @@ static const char zOptions[] =
" -line set output mode to 'line'\n"
" -list set output mode to 'list'\n"
" -separator 'x' set output field separator (|)\n"
" -stats print memory stats before each finalize\n"
" -nullvalue 'text' set text string for NULL values\n"
" -version show SQLite version\n"
;
@@ -2555,6 +2651,8 @@ int main(int argc, char **argv){
data.showHeader = 0;
}else if( strcmp(z,"-echo")==0 ){
data.echoOn = 1;
}else if( strcmp(z,"-stats")==0 ){
data.statsOn = 1;
}else if( strcmp(z,"-bail")==0 ){
bail_on_error = 1;
}else if( strcmp(z,"-version")==0 ){
+69 -21
View File
@@ -92,7 +92,7 @@ extern "C" {
**
** Since version 3.6.18, SQLite source code has been stored in the
** <a href="http://www.fossil-scm.org/">Fossil configuration management
** system</a>. ^The SQLITE_SOURCE_ID macro evalutes to
** system</a>. ^The SQLITE_SOURCE_ID macro evaluates to
** a string which identifies a particular check-in of SQLite
** within its configuration management system. ^The SQLITE_SOURCE_ID
** string contains the date and time of the check-in (UTC) and an SHA1
@@ -149,7 +149,7 @@ int sqlite3_libversion_number(void);
** compile time. ^The SQLITE_ prefix may be omitted from the
** option name passed to sqlite3_compileoption_used().
**
** ^The sqlite3_compileoption_get() function allows interating
** ^The sqlite3_compileoption_get() function allows iterating
** over the list of options that were defined at compile time by
** returning the N-th compile time option string. ^If N is out of range,
** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_
@@ -157,7 +157,7 @@ int sqlite3_libversion_number(void);
** sqlite3_compileoption_get().
**
** ^Support for the diagnostic functions sqlite3_compileoption_used()
** and sqlite3_compileoption_get() may be omitted by specifing the
** and sqlite3_compileoption_get() may be omitted by specifying the
** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time.
**
** See also: SQL functions [sqlite_compileoption_used()] and
@@ -263,7 +263,7 @@ typedef sqlite_uint64 sqlite3_uint64;
**
** ^The sqlite3_close() routine is the destructor for the [sqlite3] object.
** ^Calls to sqlite3_close() return SQLITE_OK if the [sqlite3] object is
** successfullly destroyed and all associated resources are deallocated.
** successfully destroyed and all associated resources are deallocated.
**
** Applications must [sqlite3_finalize | finalize] all [prepared statements]
** and [sqlite3_blob_close | close] all [BLOB handles] associated with
@@ -690,12 +690,21 @@ struct sqlite3_io_methods {
** is often close. The underlying VFS might choose to preallocate database
** file space based on this hint in order to help writes to the database
** file run faster.
**
** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
** extends and truncates the database file in chunks of a size specified
** by the user. The fourth argument to [sqlite3_file_control()] should
** point to an integer (type int) containing the new chunk-size to use
** for the nominated database. Allocating database file space in large
** chunks (say 1MB at a time), may reduce file-system fragmentation and
** improve performance on some systems.
*/
#define SQLITE_FCNTL_LOCKSTATE 1
#define SQLITE_GET_LOCKPROXYFILE 2
#define SQLITE_SET_LOCKPROXYFILE 3
#define SQLITE_LAST_ERRNO 4
#define SQLITE_FCNTL_SIZE_HINT 5
#define SQLITE_FCNTL_CHUNK_SIZE 6
/*
** CAPI3REF: Mutex Handle
@@ -2171,7 +2180,13 @@ int sqlite3_set_authorizer(
** ^The callback function registered by sqlite3_profile() is invoked
** as each SQL statement finishes. ^The profile callback contains
** the original statement text and an estimate of wall-clock time
** of how long that statement took to run.
** of how long that statement took to run. ^The profile callback
** time is in units of nanoseconds, however the current implementation
** is only capable of millisecond resolution so the six least significant
** digits in the time are meaningless. Future versions of SQLite
** might provide greater resolution on the profiler callback. The
** sqlite3_profile() function is considered experimental and is
** subject to change in future versions of SQLite.
*/
void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
@@ -2652,7 +2667,7 @@ typedef struct sqlite3_context sqlite3_context;
** </ul>
**
** In the templates above, NNN represents an integer literal,
** and VVV represents an alphanumeric identifer.)^ ^The values of these
** and VVV represents an alphanumeric identifier.)^ ^The values of these
** parameters (also called "host parameter names" or "SQL parameters")
** can be set using the sqlite3_bind_*() routines defined here.
**
@@ -3431,7 +3446,7 @@ int sqlite3_value_numeric_type(sqlite3_value*);
/*
** CAPI3REF: Obtain Aggregate Function Context
**
** Implementions of aggregate SQL functions use this
** Implementations of aggregate SQL functions use this
** routine to allocate memory for storing their state.
**
** ^The first time the sqlite3_aggregate_context(C,N) routine is called
@@ -3703,7 +3718,7 @@ void sqlite3_result_zeroblob(sqlite3_context*, int n);
**
** A pointer to the user supplied routine must be passed as the fifth
** argument. ^If it is NULL, this is the same as deleting the collation
** sequence (so that SQLite cannot call it anymore).
** sequence (so that SQLite cannot call it any more).
** ^Each time the application supplied function is invoked, it is passed
** as its first parameter a copy of the void* passed as the fourth argument
** to sqlite3_create_collation() or sqlite3_create_collation16().
@@ -4320,7 +4335,8 @@ struct sqlite3_module {
** CAPI3REF: Virtual Table Indexing Information
** KEYWORDS: sqlite3_index_info
**
** The sqlite3_index_info structure and its substructures is used to
** The sqlite3_index_info structure and its substructures is used as part
** of the [virtual table] interface to
** pass information into and receive the reply from the [xBestIndex]
** method of a [virtual table module]. The fields under **Inputs** are the
** inputs to xBestIndex and are read-only. xBestIndex inserts its
@@ -4328,10 +4344,12 @@ struct sqlite3_module {
**
** ^(The aConstraint[] array records WHERE clause constraints of the form:
**
** <pre>column OP expr</pre>
** <blockquote>column OP expr</blockquote>
**
** where OP is =, &lt;, &lt;=, &gt;, or &gt;=.)^ ^(The particular operator is
** stored in aConstraint[].op.)^ ^(The index of the column is stored in
** stored in aConstraint[].op using one of the
** [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^
** ^(The index of the column is stored in
** aConstraint[].iColumn.)^ ^(aConstraint[].usable is TRUE if the
** expr on the right-hand side can be evaluated (and thus the constraint
** is usable) and false if it cannot.)^
@@ -4391,6 +4409,15 @@ struct sqlite3_index_info {
int orderByConsumed; /* True if output is already ordered */
double estimatedCost; /* Estimated cost of using this index */
};
/*
** CAPI3REF: Virtual Table Constraint Operator Codes
**
** These macros defined the allowed values for the
** [sqlite3_index_info].aConstraint[].op field. Each value represents
** an operator that is part of a constraint term in the wHERE clause of
** a query that uses a [virtual table].
*/
#define SQLITE_INDEX_CONSTRAINT_EQ 2
#define SQLITE_INDEX_CONSTRAINT_GT 4
#define SQLITE_INDEX_CONSTRAINT_LE 8
@@ -4909,7 +4936,7 @@ void sqlite3_mutex_leave(sqlite3_mutex*);
** it is passed a NULL pointer).
**
** The xMutexInit() method must be threadsafe. ^It must be harmless to
** invoke xMutexInit() mutiple times within the same process and without
** invoke xMutexInit() multiple times within the same process and without
** intervening calls to xMutexEnd(). Second and subsequent calls to
** xMutexInit() must be no-ops.
**
@@ -5079,7 +5106,7 @@ int sqlite3_test_control(int op, ...);
** CAPI3REF: SQLite Runtime Status
**
** ^This interface is used to retrieve runtime status information
** about the preformance of SQLite, and optionally to reset various
** about the performance of SQLite, and optionally to reset various
** highwater marks. ^The first argument is an integer code for
** the specific parameter to measure. ^(Recognized integer codes
** are of the form [SQLITE_STATUS_MEMORY_USED | SQLITE_STATUS_...].)^
@@ -5131,6 +5158,9 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
** *pHighwater parameter to [sqlite3_status()] is of interest.
** The value written into the *pCurrent parameter is undefined.</dd>)^
**
** ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
** <dd>This parameter records the number of separate memory allocations.</dd>)^
**
** ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
** <dd>This parameter returns the number of pages used out of the
** [pagecache memory allocator] that was configured using
@@ -5192,6 +5222,7 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
#define SQLITE_STATUS_PARSER_STACK 6
#define SQLITE_STATUS_PAGECACHE_SIZE 7
#define SQLITE_STATUS_SCRATCH_SIZE 8
#define SQLITE_STATUS_MALLOC_COUNT 9
/*
** CAPI3REF: Database Connection Status
@@ -5201,7 +5232,7 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
** database connection object to be interrogated. ^The second argument
** is an integer constant, taken from the set of
** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros, that
** determiness the parameter to interrogate. The set of
** determines the parameter to interrogate. The set of
** [SQLITE_DBSTATUS_LOOKASIDE_USED | SQLITE_DBSTATUS_*] macros is likely
** to grow in future releases of SQLite.
**
@@ -5231,16 +5262,33 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
** <dd>This parameter returns the number of lookaside memory slots currently
** checked out.</dd>)^
**
** <dt>SQLITE_DBSTATUS_CACHE_USED</dt>
** <dd>^This parameter returns the approximate number of of bytes of heap
** memory used by all pager caches associated with the database connection.
** ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** memory used by all pager caches associated with the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
**
** ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** memory used to store the schema for all databases associated
** with the connection - main, temp, and any [ATTACH]-ed databases.)^
** ^The full amount of memory used by the schemas is reported, even if the
** schema memory is shared with other database connections due to
** [shared cache mode] being enabled.
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
**
** ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
** <dd>This parameter returns the approximate number of of bytes of heap
** and lookaside memory used by all prepared statements associated with
** the database connection.)^
** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
** </dd>
** </dl>
*/
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
#define SQLITE_DBSTATUS_CACHE_USED 1
#define SQLITE_DBSTATUS_MAX 1 /* Largest defined DBSTATUS */
#define SQLITE_DBSTATUS_SCHEMA_USED 2
#define SQLITE_DBSTATUS_STMT_USED 3
#define SQLITE_DBSTATUS_MAX 3 /* Largest defined DBSTATUS */
/*
@@ -5606,7 +5654,7 @@ typedef struct sqlite3_backup sqlite3_backup;
**
** ^Each call to sqlite3_backup_step() sets two values inside
** the [sqlite3_backup] object: the number of pages still to be backed
** up and the total number of pages in the source databae file.
** up and the total number of pages in the source database file.
** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
** retrieve these two values, respectively.
**
@@ -5702,7 +5750,7 @@ int sqlite3_backup_pagecount(sqlite3_backup *p);
** blocked connection already has a registered unlock-notify callback,
** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is
** called with a NULL pointer as its second argument, then any existing
** unlock-notify callback is cancelled. ^The blocked connections
** unlock-notify callback is canceled. ^The blocked connections
** unlock-notify callback may also be canceled by closing the blocked
** connection using [sqlite3_close()].
**
@@ -5784,7 +5832,7 @@ int sqlite3_unlock_notify(
**
** ^The [sqlite3_strnicmp()] API allows applications and extensions to
** compare the contents of two buffers containing UTF-8 strings in a
** case-indendent fashion, using the same definition of case independence
** case-independent fashion, using the same definition of case independence
** that SQLite uses internally when comparing identifiers.
*/
int sqlite3_strnicmp(const char *, const char *, int);
+27 -33
View File
@@ -661,14 +661,6 @@ struct Db {
/*
** An instance of the following structure stores a database schema.
**
** If there are no virtual tables configured in this schema, the
** Schema.db variable is set to NULL. After the first virtual table
** has been added, it is set to point to the database connection
** used to create the connection. Once a virtual table has been
** added to the Schema structure and the Schema.db variable populated,
** only that database connection may use the Schema to prepare
** statements.
*/
struct Schema {
int schema_cookie; /* Database schema version number for this file */
@@ -681,9 +673,6 @@ struct Schema {
u8 enc; /* Text encoding used by this database */
u16 flags; /* Flags associated with this schema */
int cache_size; /* Number of pages to use in the cache */
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3 *db; /* "Owner" connection. See comment above */
#endif
};
/*
@@ -871,6 +860,7 @@ struct sqlite3 {
int nStatement; /* Number of nested statement-transactions */
u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */
i64 nDeferredCons; /* Net deferred constraints this transaction. */
int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
/* The following variables are all protected by the STATIC_MASTER
@@ -1228,7 +1218,6 @@ struct VTable {
** of a SELECT statement.
*/
struct Table {
sqlite3 *dbMem; /* DB connection used for lookaside allocations. */
char *zName; /* Name of the table or view */
int iPKey; /* If not negative, use aCol[iPKey] as the primary key */
int nCol; /* Number of columns in this table */
@@ -1365,9 +1354,9 @@ struct FKey {
*/
struct KeyInfo {
sqlite3 *db; /* The database connection */
u8 enc; /* Text encoding - one of the TEXT_Utf* values */
u8 enc; /* Text encoding - one of the SQLITE_UTF* values */
u16 nField; /* Number of entries in aColl[] */
u8 *aSortOrder; /* If defined an aSortOrder[i] is true, sort DESC */
u8 *aSortOrder; /* Sort order for each column. May be NULL */
CollSeq *aColl[1]; /* Collating sequence for each term of the key */
};
@@ -2337,7 +2326,7 @@ struct StrAccum {
int nAlloc; /* Amount of space allocated in zText */
int mxAlloc; /* Maximum allowed string length */
u8 mallocFailed; /* Becomes true if any memory allocation fails */
u8 useMalloc; /* True if zText is enlargeable using realloc */
u8 useMalloc; /* 0: none, 1: sqlite3DbMalloc, 2: sqlite3_malloc */
u8 tooBig; /* Becomes true if string size exceeds limits */
};
@@ -2635,7 +2624,7 @@ void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
#endif
void sqlite3DropTable(Parse*, SrcList*, int, int);
void sqlite3DeleteTable(Table*);
void sqlite3DeleteTable(sqlite3*, Table*);
#ifndef SQLITE_OMIT_AUTOINCREMENT
void sqlite3AutoincrementBegin(Parse *pParse);
void sqlite3AutoincrementEnd(Parse *pParse);
@@ -2869,7 +2858,8 @@ int sqlite3ReadSchema(Parse *pParse);
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
Expr *sqlite3ExprSetColl(Parse *pParse, Expr *, Token *);
Expr *sqlite3ExprSetColl(Expr*, CollSeq*);
Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr*, Token*);
int sqlite3CheckCollSeq(Parse *, CollSeq *);
int sqlite3CheckObjectName(Parse *, const char *);
void sqlite3VdbeSetChanges(sqlite3 *, int);
@@ -2919,7 +2909,7 @@ int sqlite3InvokeBusyHandler(BusyHandler*);
int sqlite3FindDb(sqlite3*, Token*);
int sqlite3FindDbName(sqlite3 *, const char *);
int sqlite3AnalysisLoad(sqlite3*,int iDB);
void sqlite3DeleteIndexSamples(Index*);
void sqlite3DeleteIndexSamples(sqlite3*,Index*);
void sqlite3DefaultRowEst(Index*);
void sqlite3RegisterLikeFunctions(sqlite3*, int);
int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
@@ -2981,7 +2971,7 @@ void sqlite3AutoLoadExtensions(sqlite3*);
# define sqlite3VtabUnlock(X)
# define sqlite3VtabUnlockList(X)
#else
void sqlite3VtabClear(Table*);
void sqlite3VtabClear(sqlite3 *db, Table*);
int sqlite3VtabSync(sqlite3 *db, char **);
int sqlite3VtabRollback(sqlite3 *db);
int sqlite3VtabCommit(sqlite3 *db);
@@ -3034,9 +3024,9 @@ int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
#define sqlite3FkRequired(a,b,c,d) 0
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
void sqlite3FkDelete(Table*);
void sqlite3FkDelete(sqlite3 *, Table*);
#else
#define sqlite3FkDelete(a)
#define sqlite3FkDelete(a,b)
#endif
@@ -3129,17 +3119,18 @@ SQLITE_EXTERN void (*sqlite3IoTrace)(const char*,...);
** sqlite3MemdebugHasType() returns true if any of the bits in its second
** argument match the type set by the previous sqlite3MemdebugSetType().
** sqlite3MemdebugHasType() is intended for use inside assert() statements.
** For example:
**
** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
** sqlite3MemdebugNoType() returns true if none of the bits in its second
** argument match the type set by the previous sqlite3MemdebugSetType().
**
** Perhaps the most important point is the difference between MEMTYPE_HEAP
** and MEMTYPE_DB. If an allocation is MEMTYPE_DB, that means it might have
** been allocated by lookaside, except the allocation was too large or
** lookaside was already full. It is important to verify that allocations
** that might have been satisfied by lookaside are not passed back to
** non-lookaside free() routines. Asserts such as the example above are
** placed on the non-lookaside free() routines to verify this constraint.
** and MEMTYPE_LOOKASIDE. If an allocation is MEMTYPE_LOOKASIDE, that means
** it might have been allocated by lookaside, except the allocation was
** too large or lookaside was already full. It is important to verify
** that allocations that might have been satisfied by lookaside are not
** passed back to non-lookaside free() routines. Asserts such as the
** example above are placed on the non-lookaside free() routines to verify
** this constraint.
**
** All of this is no-op for a production build. It only comes into
** play when the SQLITE_MEMDEBUG compile-time option is used.
@@ -3147,13 +3138,16 @@ SQLITE_EXTERN void (*sqlite3IoTrace)(const char*,...);
#ifdef SQLITE_MEMDEBUG
void sqlite3MemdebugSetType(void*,u8);
int sqlite3MemdebugHasType(void*,u8);
int sqlite3MemdebugNoType(void*,u8);
#else
# define sqlite3MemdebugSetType(X,Y) /* no-op */
# define sqlite3MemdebugHasType(X,Y) 1
# define sqlite3MemdebugNoType(X,Y) 1
#endif
#define MEMTYPE_HEAP 0x01 /* General heap allocations */
#define MEMTYPE_DB 0x02 /* Associated with a database connection */
#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */
#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */
#define MEMTYPE_HEAP 0x01 /* General heap allocations */
#define MEMTYPE_LOOKASIDE 0x02 /* Might have been lookaside memory */
#define MEMTYPE_SCRATCH 0x04 /* Scratch allocations */
#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */
#define MEMTYPE_DB 0x10 /* Uses sqlite3DbMalloc, not sqlite_malloc */
#endif /* _SQLITEINT_H_ */
+12 -11
View File
@@ -133,20 +133,21 @@
# define SQLITE_MAX_VARIABLE_NUMBER 999
#endif
/* Maximum page size. The upper bound on this value is 32768. This a limit
** imposed by the necessity of storing the value in a 2-byte unsigned integer
** and the fact that the page size must be a power of 2.
/* Maximum page size. The upper bound on this value is 65536. This a limit
** imposed by the use of 16-bit offsets within each page.
**
** If this limit is changed, then the compiled library is technically
** incompatible with an SQLite library compiled with a different limit. If
** a process operating on a database with a page-size of 65536 bytes
** crashes, then an instance of SQLite compiled with the default page-size
** limit will not be able to rollback the aborted transaction. This could
** lead to database corruption.
** Earlier versions of SQLite allowed the user to change this value at
** compile time. This is no longer permitted, on the grounds that it creates
** a library that is technically incompatible with an SQLite library
** compiled with a different limit. If a process operating on a database
** with a page-size of 65536 bytes crashes, then an instance of SQLite
** compiled with the default page-size limit will not be able to rollback
** the aborted transaction. This could lead to database corruption.
*/
#ifndef SQLITE_MAX_PAGE_SIZE
# define SQLITE_MAX_PAGE_SIZE 32768
#ifdef SQLITE_MAX_PAGE_SIZE
# undef SQLITE_MAX_PAGE_SIZE
#endif
#define SQLITE_MAX_PAGE_SIZE 65536
/*
+73 -4
View File
@@ -14,14 +14,15 @@
** functionality.
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
/*
** Variables in which to record status information.
*/
typedef struct sqlite3StatType sqlite3StatType;
static SQLITE_WSD struct sqlite3StatType {
int nowValue[9]; /* Current value */
int mxValue[9]; /* Maximum value */
int nowValue[10]; /* Current value */
int mxValue[10]; /* Maximum value */
} sqlite3Stat = { {0,}, {0,} };
@@ -103,6 +104,8 @@ int sqlite3_db_status(
int *pHighwater, /* Write high-water mark here */
int resetFlag /* Reset high-water mark if true */
){
int rc = SQLITE_OK; /* Return code */
sqlite3_mutex_enter(db->mutex);
switch( op ){
case SQLITE_DBSTATUS_LOOKASIDE_USED: {
*pCurrent = db->lookaside.nOut;
@@ -121,6 +124,7 @@ int sqlite3_db_status(
case SQLITE_DBSTATUS_CACHE_USED: {
int totalUsed = 0;
int i;
sqlite3BtreeEnterAll(db);
for(i=0; i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
@@ -128,13 +132,78 @@ int sqlite3_db_status(
totalUsed += sqlite3PagerMemUsed(pPager);
}
}
sqlite3BtreeLeaveAll(db);
*pCurrent = totalUsed;
*pHighwater = 0;
break;
}
/*
** *pCurrent gets an accurate estimate of the amount of memory used
** to store the schema for all databases (main, temp, and any ATTACHed
** databases. *pHighwater is set to zero.
*/
case SQLITE_DBSTATUS_SCHEMA_USED: {
int i; /* Used to iterate through schemas */
int nByte = 0; /* Used to accumulate return value */
db->pnBytesFreed = &nByte;
for(i=0; i<db->nDb; i++){
Schema *pSchema = db->aDb[i].pSchema;
if( ALWAYS(pSchema!=0) ){
HashElem *p;
nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
pSchema->tblHash.count
+ pSchema->trigHash.count
+ pSchema->idxHash.count
+ pSchema->fkeyHash.count
);
nByte += sqlite3MallocSize(pSchema->tblHash.ht);
nByte += sqlite3MallocSize(pSchema->trigHash.ht);
nByte += sqlite3MallocSize(pSchema->idxHash.ht);
nByte += sqlite3MallocSize(pSchema->fkeyHash.ht);
for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
}
for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
}
}
}
db->pnBytesFreed = 0;
*pHighwater = 0;
*pCurrent = nByte;
break;
}
/*
** *pCurrent gets an accurate estimate of the amount of memory used
** to store all prepared statements.
** *pHighwater is set to zero.
*/
case SQLITE_DBSTATUS_STMT_USED: {
struct Vdbe *pVdbe; /* Used to iterate through VMs */
int nByte = 0; /* Used to accumulate return value */
db->pnBytesFreed = &nByte;
for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
sqlite3VdbeDeleteObject(db, pVdbe);
}
db->pnBytesFreed = 0;
*pHighwater = 0;
*pCurrent = nByte;
break;
}
default: {
return SQLITE_ERROR;
rc = SQLITE_ERROR;
}
}
return SQLITE_OK;
sqlite3_mutex_leave(db->mutex);
return rc;
}
+17 -17
View File
@@ -2571,7 +2571,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
int v;
const char *zOp;
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 2, objv, "(step|sort)");
Tcl_WrongNumArgs(interp, 2, objv, "(step|sort|autoindex)");
return TCL_ERROR;
}
zOp = Tcl_GetString(objv[2]);
@@ -3015,7 +3015,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
** used to open a new SQLite database. See the DbMain() routine above
** for additional information.
*/
EXTERN int Sqlite3_Init(Tcl_Interp *interp){
int Sqlite3_Init(Tcl_Interp *interp){
Tcl_InitStubs(interp, "8.4", 0);
Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);
Tcl_PkgProvide(interp, "sqlite3", PACKAGE_VERSION);
@@ -3023,24 +3023,24 @@ EXTERN int Sqlite3_Init(Tcl_Interp *interp){
Tcl_PkgProvide(interp, "sqlite", PACKAGE_VERSION);
return TCL_OK;
}
EXTERN int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
EXTERN int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
EXTERN int Tclsqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
EXTERN int Sqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
EXTERN int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
EXTERN int Sqlite3_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK; }
EXTERN int Tclsqlite3_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK;}
int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
int Tclsqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
int Sqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
int Sqlite3_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK; }
int Tclsqlite3_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK;}
#ifndef SQLITE_3_SUFFIX_ONLY
EXTERN int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
EXTERN int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
EXTERN int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
EXTERN int Tclsqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
EXTERN int Sqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
EXTERN int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
EXTERN int Sqlite_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK; }
EXTERN int Tclsqlite_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK;}
int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
int Tclsqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }
int Sqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
int Sqlite_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK; }
int Tclsqlite_SafeUnload(Tcl_Interp *interp, int flags){ return TCL_OK;}
#endif
#ifdef TCLSH
+81
View File
@@ -4613,6 +4613,44 @@ static int file_control_lasterrno_test(
return TCL_OK;
}
/*
** tclcmd: file_control_chunksize_test DB DBNAME SIZE
**
** This TCL command runs the sqlite3_file_control interface and
** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
** SQLITE_SET_LOCKPROXYFILE verbs.
*/
static int file_control_chunksize_test(
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
int nSize; /* New chunk size */
char *zDb; /* Db name ("main", "temp" etc.) */
sqlite3 *db; /* Database handle */
int rc; /* file_control() return code */
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
|| Tcl_GetIntFromObj(interp, objv[3], &nSize)
){
return TCL_ERROR;
}
zDb = Tcl_GetString(objv[2]);
if( zDb[0]=='\0' ) zDb = NULL;
rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize);
if( rc ){
Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC);
return TCL_ERROR;
}
return TCL_OK;
}
/*
** tclcmd: file_control_lockproxy_test DB PWD
**
@@ -4911,6 +4949,47 @@ static int test_wal_checkpoint(
return TCL_OK;
}
/*
** tclcmd: test_sqlite3_log ?SCRIPT?
*/
static struct LogCallback {
Tcl_Interp *pInterp;
Tcl_Obj *pObj;
} logcallback = {0, 0};
static void xLogcallback(void *unused, int err, char *zMsg){
Tcl_Obj *pNew = Tcl_DuplicateObj(logcallback.pObj);
Tcl_IncrRefCount(pNew);
Tcl_ListObjAppendElement(
0, pNew, Tcl_NewStringObj(sqlite3TestErrorName(err), -1)
);
Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1));
Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
Tcl_DecrRefCount(pNew);
}
static int test_sqlite3_log(
ClientData clientData,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
if( objc>2 ){
Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT");
return TCL_ERROR;
}
if( logcallback.pObj ){
Tcl_DecrRefCount(logcallback.pObj);
logcallback.pObj = 0;
logcallback.pInterp = 0;
sqlite3_config(SQLITE_CONFIG_LOG, 0, 0);
}
if( objc>1 ){
logcallback.pObj = objv[1];
Tcl_IncrRefCount(logcallback.pObj);
logcallback.pInterp = interp;
sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, 0);
}
return TCL_OK;
}
/*
** tcl_objproc COMMANDNAME ARGS...
@@ -5106,6 +5185,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "file_control_test", file_control_test, 0 },
{ "file_control_lasterrno_test", file_control_lasterrno_test, 0 },
{ "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
{ "file_control_chunksize_test", file_control_chunksize_test, 0 },
{ "sqlite3_vfs_list", vfs_list, 0 },
/* Functions from os.h */
@@ -5133,6 +5213,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_unlock_notify", test_unlock_notify, 0 },
#endif
{ "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 },
{ "test_sqlite3_log", test_sqlite3_log, 0 },
};
static int bitmask_size = sizeof(Bitmask)*8;
int i;
+1 -1
View File
@@ -72,7 +72,7 @@ static int pager_open(
int argc, /* Number of arguments */
const char **argv /* Text of each argument */
){
u16 pageSize;
u32 pageSize;
Pager *pPager;
int nPage;
int rc;
+2 -2
View File
@@ -142,7 +142,7 @@ static int tcl_thread_create(
}
threadset[i].busy = 1;
sqlite3_free(threadset[i].zFilename);
threadset[i].zFilename = sqlite3DbStrDup(0, argv[2]);
threadset[i].zFilename = sqlite3_mprintf("%s", argv[2]);
threadset[i].opnum = 1;
threadset[i].completed = 0;
rc = pthread_create(&x, 0, thread_main, &threadset[i]);
@@ -476,7 +476,7 @@ static int tcl_thread_compile(
thread_wait(&threadset[i]);
threadset[i].xOp = do_compile;
sqlite3_free(threadset[i].zArg);
threadset[i].zArg = sqlite3DbStrDup(0, argv[2]);
threadset[i].zArg = sqlite3_mprintf("%s", argv[2]);
threadset[i].opnum++;
return TCL_OK;
}
+1 -1
View File
@@ -155,7 +155,7 @@ static int test_translate(
if( enc_from==SQLITE_UTF8 ){
z = Tcl_GetString(objv[1]);
if( objc==5 ){
z = sqlite3DbStrDup(0, z);
z = sqlite3_mprintf("%s", z);
}
sqlite3ValueSetStr(pVal, -1, z, enc_from, xDel);
}else{
+2 -2
View File
@@ -164,7 +164,7 @@ static int tcl_client_create(
}
threadset[i].busy = 1;
sqlite3_free(threadset[i].zFilename);
threadset[i].zFilename = sqlite3DbStrDup(0, argv[2]);
threadset[i].zFilename = sqlite3_mprintf("%s", argv[2]);
threadset[i].opnum = 1;
threadset[i].completed = 0;
rc = pthread_create(&x, 0, client_main, &threadset[i]);
@@ -507,7 +507,7 @@ static int tcl_client_compile(
client_wait(&threadset[i]);
threadset[i].xOp = do_compile;
sqlite3_free(threadset[i].zArg);
threadset[i].zArg = sqlite3DbStrDup(0, argv[2]);
threadset[i].zArg = sqlite3_mprintf("%s", argv[2]);
threadset[i].opnum++;
return TCL_OK;
}
+1 -1
View File
@@ -485,7 +485,7 @@ static int echoCreate(
rc = sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
if( rc!=SQLITE_OK ){
*pzErr = sqlite3DbStrDup(0, sqlite3_errmsg(db));
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
}
}
+16 -7
View File
@@ -127,6 +127,7 @@
#include <sys/param.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
/*
** Size of the write buffer used by journal files in bytes.
@@ -135,6 +136,11 @@
# define SQLITE_DEMOVFS_BUFFERSZ 8192
#endif
/*
** The maximum pathname length supported by this VFS.
*/
#define MAXPATHNAME 512
/*
** When using this VFS, the sqlite3_file* handles that SQLite uses are
** actually pointers to instances of type DemoFile.
@@ -446,16 +452,19 @@ static int demoOpen(
** file has been synced to disk before returning.
*/
static int demoDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
int rc;
int rc; /* Return code */
rc = unlink(zPath);
if( rc!=0 && errno==ENOENT ) return SQLITE_OK;
if( rc==0 && dirSync ){
int dfd; /* File descriptor open on directory */
int i; /* Iterator variable */
char zDir[pVfs->mxPathname+1];/* Name of directory containing file zPath */
char zDir[MAXPATHNAME+1]; /* Name of directory containing file zPath */
/* Figure out the directory name from the path of the file deleted. */
sqlite3_snprintf(pVfs->mxPathname, zDir, "%s", zPath);
zDir[pVfs->mxPathname] = '\0';
sqlite3_snprintf(MAXPATHNAME, zDir, "%s", zPath);
zDir[MAXPATHNAME] = '\0';
for(i=strlen(zDir); i>1 && zDir[i]!='/'; i++);
zDir[i] = '\0';
@@ -524,13 +533,13 @@ static int demoFullPathname(
int nPathOut, /* Size of output buffer in bytes */
char *zPathOut /* Pointer to output buffer */
){
char zDir[pVfs->mxPathname+1];
char zDir[MAXPATHNAME+1];
if( zPath[0]=='/' ){
zDir[0] = '\0';
}else{
getcwd(zDir, sizeof(zDir));
}
zDir[pVfs->mxPathname] = '\0';
zDir[MAXPATHNAME] = '\0';
sqlite3_snprintf(nPathOut, zPathOut, "%s/%s", zDir, zPath);
zPathOut[nPathOut-1] = '\0';
@@ -609,7 +618,7 @@ sqlite3_vfs *sqlite3_demovfs(void){
static sqlite3_vfs demovfs = {
1, /* iVersion */
sizeof(DemoFile), /* szOsFile */
512, /* mxPathname */
MAXPATHNAME, /* mxPathname */
0, /* pNext */
"demo", /* zName */
0, /* pAppData */
+10 -1
View File
@@ -361,6 +361,7 @@ static int openTransaction(jt_file *pMain, jt_file *pJournal){
sqlite3_file *p = pMain->pReal;
int rc = SQLITE_OK;
closeTransaction(pMain);
aData = sqlite3_malloc(pMain->nPagesize);
pMain->pWritable = sqlite3BitvecCreate(pMain->nPage);
pMain->aCksum = sqlite3_malloc(sizeof(u32) * (pMain->nPage + 1));
@@ -379,6 +380,15 @@ static int openTransaction(jt_file *pMain, jt_file *pJournal){
** leaf to the jt_file.pWritable bitvec.
*/
rc = sqlite3OsRead(p, aData, pMain->nPagesize, 0);
if( rc==SQLITE_OK ){
u32 nDbsize = decodeUint32(&aData[28]);
if( nDbsize>0 && memcmp(&aData[24], &aData[92], 4)==0 ){
u32 iPg;
for(iPg=nDbsize+1; iPg<=pMain->nPage; iPg++){
sqlite3BitvecSet(pMain->pWritable, iPg);
}
}
}
iTrunk = decodeUint32(&aData[32]);
while( rc==SQLITE_OK && iTrunk>0 ){
u32 nLeaf;
@@ -492,7 +502,6 @@ finish_rjf:
return rc;
}
/*
** Write data to an jt-file.
*/
+14 -8
View File
@@ -728,7 +728,10 @@ static int test_memdebug_settitle(
return TCL_OK;
}
#define MALLOC_LOG_FRAMES 10
#define MALLOC_LOG_FRAMES 10
#define MALLOC_LOG_KEYINTS ( \
10 * ((sizeof(int)>=sizeof(void*)) ? 1 : sizeof(void*)/sizeof(int)) \
)
static Tcl_HashTable aMallocLog;
static int mallocLogEnabled = 0;
@@ -745,8 +748,8 @@ static void test_memdebug_callback(int nByte, int nFrame, void **aFrame){
Tcl_HashEntry *pEntry;
int isNew;
int aKey[MALLOC_LOG_FRAMES];
int nKey = sizeof(int)*MALLOC_LOG_FRAMES;
int aKey[MALLOC_LOG_KEYINTS];
int nKey = sizeof(int)*MALLOC_LOG_KEYINTS;
memset(aKey, 0, nKey);
if( (sizeof(void*)*nFrame)<nKey ){
@@ -781,7 +784,7 @@ static void test_memdebug_log_clear(void){
Tcl_Free((char *)pLog);
}
Tcl_DeleteHashTable(&aMallocLog);
Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_FRAMES);
Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS);
}
static int test_memdebug_log(
@@ -804,7 +807,7 @@ static int test_memdebug_log(
void (*xBacktrace)(int, int, void **));
sqlite3MemdebugBacktraceCallback(test_memdebug_callback);
#endif
Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_FRAMES);
Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS);
isInit = 1;
}
@@ -827,7 +830,7 @@ static int test_memdebug_log(
Tcl_HashEntry *pEntry;
Tcl_Obj *pRet = Tcl_NewObj();
assert(sizeof(int)==sizeof(void*));
assert(sizeof(Tcl_WideInt)>=sizeof(void*));
for(
pEntry=Tcl_FirstHashEntry(&aMallocLog, &search);
@@ -836,13 +839,13 @@ static int test_memdebug_log(
){
Tcl_Obj *apElem[MALLOC_LOG_FRAMES+2];
MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
int *aKey = (int *)Tcl_GetHashKey(&aMallocLog, pEntry);
Tcl_WideInt *aKey = (Tcl_WideInt *)Tcl_GetHashKey(&aMallocLog, pEntry);
int ii;
apElem[0] = Tcl_NewIntObj(pLog->nCall);
apElem[1] = Tcl_NewIntObj(pLog->nByte);
for(ii=0; ii<MALLOC_LOG_FRAMES; ii++){
apElem[ii+2] = Tcl_NewIntObj(aKey[ii]);
apElem[ii+2] = Tcl_NewWideIntObj(aKey[ii]);
}
Tcl_ListObjAppendElement(interp, pRet,
@@ -1237,6 +1240,7 @@ static int test_status(
{ "SQLITE_STATUS_SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW },
{ "SQLITE_STATUS_SCRATCH_SIZE", SQLITE_STATUS_SCRATCH_SIZE },
{ "SQLITE_STATUS_PARSER_STACK", SQLITE_STATUS_PARSER_STACK },
{ "SQLITE_STATUS_MALLOC_COUNT", SQLITE_STATUS_MALLOC_COUNT },
};
Tcl_Obj *pResult;
if( objc!=3 ){
@@ -1288,6 +1292,8 @@ static int test_db_status(
} aOp[] = {
{ "SQLITE_DBSTATUS_LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED },
{ "SQLITE_DBSTATUS_CACHE_USED", SQLITE_DBSTATUS_CACHE_USED },
{ "SQLITE_DBSTATUS_SCHEMA_USED", SQLITE_DBSTATUS_SCHEMA_USED },
{ "SQLITE_DBSTATUS_STMT_USED", SQLITE_DBSTATUS_STMT_USED }
};
Tcl_Obj *pResult;
if( objc!=4 ){
+7 -9
View File
@@ -376,7 +376,13 @@ static int statNext(sqlite3_vtab_cursor *pCursor){
if( pCsr->aPage[0].pPg==0 ){
rc = sqlite3_step(pCsr->pStmt);
if( rc==SQLITE_ROW ){
int nPage;
u32 iRoot = sqlite3_column_int64(pCsr->pStmt, 1);
sqlite3PagerPagecount(pPager, &nPage);
if( nPage==0 ){
pCsr->isEof = 1;
return sqlite3_reset(pCsr->pStmt);
}
rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg);
pCsr->aPage[0].iPgno = iRoot;
pCsr->aPage[0].iCell = 0;
@@ -486,17 +492,9 @@ static int statFilter(
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
sqlite3 *db = ((StatTable *)(pCursor->pVtab))->db;
StatCursor *pCsr = (StatCursor *)pCursor;
int nPage = 0;
statResetCsr((StatCursor *)pCursor);
sqlite3PagerPagecount(sqlite3BtreePager(db->aDb[0].pBt), &nPage);
if( nPage==0 ){
pCsr->isEof = 1;
return SQLITE_OK;
}
statResetCsr(pCsr);
return statNext(pCursor);
}
+2 -2
View File
@@ -1000,7 +1000,7 @@ static int testvfs_obj_cmd(
int n;
u8 *a = Tcl_GetByteArrayFromObj(objv[3], &n);
int pgsz = pBuffer->pgsz;
if( pgsz==0 ) pgsz = 32768;
if( pgsz==0 ) pgsz = 65536;
for(i=0; i*pgsz<n; i++){
int nByte = pgsz;
tvfsAllocPage(pBuffer, i, pgsz);
@@ -1014,7 +1014,7 @@ static int testvfs_obj_cmd(
pObj = Tcl_NewObj();
for(i=0; pBuffer->aPage[i]; i++){
int pgsz = pBuffer->pgsz;
if( pgsz==0 ) pgsz = 32768;
if( pgsz==0 ) pgsz = 65536;
Tcl_AppendObjToObj(pObj, Tcl_NewByteArrayObj(pBuffer->aPage[i], pgsz));
}
Tcl_SetObjResult(interp, pObj);
+3 -3
View File
@@ -496,7 +496,7 @@ abort_parse:
}
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3DbFree(db, pParse->apVtabLock);
sqlite3_free(pParse->apVtabLock);
#endif
if( !IN_DECLARE_VTAB ){
@@ -504,7 +504,7 @@ abort_parse:
** structure built up in pParse->pNewTable. The calling code (see vtab.c)
** will take responsibility for freeing the Table structure.
*/
sqlite3DeleteTable(pParse->pNewTable);
sqlite3DeleteTable(db, pParse->pNewTable);
}
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
@@ -518,7 +518,7 @@ abort_parse:
while( pParse->pZombieTab ){
Table *p = pParse->pZombieTab;
pParse->pZombieTab = p->pNextZombie;
sqlite3DeleteTable(p);
sqlite3DeleteTable(db, p);
}
if( nErr>0 && pParse->rc==SQLITE_OK ){
pParse->rc = SQLITE_ERROR;
+5 -3
View File
@@ -800,6 +800,7 @@ static TriggerPrg *codeRowTrigger(
int iEndTrigger = 0; /* Label to jump to if WHEN is false */
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
assert( pTop->pVdbe );
/* Allocate the TriggerPrg and SubProgram objects. To ensure that they
** are freed if an error occurs, link them into the Parse.pTriggerPrg
@@ -810,7 +811,7 @@ static TriggerPrg *codeRowTrigger(
pTop->pTriggerPrg = pPrg;
pPrg->pProgram = pProgram = sqlite3DbMallocZero(db, sizeof(SubProgram));
if( !pProgram ) return 0;
pProgram->nRef = 1;
sqlite3VdbeLinkSubProgram(pTop->pVdbe, pProgram);
pPrg->pTrigger = pTrigger;
pPrg->orconf = orconf;
pPrg->aColmask[0] = 0xffffffff;
@@ -944,8 +945,9 @@ void sqlite3CodeRowTriggerDirect(
/* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program
** is a pointer to the sub-vdbe containing the trigger program. */
if( pPrg ){
int bRecursive = (p->zName && 0==(pParse->db->flags&SQLITE_RecTriggers));
sqlite3VdbeAddOp3(v, OP_Program, reg, ignoreJump, ++pParse->nMem);
pPrg->pProgram->nRef++;
sqlite3VdbeChangeP4(v, -1, (const char *)pPrg->pProgram, P4_SUBPROGRAM);
VdbeComment(
(v, "Call: %s.%s", (p->zName?p->zName:"fkey"), onErrorText(orconf)));
@@ -955,7 +957,7 @@ void sqlite3CodeRowTriggerDirect(
** invocation is disallowed if (a) the sub-program is really a trigger,
** not a foreign key action, and (b) the flag to enable recursive triggers
** is clear. */
sqlite3VdbeChangeP5(v, (u8)(p->zName && !(pParse->db->flags&SQLITE_RecTriggers)));
sqlite3VdbeChangeP5(v, (u8)bRecursive);
}
}
+1 -1
View File
@@ -8,7 +8,7 @@
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
sqlite*************************************************************************
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
*/
+23 -27
View File
@@ -501,6 +501,20 @@ static int checkSavepointCount(sqlite3 *db){
}
#endif
/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
** in memory obtained from sqlite3DbMalloc).
*/
static void importVtabErrMsg(Vdbe *p, sqlite3_vtab *pVtab){
sqlite3 *db = p->db;
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
sqlite3_free(pVtab->zErrMsg);
pVtab->zErrMsg = 0;
}
/*
** Execute as much of a VDBE program as we can then return.
**
@@ -4030,9 +4044,7 @@ case OP_Rowid: { /* out2-prerelease */
pModule = pVtab->pModule;
assert( pModule->xRowid );
rc = pModule->xRowid(pC->pVtabCursor, &v);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
importVtabErrMsg(p, pVtab);
#endif /* SQLITE_OMIT_VIRTUALTABLE */
}else{
assert( pC->pCursor!=0 );
@@ -4337,7 +4349,7 @@ case OP_IdxRowid: { /* out2-prerelease */
** that if the key from register P3 is a prefix of the key in the cursor,
** the result is false whereas it would be true with IdxGT.
*/
/* Opcode: IdxLT P1 P2 P3 * P5
/* Opcode: IdxLT P1 P2 P3 P4 P5
**
** The P4 register values beginning with P3 form an unpacked index
** key that omits the ROWID. Compare this key value against the index
@@ -5375,11 +5387,7 @@ case OP_VBegin: {
VTable *pVTab;
pVTab = pOp->p4.pVtab;
rc = sqlite3VtabBegin(db, pVTab);
if( pVTab ){
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVTab->pVtab->zErrMsg;
pVTab->pVtab->zErrMsg = 0;
}
if( pVTab ) importVtabErrMsg(p, pVTab->pVtab);
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -5429,9 +5437,7 @@ case OP_VOpen: {
pModule = (sqlite3_module *)pVtab->pModule;
assert(pVtab && pModule);
rc = pModule->xOpen(pVtab, &pVtabCursor);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
importVtabErrMsg(p, pVtab);
if( SQLITE_OK==rc ){
/* Initialize sqlite3_vtab_cursor base class */
pVtabCursor->pVtab = pVtab;
@@ -5508,9 +5514,7 @@ case OP_VFilter: { /* jump */
p->inVtabMethod = 1;
rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
p->inVtabMethod = 0;
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
importVtabErrMsg(p, pVtab);
if( rc==SQLITE_OK ){
res = pModule->xEof(pVtabCursor);
}
@@ -5560,9 +5564,7 @@ case OP_VColumn: {
MemSetTypeFlag(&sContext.s, MEM_Null);
rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
importVtabErrMsg(p, pVtab);
if( sContext.isError ){
rc = sContext.isError;
}
@@ -5615,9 +5617,7 @@ case OP_VNext: { /* jump */
p->inVtabMethod = 1;
rc = pModule->xNext(pCur->pVtabCursor);
p->inVtabMethod = 0;
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
importVtabErrMsg(p, pVtab);
if( rc==SQLITE_OK ){
res = pModule->xEof(pCur->pVtabCursor);
}
@@ -5647,9 +5647,7 @@ case OP_VRename: {
REGISTER_TRACE(pOp->p1, pName);
assert( pName->flags & MEM_Str );
rc = pVtab->pModule->xRename(pVtab, pName->z);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
importVtabErrMsg(p, pVtab);
break;
}
@@ -5701,9 +5699,7 @@ case OP_VUpdate: {
pX++;
}
rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
importVtabErrMsg(p, pVtab);
if( rc==SQLITE_OK && pOp->p1 ){
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
db->lastRowid = rowid;
+6 -2
View File
@@ -81,8 +81,8 @@ struct SubProgram {
int nOp; /* Elements in aOp[] */
int nMem; /* Number of memory cells required */
int nCsr; /* Number of cursors required */
int nRef; /* Number of pointers to this structure */
void *token; /* id that may be used to recursive triggers */
SubProgram *pNext; /* Next sub-program already visited */
};
/*
@@ -184,6 +184,7 @@ VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
int sqlite3VdbeMakeLabel(Vdbe*);
void sqlite3VdbeRunOnlyOnce(Vdbe*);
void sqlite3VdbeDelete(Vdbe*);
void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*);
void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int);
int sqlite3VdbeFinalize(Vdbe*);
void sqlite3VdbeResolveLabel(Vdbe*, int);
@@ -201,7 +202,6 @@ sqlite3 *sqlite3VdbeDb(Vdbe*);
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int);
void sqlite3VdbeSwap(Vdbe*,Vdbe*);
VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
void sqlite3VdbeProgramDelete(sqlite3 *, SubProgram *, int);
sqlite3_value *sqlite3VdbeGetValue(Vdbe*, int, u8);
void sqlite3VdbeSetVarmask(Vdbe*, int);
#ifndef SQLITE_OMIT_TRACE
@@ -212,6 +212,10 @@ UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,char*,int);
void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
#ifndef SQLITE_OMIT_TRIGGER
void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
#endif
#ifndef NDEBUG
void sqlite3VdbeComment(Vdbe*, const char*, ...);
+1
View File
@@ -323,6 +323,7 @@ struct Vdbe {
VdbeFrame *pFrame; /* Parent frame */
int nFrame; /* Number of frames in pFrame list */
u32 expmask; /* Binding to these vars invalidates VM */
SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
};
/*
+1 -1
View File
@@ -398,7 +398,7 @@ static int sqlite3Step(Vdbe *p){
if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){
sqlite3_int64 iNow;
sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
db->xProfile(db->pProfileArg, p->zSql, iNow - p->startTime);
db->xProfile(db->pProfileArg, p->zSql, (iNow - p->startTime)*1000000);
}
#endif
+73 -54
View File
@@ -573,15 +573,17 @@ static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
}
}
static void vdbeFreeOpArray(sqlite3 *, Op *, int);
/*
** Delete a P4 value if necessary.
*/
static void freeP4(sqlite3 *db, int p4type, void *p4){
if( p4 ){
assert( db );
switch( p4type ){
case P4_REAL:
case P4_INT64:
case P4_MPRINTF:
case P4_DYNAMIC:
case P4_KEYINFO:
case P4_INTARRAY:
@@ -589,10 +591,14 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
sqlite3DbFree(db, p4);
break;
}
case P4_MPRINTF: {
if( db->pnBytesFreed==0 ) sqlite3_free(p4);
break;
}
case P4_VDBEFUNC: {
VdbeFunc *pVdbeFunc = (VdbeFunc *)p4;
freeEphemeralFunction(db, pVdbeFunc->pFunc);
sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
if( db->pnBytesFreed==0 ) sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
sqlite3DbFree(db, pVdbeFunc);
break;
}
@@ -601,15 +607,17 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
break;
}
case P4_MEM: {
sqlite3ValueFree((sqlite3_value*)p4);
if( db->pnBytesFreed==0 ){
sqlite3ValueFree((sqlite3_value*)p4);
}else{
Mem *p = (Mem*)p4;
sqlite3DbFree(db, p->zMalloc);
sqlite3DbFree(db, p);
}
break;
}
case P4_VTAB : {
sqlite3VtabUnlock((VTable *)p4);
break;
}
case P4_SUBPROGRAM : {
sqlite3VdbeProgramDelete(db, (SubProgram *)p4, 1);
if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4);
break;
}
}
@@ -635,35 +643,15 @@ static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
}
/*
** Decrement the ref-count on the SubProgram structure passed as the
** second argument. If the ref-count reaches zero, free the structure.
**
** The array of VDBE opcodes stored as SubProgram.aOp is freed if
** either the ref-count reaches zero or parameter freeop is non-zero.
**
** Since the array of opcodes pointed to by SubProgram.aOp may directly
** or indirectly contain a reference to the SubProgram structure itself.
** By passing a non-zero freeop parameter, the caller may ensure that all
** SubProgram structures and their aOp arrays are freed, even when there
** are such circular references.
** Link the SubProgram object passed as the second argument into the linked
** list at Vdbe.pSubProgram. This list is used to delete all sub-program
** objects when the VM is no longer required.
*/
void sqlite3VdbeProgramDelete(sqlite3 *db, SubProgram *p, int freeop){
if( p ){
assert( p->nRef>0 );
if( freeop || p->nRef==1 ){
Op *aOp = p->aOp;
p->aOp = 0;
vdbeFreeOpArray(db, aOp, p->nOp);
p->nOp = 0;
}
p->nRef--;
if( p->nRef==0 ){
sqlite3DbFree(db, p);
}
}
void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){
p->pNext = pVdbe->pProgram;
pVdbe->pProgram = p;
}
/*
** Change N opcodes starting at addr to No-ops.
*/
@@ -739,7 +727,7 @@ void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
nField = ((KeyInfo*)zP4)->nField;
nByte = sizeof(*pKeyInfo) + (nField-1)*sizeof(pKeyInfo->aColl[0]) + nField;
pKeyInfo = sqlite3Malloc( nByte );
pKeyInfo = sqlite3DbMallocRaw(0, nByte);
pOp->p4.pKeyInfo = pKeyInfo;
if( pKeyInfo ){
u8 *aSortOrder;
@@ -1003,6 +991,12 @@ static void releaseMemArray(Mem *p, int N){
Mem *pEnd;
sqlite3 *db = p->db;
u8 malloc_failed = db->mallocFailed;
if( db->pnBytesFreed ){
for(pEnd=&p[N]; p<pEnd; p++){
sqlite3DbFree(db, p->zMalloc);
}
return;
}
for(pEnd=&p[N]; p<pEnd; p++){
assert( (&p[1])==pEnd || p[0].db==p[1].db );
@@ -1652,9 +1646,6 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
** to the transaction.
*/
rc = sqlite3VtabSync(db, &p->zErrMsg);
if( rc!=SQLITE_OK ){
return rc;
}
/* This loop determines (a) if the commit hook should be invoked and
** (b) how many database files have open write transactions, not
@@ -1662,13 +1653,17 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
** one database file has an open write transaction, a master journal
** file is required for an atomic commit.
*/
for(i=0; i<db->nDb; i++){
for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
Btree *pBt = db->aDb[i].pBt;
if( sqlite3BtreeIsInTrans(pBt) ){
needXcommit = 1;
if( i!=1 ) nTrans++;
rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt));
}
}
if( rc!=SQLITE_OK ){
return rc;
}
/* If there are any write-transactions at all, invoke the commit hook */
if( needXcommit && db->xCommitCallback ){
@@ -1807,6 +1802,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
}
}
sqlite3OsCloseFree(pMaster);
assert( rc!=SQLITE_BUSY );
if( rc!=SQLITE_OK ){
sqlite3DbFree(db, zMaster);
return rc;
@@ -2065,8 +2061,17 @@ int sqlite3VdbeHalt(Vdbe *p){
isSpecialError = mrc==SQLITE_NOMEM || mrc==SQLITE_IOERR
|| mrc==SQLITE_INTERRUPT || mrc==SQLITE_FULL;
if( isSpecialError ){
/* If the query was read-only, we need do no rollback at all. Otherwise,
** proceed with the special handling.
/* If the query was read-only and the error code is SQLITE_INTERRUPT,
** no rollback is necessary. Otherwise, at least a savepoint
** transaction must be rolled back to restore the database to a
** consistent state.
**
** Even if the statement is read-only, it is important to perform
** a statement or transaction rollback operation. If the error
** occured while writing to the journal, sub-journal or database
** file as part of an effort to free up cache space (see function
** pagerStress() in pager.c), the rollback is required to restore
** the pager to a consistent state.
*/
if( !p->readOnly || mrc!=SQLITE_INTERRUPT ){
if( (mrc==SQLITE_NOMEM || mrc==SQLITE_FULL) && p->usesStmtJournal ){
@@ -2335,6 +2340,30 @@ void sqlite3VdbeDeleteAuxData(VdbeFunc *pVdbeFunc, int mask){
}
}
/*
** Free all memory associated with the Vdbe passed as the second argument.
** The difference between this function and sqlite3VdbeDelete() is that
** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with
** the database connection.
*/
void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
SubProgram *pSub, *pNext;
assert( p->db==0 || p->db==db );
releaseMemArray(p->aVar, p->nVar);
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
for(pSub=p->pProgram; pSub; pSub=pNext){
pNext = pSub->pNext;
vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
sqlite3DbFree(db, pSub);
}
vdbeFreeOpArray(db, p->aOp, p->nOp);
sqlite3DbFree(db, p->aLabel);
sqlite3DbFree(db, p->aColName);
sqlite3DbFree(db, p->zSql);
sqlite3DbFree(db, p->pFree);
sqlite3DbFree(db, p);
}
/*
** Delete an entire VDBE.
*/
@@ -2352,16 +2381,9 @@ void sqlite3VdbeDelete(Vdbe *p){
if( p->pNext ){
p->pNext->pPrev = p->pPrev;
}
releaseMemArray(p->aVar, p->nVar);
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
vdbeFreeOpArray(db, p->aOp, p->nOp);
sqlite3DbFree(db, p->aLabel);
sqlite3DbFree(db, p->aColName);
sqlite3DbFree(db, p->zSql);
p->magic = VDBE_MAGIC_DEAD;
sqlite3DbFree(db, p->pFree);
p->db = 0;
sqlite3DbFree(db, p);
sqlite3VdbeDeleteObject(db, p);
}
/*
@@ -2387,11 +2409,8 @@ int sqlite3VdbeCursorMoveto(VdbeCursor *p){
rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
if( rc ) return rc;
p->lastRowid = p->movetoTarget;
p->rowidIsValid = ALWAYS(res==0) ?1:0;
if( NEVER(res<0) ){
rc = sqlite3BtreeNext(p->pCursor, &res);
if( rc ) return rc;
}
if( res!=0 ) return SQLITE_CORRUPT_BKPT;
p->rowidIsValid = 1;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
+1 -1
View File
@@ -1016,7 +1016,7 @@ int sqlite3ValueFromExpr(
}
op = pExpr->op;
/* op can only be TK_REGISTER is we have compiled with SQLITE_ENABLE_STAT2.
/* op can only be TK_REGISTER if we have compiled with SQLITE_ENABLE_STAT2.
** The ifdef here is to enable us to achieve 100% branch test coverage even
** when SQLITE_ENABLE_STAT2 is omitted.
*/
+8 -9
View File
@@ -221,14 +221,14 @@ void sqlite3VtabUnlockList(sqlite3 *db){
** in the list are moved to the sqlite3.pDisconnect list of the associated
** database connection.
*/
void sqlite3VtabClear(Table *p){
vtabDisconnectAll(0, p);
void sqlite3VtabClear(sqlite3 *db, Table *p){
if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
if( p->azModuleArg ){
int i;
for(i=0; i<p->nModuleArg; i++){
sqlite3DbFree(p->dbMem, p->azModuleArg[i]);
sqlite3DbFree(db, p->azModuleArg[i]);
}
sqlite3DbFree(p->dbMem, p->azModuleArg);
sqlite3DbFree(db, p->azModuleArg);
}
}
@@ -393,7 +393,6 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */
return;
}
pSchema->db = pParse->db;
pParse->pNewTable = 0;
}
}
@@ -467,7 +466,7 @@ static int vtabCallConstructor(
*pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName);
}else {
*pzErr = sqlite3MPrintf(db, "%s", zErr);
sqlite3DbFree(db, zErr);
sqlite3_free(zErr);
}
sqlite3DbFree(db, pVTable);
}else if( ALWAYS(pVTable->pVtab) ){
@@ -682,7 +681,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
if( pParse->pVdbe ){
sqlite3VdbeFinalize(pParse->pVdbe);
}
sqlite3DeleteTable(pParse->pNewTable);
sqlite3DeleteTable(db, pParse->pNewTable);
sqlite3StackFree(db, pParse);
}
@@ -769,8 +768,8 @@ int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
if( pVtab && (x = pVtab->pModule->xSync)!=0 ){
rc = x(pVtab);
sqlite3DbFree(db, *pzErrmsg);
*pzErrmsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
*pzErrmsg = sqlite3DbStrDup(db, pVtab->zErrMsg);
sqlite3_free(pVtab->zErrMsg);
}
}
db->aVTrans = aVTrans;
+64 -17
View File
@@ -292,6 +292,10 @@ typedef struct WalCkptInfo WalCkptInfo;
**
** The actual header in the wal-index consists of two copies of this
** object.
**
** The szPage value can be any power of 2 between 512 and 32768, inclusive.
** Or it can be 1 to represent a 65536-byte page. The latter case was
** added in 3.7.1 when support for 64K pages was added.
*/
struct WalIndexHdr {
u32 iVersion; /* Wal-index version */
@@ -299,7 +303,7 @@ struct WalIndexHdr {
u32 iChange; /* Counter incremented each transaction */
u8 isInit; /* 1 when initialized */
u8 bigEndCksum; /* True if checksums in WAL are big-endian */
u16 szPage; /* Database page size in bytes */
u16 szPage; /* Database page size in bytes. 1==64K */
u32 mxFrame; /* Index of last valid frame in the WAL */
u32 nPage; /* Size of database in pages */
u32 aFrameCksum[2]; /* Checksum of last frame in log */
@@ -410,7 +414,7 @@ struct Wal {
u32 iCallback; /* Value to pass to log callback (or 0) */
int nWiData; /* Size of array apWiData */
volatile u32 **apWiData; /* Pointer to wal-index content in memory */
u16 szPage; /* Database page size */
u32 szPage; /* Database page size */
i16 readLock; /* Which read lock is being held. -1 for none */
u8 exclusiveMode; /* Non-zero if connection is in exclusive mode */
u8 writeLock; /* True if in a write transaction */
@@ -1081,7 +1085,7 @@ static int walIndexRecover(Wal *pWal){
goto finished;
}
pWal->hdr.bigEndCksum = (u8)(magic&0x00000001);
pWal->szPage = (u16)szPage;
pWal->szPage = szPage;
pWal->nCkpt = sqlite3Get4byte(&aBuf[12]);
memcpy(&pWal->hdr.aSalt, &aBuf[16], 8);
@@ -1131,7 +1135,9 @@ static int walIndexRecover(Wal *pWal){
if( nTruncate ){
pWal->hdr.mxFrame = iFrame;
pWal->hdr.nPage = nTruncate;
pWal->hdr.szPage = (u16)szPage;
pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
testcase( szPage<=32768 );
testcase( szPage>=65536 );
aFrameCksum[0] = pWal->hdr.aFrameCksum[0];
aFrameCksum[1] = pWal->hdr.aFrameCksum[1];
}
@@ -1156,6 +1162,17 @@ finished:
pInfo->nBackfill = 0;
pInfo->aReadMark[0] = 0;
for(i=1; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
/* If more than one frame was recovered from the log file, report an
** event via sqlite3_log(). This is to help with identifying performance
** problems caused by applications routinely shutting down without
** checkpointing the log file.
*/
if( pWal->hdr.nPage ){
sqlite3_log(SQLITE_OK, "Recovered %d frames from WAL file %s",
pWal->hdr.nPage, pWal->zWalName
);
}
}
recovery_error:
@@ -1516,14 +1533,18 @@ static int walCheckpoint(
u8 *zBuf /* Temporary buffer to use */
){
int rc; /* Return code */
int szPage = pWal->hdr.szPage; /* Database page-size */
int szPage; /* Database page-size */
WalIterator *pIter = 0; /* Wal iterator context */
u32 iDbpage = 0; /* Next database page to write */
u32 iFrame = 0; /* Wal frame containing data for iDbpage */
u32 mxSafeFrame; /* Max frame that can be backfilled */
u32 mxPage; /* Max database page to write */
int i; /* Loop counter */
volatile WalCkptInfo *pInfo; /* The checkpoint status information */
szPage = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
testcase( szPage<=32768 );
testcase( szPage>=65536 );
if( pWal->hdr.mxFrame==0 ) return SQLITE_OK;
/* Allocate the iterator */
@@ -1534,7 +1555,7 @@ static int walCheckpoint(
assert( pIter );
/*** TODO: Move this test out to the caller. Make it an assert() here ***/
if( pWal->hdr.szPage!=nBuf ){
if( szPage!=nBuf ){
rc = SQLITE_CORRUPT_BKPT;
goto walcheckpoint_out;
}
@@ -1545,6 +1566,7 @@ static int walCheckpoint(
** cannot be backfilled from the WAL.
*/
mxSafeFrame = pWal->hdr.mxFrame;
mxPage = pWal->hdr.nPage;
pInfo = walCkptInfo(pWal);
for(i=1; i<WAL_NREADER; i++){
u32 y = pInfo->aReadMark[i];
@@ -1565,6 +1587,7 @@ static int walCheckpoint(
if( pInfo->nBackfill<mxSafeFrame
&& (rc = walLockExclusive(pWal, WAL_READ_LOCK(0), 1))==SQLITE_OK
){
i64 nSize; /* Current size of database file */
u32 nBackfill = pInfo->nBackfill;
/* Sync the WAL to disk */
@@ -1572,11 +1595,22 @@ static int walCheckpoint(
rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
}
/* If the database file may grow as a result of this checkpoint, hint
** about the eventual size of the db file to the VFS layer.
*/
if( rc==SQLITE_OK ){
i64 nReq = ((i64)mxPage * szPage);
rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
if( rc==SQLITE_OK && nSize<nReq ){
sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
}
}
/* Iterate through the contents of the WAL, copying data to the db file. */
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
i64 iOffset;
assert( walFramePgno(pWal, iFrame)==iDbpage );
if( iFrame<=nBackfill || iFrame>mxSafeFrame ) continue;
if( iFrame<=nBackfill || iFrame>mxSafeFrame || iDbpage>mxPage ) continue;
iOffset = walFrameOffset(iFrame, szPage) + WAL_FRAME_HDRSIZE;
/* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL file */
rc = sqlite3OsRead(pWal->pWalFd, zBuf, szPage, iOffset);
@@ -1683,7 +1717,7 @@ static int walIndexTryHdr(Wal *pWal, int *pChanged){
/* The first page of the wal-index must be mapped at this point. */
assert( pWal->nWiData>0 && pWal->apWiData[0] );
/* Read the header. This might happen currently with a write to the
/* Read the header. This might happen concurrently with a write to the
** same area of shared memory on a different CPU in a SMP,
** meaning it is possible that an inconsistent snapshot is read
** from the file. If this happens, return non-zero.
@@ -1712,7 +1746,9 @@ static int walIndexTryHdr(Wal *pWal, int *pChanged){
if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){
*pChanged = 1;
memcpy(&pWal->hdr, &h1, sizeof(WalIndexHdr));
pWal->szPage = pWal->hdr.szPage;
pWal->szPage = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
testcase( pWal->szPage<=32768 );
testcase( pWal->szPage>=65536 );
}
/* The header was successfully read. Return zero. */
@@ -2031,6 +2067,7 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
** read-lock.
*/
void sqlite3WalEndReadTransaction(Wal *pWal){
sqlite3WalEndWriteTransaction(pWal);
if( pWal->readLock>=0 ){
walUnlockShared(pWal, WAL_READ_LOCK(pWal->readLock));
pWal->readLock = -1;
@@ -2141,7 +2178,13 @@ int sqlite3WalRead(
** required page. Read and return data from the log file.
*/
if( iRead ){
i64 iOffset = walFrameOffset(iRead, pWal->hdr.szPage) + WAL_FRAME_HDRSIZE;
int sz;
i64 iOffset;
sz = pWal->hdr.szPage;
sz = (pWal->hdr.szPage&0xfe00) + ((pWal->hdr.szPage&0x0001)<<16);
testcase( sz<=32768 );
testcase( sz>=65536 );
iOffset = walFrameOffset(iRead, sz) + WAL_FRAME_HDRSIZE;
*pInWal = 1;
/* testcase( IS_BIG_INT(iOffset) ); // requires a 4GiB WAL */
return sqlite3OsRead(pWal->pWalFd, pOut, nOut, iOffset);
@@ -2153,11 +2196,13 @@ int sqlite3WalRead(
/*
** Set *pPgno to the size of the database file (or zero, if unknown).
** Return the size of the database in pages (or zero, if unknown).
*/
void sqlite3WalDbsize(Wal *pWal, Pgno *pPgno){
assert( pWal->readLock>=0 || pWal->lockError );
*pPgno = pWal->hdr.nPage;
Pgno sqlite3WalDbsize(Wal *pWal){
if( pWal && ALWAYS(pWal->readLock>=0) ){
return pWal->hdr.nPage;
}
return 0;
}
@@ -2233,7 +2278,7 @@ int sqlite3WalEndWriteTransaction(Wal *pWal){
*/
int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){
int rc = SQLITE_OK;
if( pWal->writeLock ){
if( ALWAYS(pWal->writeLock) ){
Pgno iMax = pWal->hdr.mxFrame;
Pgno iFrame;
@@ -2422,7 +2467,7 @@ int sqlite3WalFrames(
sqlite3Put4byte(&aWalHdr[24], aCksum[0]);
sqlite3Put4byte(&aWalHdr[28], aCksum[1]);
pWal->szPage = (u16)szPage;
pWal->szPage = szPage;
pWal->hdr.bigEndCksum = SQLITE_BIGENDIAN;
pWal->hdr.aFrameCksum[0] = aCksum[0];
pWal->hdr.aFrameCksum[1] = aCksum[1];
@@ -2517,7 +2562,9 @@ int sqlite3WalFrames(
if( rc==SQLITE_OK ){
/* Update the private copy of the header. */
pWal->hdr.szPage = (u16)szPage;
pWal->hdr.szPage = (u16)((szPage&0xff00) | (szPage>>16));
testcase( szPage<=32768 );
testcase( szPage>=65536 );
pWal->hdr.mxFrame = iFrame;
if( isCommit ){
pWal->hdr.iChange++;
+3 -4
View File
@@ -25,7 +25,7 @@
# define sqlite3WalBeginReadTransaction(y,z) 0
# define sqlite3WalEndReadTransaction(z)
# define sqlite3WalRead(v,w,x,y,z) 0
# define sqlite3WalDbsize(y,z)
# define sqlite3WalDbsize(y) 0
# define sqlite3WalBeginWriteTransaction(y) 0
# define sqlite3WalEndWriteTransaction(x) 0
# define sqlite3WalUndo(x,y,z) 0
@@ -61,9 +61,8 @@ void sqlite3WalEndReadTransaction(Wal *pWal);
/* Read a page from the write-ahead log, if it is present. */
int sqlite3WalRead(Wal *pWal, Pgno pgno, int *pInWal, int nOut, u8 *pOut);
/* Return the size of the database as it existed at the beginning
** of the snapshot */
void sqlite3WalDbsize(Wal *pWal, Pgno *pPgno);
/* If the WAL is not empty, return the size of the database. */
Pgno sqlite3WalDbsize(Wal *pWal);
/* Obtain or release the WRITER lock. */
int sqlite3WalBeginWriteTransaction(Wal *pWal);
+89 -34
View File
@@ -327,6 +327,7 @@ static void whereClauseClear(WhereClause *pWC){
static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
WhereTerm *pTerm;
int idx;
testcase( wtFlags & TERM_VIRTUAL ); /* EV: R-00211-15100 */
if( pWC->nTerm>=pWC->nSlot ){
WhereTerm *pOld = pWC->a;
sqlite3 *db = pWC->pParse->db;
@@ -472,6 +473,13 @@ static Bitmask exprSelectTableUsage(WhereMaskSet *pMaskSet, Select *pS){
** Return TRUE if the given operator is one of the operators that is
** allowed for an indexable WHERE clause term. The allowed operators are
** "=", "<", ">", "<=", ">=", and "IN".
**
** IMPLEMENTATION-OF: R-59926-26393 To be usable by an index a term must be
** of one of the following forms: column = expression column > expression
** column >= expression column < expression column <= expression
** expression = column expression > column expression >= column
** expression < column expression <= column column IN
** (expression-list) column IN (subquery) column IS NULL
*/
static int allowedOp(int op){
assert( TK_GT>TK_EQ && TK_GT<TK_GE );
@@ -635,7 +643,6 @@ static int isLikeOrGlob(
int c; /* One character in z[] */
int cnt; /* Number of non-wildcard prefix characters */
char wc[3]; /* Wildcard characters */
CollSeq *pColl; /* Collating sequence for LHS */
sqlite3 *db = pParse->db; /* Database connection */
sqlite3_value *pVal = 0;
int op; /* Opcode of pRight */
@@ -654,19 +661,6 @@ static int isLikeOrGlob(
return 0;
}
assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */
pColl = sqlite3ExprCollSeq(pParse, pLeft);
if( pColl==0 ) return 0; /* Happens when LHS has an undefined collation */
if( (pColl->type!=SQLITE_COLL_BINARY || *pnoCase) &&
(pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){
/* IMP: R-09003-32046 For the GLOB operator, the column must use the
** default BINARY collating sequence.
** IMP: R-41408-28306 For the LIKE operator, if case_sensitive_like mode
** is enabled then the column must use the default BINARY collating
** sequence, or if case_sensitive_like mode is disabled then the column
** must use the built-in NOCASE collating sequence.
*/
return 0;
}
pRight = pList->a[0].pExpr;
op = pRight->op;
@@ -689,9 +683,9 @@ static int isLikeOrGlob(
while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
cnt++;
}
if( cnt!=0 && c!=0 && 255!=(u8)z[cnt-1] ){
if( cnt!=0 && 255!=(u8)z[cnt-1] ){
Expr *pPrefix;
*pisComplete = z[cnt]==wc[0] && z[cnt+1]==0;
*pisComplete = c==wc[0] && z[cnt+1]==0;
pPrefix = sqlite3Expr(db, TK_STRING, z);
if( pPrefix ) pPrefix->u.zToken[cnt] = 0;
*ppPrefix = pPrefix;
@@ -1030,6 +1024,8 @@ static void exprAnalyzeOrTerm(
/* At this point, okToChngToIN is true if original pTerm satisfies
** case 1. In that case, construct a new virtual term that is
** pTerm converted into an IN operator.
**
** EV: R-00211-15100
*/
if( okToChngToIN ){
Expr *pDup; /* A transient duplicate expression */
@@ -1246,6 +1242,7 @@ static void exprAnalyze(
Expr *pNewExpr2;
int idxNew1;
int idxNew2;
CollSeq *pColl; /* Collating sequence to use */
pLeft = pExpr->x.pList->a[1].pExpr;
pStr2 = sqlite3ExprDup(db, pStr1, 0);
@@ -1260,17 +1257,23 @@ static void exprAnalyze(
** inequality. To avoid this, make sure to also run the full
** LIKE on all candidate expressions by clearing the isComplete flag
*/
if( c=='A'-1 ) isComplete = 0;
if( c=='A'-1 ) isComplete = 0; /* EV: R-64339-08207 */
c = sqlite3UpperToLower[c];
}
*pC = c + 1;
}
pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft,0),pStr1,0);
pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, noCase ? "NOCASE" : "BINARY",0);
pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
pStr1, 0);
idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew1==0 );
exprAnalyze(pSrc, pWC, idxNew1);
pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprDup(db,pLeft,0),pStr2,0);
pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
sqlite3ExprSetColl(sqlite3ExprDup(db,pLeft,0), pColl),
pStr2, 0);
idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew2==0 );
exprAnalyze(pSrc, pWC, idxNew2);
@@ -2022,7 +2025,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg);
}
}
sqlite3DbFree(pParse->db, pVtab->zErrMsg);
sqlite3_free(pVtab->zErrMsg);
pVtab->zErrMsg = 0;
for(i=0; i<p->nConstraint; i++){
@@ -2887,6 +2890,9 @@ static void bestIndex(
** in the ON clause. The term is disabled in (3) because it is not part
** of a LEFT OUTER JOIN. In (1), the term is not disabled.
**
** IMPLEMENTATION-OF: R-24597-58655 No tests are done for terms that are
** completely satisfied by indices.
**
** Disabling a term causes that term to not be tested in the inner loop
** of the join. Disabling is an optimization. When terms are satisfied
** by indices, we disable them to prevent redundant tests in the inner
@@ -3098,6 +3104,7 @@ static int codeAllEqualityTerms(
/* The following true for indices with redundant columns.
** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
if( r1!=regBase+j ){
if( nReg==1 ){
@@ -3241,6 +3248,7 @@ static Bitmask codeOneLoopStart(
assert( pTerm->pExpr!=0 );
assert( pTerm->leftCursor==iCur );
assert( omitTable==0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg);
addrNxt = pLevel->addrNxt;
sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
@@ -3281,6 +3289,7 @@ static Bitmask codeOneLoopStart(
assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */
assert( TK_GE==TK_GT+3 ); /* ... is correcct. */
testcase( pStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
pX = pStart->pExpr;
assert( pX!=0 );
assert( pStart->leftCursor==iCur );
@@ -3298,6 +3307,7 @@ static Bitmask codeOneLoopStart(
pX = pEnd->pExpr;
assert( pX!=0 );
assert( pEnd->leftCursor==iCur );
testcase( pEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
memEndValue = ++pParse->nMem;
sqlite3ExprCode(pParse, pX->pRight, memEndValue);
if( pX->op==TK_LT || pX->op==TK_GT ){
@@ -3355,7 +3365,7 @@ static Bitmask codeOneLoopStart(
** constraints but an index is selected anyway, in order
** to force the output order to conform to an ORDER BY.
*/
int aStartOp[] = {
static const u8 aStartOp[] = {
0,
0,
OP_Rewind, /* 2: (!start_constraints && startEq && !bRev) */
@@ -3365,12 +3375,12 @@ static Bitmask codeOneLoopStart(
OP_SeekGe, /* 6: (start_constraints && startEq && !bRev) */
OP_SeekLe /* 7: (start_constraints && startEq && bRev) */
};
int aEndOp[] = {
static const u8 aEndOp[] = {
OP_Noop, /* 0: (!end_constraints) */
OP_IdxGE, /* 1: (end_constraints && !bRev) */
OP_IdxLT /* 2: (end_constraints && bRev) */
};
int nEq = pLevel->plan.nEq;
int nEq = pLevel->plan.nEq; /* Number of == or IN terms */
int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */
int regBase; /* Base register holding constraint values */
int r1; /* Temp register */
@@ -3380,10 +3390,10 @@ static Bitmask codeOneLoopStart(
int endEq; /* True if range end uses ==, >= or <= */
int start_constraints; /* Start of range is constrained */
int nConstraint; /* Number of constraint terms */
Index *pIdx; /* The index we will be using */
int iIdxCur; /* The VDBE cursor for the index */
int nExtraReg = 0; /* Number of extra registers needed */
int op; /* Instruction opcode */
Index *pIdx; /* The index we will be using */
int iIdxCur; /* The VDBE cursor for the index */
int nExtraReg = 0; /* Number of extra registers needed */
int op; /* Instruction opcode */
char *zStartAff; /* Affinity for start of range constraint */
char *zEndAff; /* Affinity for end of range constraint */
@@ -3465,6 +3475,7 @@ static Bitmask codeOneLoopStart(
}
}
nConstraint++;
testcase( pRangeStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
}else if( isMinQuery ){
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
nConstraint++;
@@ -3504,6 +3515,7 @@ static Bitmask codeOneLoopStart(
}
codeApplyAffinity(pParse, regBase, nEq+1, zEndAff);
nConstraint++;
testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
}
sqlite3DbFree(pParse->db, zStartAff);
sqlite3DbFree(pParse->db, zEndAff);
@@ -3710,11 +3722,15 @@ static Bitmask codeOneLoopStart(
/* Insert code to test every subexpression that can be completely
** computed using the current set of tables.
**
** IMPLEMENTATION-OF: R-49525-50935 Terms that cannot be satisfied through
** the use of indices become tests that are evaluated against each row of
** the relevant input tables.
*/
k = 0;
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
Expr *pE;
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & notReady)!=0 ){
@@ -3742,7 +3758,7 @@ static Bitmask codeOneLoopStart(
VdbeComment((v, "record LEFT JOIN hit"));
sqlite3ExprCacheClear(pParse);
for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
if( (pTerm->prereqAll & notReady)!=0 ){
@@ -3960,7 +3976,7 @@ WhereInfo *sqlite3WhereBegin(
initMaskSet(pMaskSet);
whereClauseInit(pWC, pParse, pMaskSet);
sqlite3ExprCodeConstants(pParse, pWhere);
whereSplit(pWC, pWhere, TK_AND);
whereSplit(pWC, pWhere, TK_AND); /* IMP: R-15842-53296 */
/* Special case: a WHERE clause that is constant. Evaluate the
** expression and either jump over all of the code or fall thru.
@@ -4048,6 +4064,8 @@ WhereInfo *sqlite3WhereBegin(
int bestJ = -1; /* The value of j */
Bitmask m; /* Bitmask value for j or bestJ */
int isOptimal; /* Iterator for optimal/non-optimal search */
int nUnconstrained; /* Number tables without INDEXED BY */
Bitmask notIndexed; /* Mask of tables that cannot use an index */
memset(&bestPlan, 0, sizeof(bestPlan));
bestPlan.rCost = SQLITE_BIG_DBL;
@@ -4089,8 +4107,10 @@ WhereInfo *sqlite3WhereBegin(
** algorithm may choose to use t2 for the outer loop, which is a much
** costlier approach.
*/
nUnconstrained = 0;
notIndexed = 0;
for(isOptimal=(iFrom<nTabList-1); isOptimal>=0; isOptimal--){
Bitmask mask; /* Mask of tables not yet ready */
Bitmask mask; /* Mask of tables not yet ready */
for(j=iFrom, pTabItem=&pTabList->a[j]; j<nTabList; j++, pTabItem++){
int doNotReorder; /* True if this table should not be reordered */
WhereCost sCost; /* Cost information from best[Virtual]Index() */
@@ -4105,6 +4125,7 @@ WhereInfo *sqlite3WhereBegin(
}
mask = (isOptimal ? m : notReady);
pOrderBy = ((i==0 && ppOrderBy )?*ppOrderBy:0);
if( pTabItem->pIndex==0 ) nUnconstrained++;
assert( pTabItem->pTab );
#ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -4118,9 +4139,43 @@ WhereInfo *sqlite3WhereBegin(
}
assert( isOptimal || (sCost.used&notReady)==0 );
if( (sCost.used&notReady)==0
&& (bestJ<0 || sCost.rCost<bestPlan.rCost
|| (sCost.rCost<=bestPlan.rCost && sCost.nRow<bestPlan.nRow))
/* If an INDEXED BY clause is present, then the plan must use that
** index if it uses any index at all */
assert( pTabItem->pIndex==0
|| (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0
|| sCost.plan.u.pIdx==pTabItem->pIndex );
if( isOptimal && (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){
notIndexed |= m;
}
/* Conditions under which this table becomes the best so far:
**
** (1) The table must not depend on other tables that have not
** yet run.
**
** (2) A full-table-scan plan cannot supercede another plan unless
** it is an "optimal" plan as defined above.
**
** (3) All tables have an INDEXED BY clause or this table lacks an
** INDEXED BY clause or this table uses the specific
** index specified by its INDEXED BY clause. This rule ensures
** that a best-so-far is always selected even if an impossible
** combination of INDEXED BY clauses are given. The error
** will be detected and relayed back to the application later.
** The NEVER() comes about because rule (2) above prevents
** An indexable full-table-scan from reaching rule (3).
**
** (4) The plan cost must be lower than prior plans or else the
** cost must be the same and the number of rows must be lower.
*/
if( (sCost.used&notReady)==0 /* (1) */
&& (bestJ<0 || (notIndexed&m)!=0 /* (2) */
|| (sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)
&& (nUnconstrained==0 || pTabItem->pIndex==0 /* (3) */
|| NEVER((sCost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
&& (bestJ<0 || sCost.rCost<bestPlan.rCost /* (4) */
|| (sCost.rCost<=bestPlan.rCost && sCost.nRow<bestPlan.nRow))
){
WHERETRACE(("... best so far with cost=%g and nRow=%g\n",
sCost.rCost, sCost.nRow));
+16 -1
View File
@@ -268,6 +268,22 @@ do_test analyze3-2.5 {
set like "%a"
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
} {999 999 100}
do_test analyze3-2.6 {
set like "a"
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
} {101 0 0}
do_test analyze3-2.7 {
set like "ab"
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
} {11 0 0}
do_test analyze3-2.8 {
set like "abc"
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
} {2 0 1}
do_test analyze3-2.9 {
set like "a_c"
sf_execsql { SELECT count(*) FROM t1 WHERE b LIKE $like }
} {101 0 10}
#-------------------------------------------------------------------------
@@ -387,7 +403,6 @@ do_test analyze3-3.6.5 {
} {SQLITE_OK}
do_test analyze3-3.7.1 {
breakpoint
set S [sqlite3_prepare_v2 db {
SELECT * FROM t1 WHERE a IN (
?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?33,
+274
View File
@@ -0,0 +1,274 @@
# 2010 August 19
#
# 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 that the current version of SQLite
# is capable of reading and writing databases created by previous
# versions, and vice-versa.
#
# To use this test, old versions of the testfixture process should be
# copied into the working directory alongside the new version. The old
# versions should be named "testfixtureXXX" (or testfixtureXXX.exe on
# windows), where XXX can be any string.
#
# This test file uses the tcl code for controlling a second testfixture
# process located in lock_common.tcl. See the commments in lock_common.tcl
# for documentation of the available commands.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
db close
# Search for binaries to test against. Any executable files that match
# our naming convention are assumed to be testfixture binaries to test
# against.
#
set binaries [list]
set pattern "[file tail [info nameofexec]]?*"
if {$tcl_platform(platform)=="windows"} {
set pattern [string map {\.exe {}} $pattern]
}
foreach file [glob -nocomplain $pattern] {
if {[file executable $file]} {lappend binaries $file}
}
if {[llength $binaries]==0} {
puts "WARNING: No historical binaries to test against."
puts "WARNING: No backwards-compatibility tests have been run."
finish_test
return
}
proc get_version {binary} {
set chan [launch_testfixture $binary]
set v [testfixture $chan { sqlite3 -version }]
close $chan
set v
}
foreach bin $binaries {
puts -nonewline "Testing against $bin - "
flush stdout
puts "version [get_version $bin]"
}
proc do_backcompat_test {rv bin1 bin2 script} {
file delete -force test.db
if {$bin1 != ""} { set ::bc_chan1 [launch_testfixture $bin1] }
set ::bc_chan2 [launch_testfixture $bin2]
if { $rv } {
proc code2 {tcl} { uplevel #0 $tcl }
if {$bin1 != ""} { proc code2 {tcl} { testfixture $::bc_chan1 $tcl } }
proc code1 {tcl} { testfixture $::bc_chan2 $tcl }
} else {
proc code1 {tcl} { uplevel #0 $tcl }
if {$bin1 != ""} { proc code1 {tcl} { testfixture $::bc_chan1 $tcl } }
proc code2 {tcl} { testfixture $::bc_chan2 $tcl }
}
proc sql1 sql { code1 [list db eval $sql] }
proc sql2 sql { code2 [list db eval $sql] }
code1 { sqlite3 db test.db }
code2 { sqlite3 db test.db }
uplevel $script
catch { code1 { db close } }
catch { code2 { db close } }
catch { close $::bc_chan2 }
catch { close $::bc_chan1 }
}
array set ::incompatible [list]
proc do_allbackcompat_test {script} {
foreach bin $::binaries {
set nErr [set_test_counter errors]
foreach dir {0 1} {
set bintag [string map {testfixture {}} $bin]
set bintag [string map {\.exe {}} $bintag]
if {$bintag == ""} {set bintag self}
set ::bcname ".$bintag.$dir."
rename do_test _do_test
proc do_test {nm sql res} {
set nm [regsub {\.} $nm $::bcname]
uplevel [list _do_test $nm $sql $res]
}
do_backcompat_test $dir {} $bin $script
rename do_test {}
rename _do_test do_test
}
if { $nErr < [set_test_counter errors] } {
set ::incompatible([get_version $bin]) 1
}
}
}
proc read_file {zFile} {
set zData {}
if {[file exists $zFile]} {
set fd [open $zFile]
fconfigure $fd -translation binary -encoding binary
if {[file size $zFile]<=$::sqlite_pending_byte || $zFile != "test.db"} {
set zData [read $fd]
} else {
set zData [read $fd $::sqlite_pending_byte]
append zData [string repeat x 512]
seek $fd [expr $::sqlite_pending_byte+512] start
append zData [read $fd]
}
close $fd
}
return $zData
}
proc write_file {zFile zData} {
set fd [open $zFile w]
fconfigure $fd -translation binary -encoding binary
puts -nonewline $fd $zData
close $fd
}
proc read_file_system {} {
set ret [list]
foreach f {test.db test.db-journal test.db-wal} { lappend ret [read_file $f] }
set ret
}
proc write_file_system {data} {
foreach f {test.db test.db-journal test.db-wal} d $data {
if {[string length $d] == 0} {
file delete -force $f
} else {
write_file $f $d
}
}
}
#-------------------------------------------------------------------------
# Actual tests begin here.
#
# This first block of tests checks to see that the same database and
# journal files can be used by old and new versions. WAL and wal-index
# files are tested separately below.
#
do_allbackcompat_test {
# Test that database files are backwards compatible.
#
do_test backcompat-1.1.1 { sql1 {
CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
INSERT INTO t1 VALUES('abc', 'def');
} } {}
do_test backcompat-1.1.2 { sql2 { SELECT * FROM t1; } } {abc def}
do_test backcompat-1.1.3 { sql2 { INSERT INTO t1 VALUES('ghi', 'jkl'); } } {}
do_test backcompat-1.1.4 { sql1 { SELECT * FROM t1; } } {abc def ghi jkl}
do_test backcompat-1.1.5 { sql1 { PRAGMA integrity_check } } {ok}
do_test backcompat-1.1.6 { sql2 { PRAGMA integrity_check } } {ok}
# Test that one version can roll back a hot-journal file left in the
# file-system by the other version.
#
# Each test case is named "backcompat-1.X...", where X is either 0 or
# 1. If it is 0, then the current version creates a journal file that
# the old versions try to read. Otherwise, if X is 1, then the old version
# creates the journal file and we try to read it with the current version.
#
do_test backcompat-1.2.1 { sql1 {
PRAGMA cache_size = 10;
BEGIN;
INSERT INTO t1 VALUES(randomblob(400), randomblob(400));
INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1;
INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1;
INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1;
INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM t1;
COMMIT;
} } {}
set cksum1 [sql1 {SELECT md5sum(a), md5sum(b) FROM t1}]
set cksum2 [sql2 {SELECT md5sum(a), md5sum(b) FROM t1}]
do_test backcompat-1.2.2 [list string compare $cksum1 $cksum2] 0
do_test backcompat-1.2.3 { sql1 {
BEGIN;
UPDATE t1 SET a = randomblob(500);
} } {}
set data [read_file_system]
do_test backcompat-1.2.4 { sql1 { COMMIT } } {}
set same [expr {[sql2 {SELECT md5sum(a), md5sum(b) FROM t1}] == $cksum2}]
do_test backcompat-1.2.5 [list set {} $same] 0
code1 { db close }
code2 { db close }
write_file_system $data
code1 { sqlite3 db test.db }
code2 { sqlite3 db test.db }
set same [expr {[sql2 {SELECT md5sum(a), md5sum(b) FROM t1}] == $cksum2}]
do_test backcompat-1.2.6 [list set {} $same] 1
do_test backcompat-1.2.7 { sql1 { PRAGMA integrity_check } } {ok}
do_test backcompat-1.2.8 { sql2 { PRAGMA integrity_check } } {ok}
}
foreach k [lsort [array names ::incompatible]] {
puts "ERROR: Detected journal incompatibility with version $k"
}
unset ::incompatible
#-------------------------------------------------------------------------
# Test that WAL and wal-index files may be shared between different
# SQLite versions.
#
do_allbackcompat_test {
if {[code1 {sqlite3 -version}] >= "3.7.0"
&& [code2 {sqlite3 -version}] >= "3.7.0"
} {
do_test backcompat-2.1.1 { sql1 {
PRAGMA journal_mode = WAL;
CREATE TABLE t1(a PRIMARY KEY, b UNIQUE);
INSERT INTO t1 VALUES('I', 1);
INSERT INTO t1 VALUES('II', 2);
INSERT INTO t1 VALUES('III', 3);
SELECT * FROM t1;
} } {wal I 1 II 2 III 3}
do_test backcompat-2.1.2 { sql2 {
SELECT * FROM t1;
} } {I 1 II 2 III 3}
set data [read_file_system]
code1 {db close}
code2 {db close}
write_file_system $data
code1 {sqlite3 db test.db}
code2 {sqlite3 db test.db}
# The WAL file now in the file-system was created by the [code1]
# process. Check that the [code2] process can recover the log.
#
do_test backcompat-2.1.3 { sql2 {
SELECT * FROM t1;
} } {I 1 II 2 III 3}
do_test backcompat-2.1.4 { sql1 {
SELECT * FROM t1;
} } {I 1 II 2 III 3}
}
}
finish_test
+22
View File
@@ -789,4 +789,26 @@ do_test conflict-12.4 {
} {2 one}
# Ticket [c38baa3d969eab7946dc50ba9d9b4f0057a19437]
# REPLACE works like ABORT on a CHECK constraint.
#
do_test conflict-13.1 {
execsql {
CREATE TABLE t13(a CHECK(a!=2));
BEGIN;
REPLACE INTO t13 VALUES(1);
}
catchsql {
REPLACE INTO t13 VALUES(2);
}
} {1 {constraint failed}}
do_test conflict-13.2 {
execsql {
REPLACE INTO t13 VALUES(3);
COMMIT;
SELECT * FROM t13;
}
} {1 3}
finish_test
+298 -1
View File
@@ -33,7 +33,7 @@ do_test dbstatus-1.1 {
set sz2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1]
set ::PAGESZ [expr {$sz2-$sz1}]
set ::BASESZ [expr {$sz1-$::PAGESZ}]
expr {$::PAGESZ>1024 && $::PAGESZ<1200}
expr {$::PAGESZ>1024 && $::PAGESZ<1300}
} {1}
do_test dbstatus-1.2 {
db eval {
@@ -42,4 +42,301 @@ do_test dbstatus-1.2 {
lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1
} [expr {$BASESZ + 10*$PAGESZ}]
proc lookaside {db} {
expr { $::lookaside_buffer_size *
[lindex [sqlite3_db_status $db SQLITE_DBSTATUS_LOOKASIDE_USED 0] 1]
}
}
#---------------------------------------------------------------------------
# Run the dbstatus-2 and dbstatus-3 tests with several of different
# lookaside buffer sizes.
#
foreach ::lookaside_buffer_size {0 64 120} {
# Do not run any of these tests if there is SQL configured to run
# as part of the [sqlite3] command. This prevents the script from
# configuring the size of the lookaside buffer after [sqlite3] has
# returned.
if {[presql] != ""} break
#-------------------------------------------------------------------------
# Tests for SQLITE_DBSTATUS_SCHEMA_USED.
#
# Each test in the following block works as follows. Each test uses a
# different database schema.
#
# 1. Open a connection to an empty database. Disable statement caching.
#
# 2. Execute the SQL to create the database schema. Measure the total
# heap and lookaside memory allocated by SQLite, and the memory
# allocated for the database schema according to sqlite3_db_status().
#
# 3. Drop all tables in the database schema. Measure the total memory
# and the schema memory again.
#
# 4. Repeat step 2.
#
# 5. Repeat step 3.
#
# Then test that:
#
# a) The difference in schema memory quantities in steps 2 and 3 is the
# same as the difference in total memory in steps 2 and 3.
#
# b) Step 4 reports the same amount of schema and total memory used as
# in step 2.
#
# c) Step 5 reports the same amount of schema and total memory used as
# in step 3.
#
foreach {tn schema} {
1 { CREATE TABLE t1(a, b) }
2 { CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1, c UNIQUE) }
3 {
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a, b);
}
4 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(c, d);
CREATE TRIGGER AFTER INSERT ON t1 BEGIN
INSERT INTO t2 VALUES(new.a, new.b);
SELECT * FROM t1, t2 WHERE a=c AND b=d GROUP BY b HAVING a>5 ORDER BY a;
END;
}
5 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(c, d);
CREATE VIEW v1 AS SELECT * FROM t1 UNION SELECT * FROM t2;
}
6 {
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a);
CREATE INDEX i2 ON t1(a,b);
CREATE INDEX i3 ON t1(b,b);
INSERT INTO t1 VALUES(randomblob(20), randomblob(25));
INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
ANALYZE;
}
7 {
CREATE TABLE t1(a, b);
CREATE TABLE t2(c, d);
CREATE VIEW v1 AS
SELECT * FROM t1
UNION
SELECT * FROM t2
UNION ALL
SELECT c||b, d||a FROM t2 LEFT OUTER JOIN t1 GROUP BY c, d
ORDER BY 1, 2
;
CREATE TRIGGER tr1 INSTEAD OF INSERT ON v1 BEGIN
SELECT * FROM v1;
UPDATE t1 SET a=5, b=(SELECT c FROM t2);
END;
SELECT * FROM v1;
}
8x {
CREATE TABLE t1(a, b, UNIQUE(a, b));
CREATE VIRTUAL TABLE t2 USING echo(t1);
}
} {
set tn "$::lookaside_buffer_size-$tn"
# Step 1.
db close
file delete -force test.db
sqlite3 db test.db
sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
db cache size 0
catch { register_echo_module db }
ifcapable !vtab { if {[string match *x $tn]} continue }
# Step 2.
execsql $schema
set nAlloc1 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc1 [lookaside db]
set nSchema1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
# Step 3.
drop_all_tables
set nAlloc2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc2 [lookaside db]
set nSchema2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
# Step 4.
execsql $schema
set nAlloc3 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc3 [lookaside db]
set nSchema3 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
# Step 5.
drop_all_tables
set nAlloc4 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc4 [lookaside db]
set nSchema4 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
set nFree [expr {$nAlloc1-$nAlloc2}]
# Tests for which the test name ends in an "x" report slightly less
# memory than is actually freed when all schema items are finalized.
# This is because memory allocated by virtual table implementations
# for any reason is not counted as "schema memory".
#
# Additionally, in auto-vacuum mode, dropping tables and indexes causes
# the page-cache to shrink. So the amount of memory freed is always
# much greater than just that reported by DBSTATUS_SCHEMA_USED in this
# case.
#
if {[string match *x $tn] || $AUTOVACUUM} {
do_test dbstatus-2.$tn.ax { expr {($nSchema1-$nSchema2)<=$nFree} } 1
} else {
do_test dbstatus-2.$tn.a { expr {$nSchema1-$nSchema2} } $nFree
}
do_test dbstatus-2.$tn.b { list $nAlloc1 $nSchema1 } "$nAlloc3 $nSchema3"
do_test dbstatus-2.$tn.c { list $nAlloc2 $nSchema2 } "$nAlloc4 $nSchema4"
}
#-------------------------------------------------------------------------
# Tests for SQLITE_DBSTATUS_STMT_USED.
#
# Each test in the following block works as follows. Each test uses a
# different database schema.
#
# 1. Open a connection to an empty database. Initialized the database
# schema.
#
# 2. Prepare a bunch of SQL statements. Measure the total heap and
# lookaside memory allocated by SQLite, and the memory allocated
# for the prepared statements according to sqlite3_db_status().
#
# 3. Finalize all prepared statements Measure the total memory
# and the prepared statement memory again.
#
# 4. Repeat step 2.
#
# 5. Repeat step 3.
#
# Then test that:
#
# a) The difference in schema memory quantities in steps 2 and 3 is the
# same as the difference in total memory in steps 2 and 3.
#
# b) Step 4 reports the same amount of schema and total memory used as
# in step 2.
#
# c) Step 5 reports the same amount of schema and total memory used as
# in step 3.
#
foreach {tn schema statements} {
1 { CREATE TABLE t1(a, b) } {
SELECT * FROM t1;
INSERT INTO t1 VALUES(1, 2);
INSERT INTO t1 SELECT * FROM t1;
UPDATE t1 SET a=5;
DELETE FROM t1;
}
2 {
PRAGMA recursive_triggers = 1;
CREATE TABLE t1(a, b);
CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
INSERT INTO t1 VALUES(new.a-1, new.b);
END;
} {
INSERT INTO t1 VALUES(5, 'x');
}
3 {
PRAGMA recursive_triggers = 1;
CREATE TABLE t1(a, b);
CREATE TABLE t2(a, b);
CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
INSERT INTO t2 VALUES(new.a-1, new.b);
END;
CREATE TRIGGER tr2 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
INSERT INTO t1 VALUES(new.a-1, new.b);
END;
} {
INSERT INTO t1 VALUES(10, 'x');
}
4 {
CREATE TABLE t1(a, b);
} {
SELECT count(*) FROM t1 WHERE upper(a)='ABC';
}
5x {
CREATE TABLE t1(a, b UNIQUE);
CREATE VIRTUAL TABLE t2 USING echo(t1);
} {
SELECT count(*) FROM t2;
SELECT * FROM t2 WHERE b>5;
SELECT * FROM t2 WHERE b='abcdefg';
}
} {
set tn "$::lookaside_buffer_size-$tn"
# Step 1.
db close
file delete -force test.db
sqlite3 db test.db
sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
db cache size 1000
catch { register_echo_module db }
ifcapable !vtab { if {[string match *x $tn]} continue }
execsql $schema
db cache flush
# Step 2.
execsql $statements
set nAlloc1 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc1 [lookaside db]
set nStmt1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
execsql $statements
# Step 3.
db cache flush
set nAlloc2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc2 [lookaside db]
set nStmt2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
# Step 3.
execsql $statements
set nAlloc3 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc3 [lookaside db]
set nStmt3 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
execsql $statements
# Step 4.
db cache flush
set nAlloc4 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
incr nAlloc4 [lookaside db]
set nStmt4 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
set nFree [expr {$nAlloc1-$nAlloc2}]
do_test dbstatus-3.$tn.a { expr $nStmt2 } {0}
# Tests for which the test name ends in an "x" report slightly less
# memory than is actually freed when all statements are finalized.
# This is because a small amount of memory allocated by a virtual table
# implementation using sqlite3_mprintf() is technically considered
# external and so is not counted as "statement memory".
#
#puts "$nStmt1 $nFree"
if {[string match *x $tn]} {
do_test dbstatus-3.$tn.bx { expr $nStmt1<=$nFree } {1}
} else {
do_test dbstatus-3.$tn.b { expr $nStmt1==$nFree } {1}
}
do_test dbstatus-3.$tn.c { list $nAlloc1 $nStmt1 } [list $nAlloc3 $nStmt3]
do_test dbstatus-3.$tn.d { list $nAlloc2 $nStmt2 } [list $nAlloc4 $nStmt4]
}
}
finish_test
+774
View File
@@ -329,4 +329,778 @@ foreach {n1 rhs} $literals {
}
}
#-------------------------------------------------------------------------
# Run some tests on the COLLATE "unary postfix operator".
#
# This collation sequence reverses both arguments before using
# [string compare] to compare them. For example, when comparing the
# strings 'one' and 'four', return the result of:
#
# string compare eno ruof
#
proc reverse_str {zStr} {
set out ""
foreach c [split $zStr {}] { set out "${c}${out}" }
set out
}
proc reverse_collate {zLeft zRight} {
string compare [reverse_str $zLeft] [reverse_str $zRight]
}
db collate reverse reverse_collate
# EVIDENCE-OF: R-59577-33471 The COLLATE operator is a unary postfix
# operator that assigns a collating sequence to an expression.
#
# EVIDENCE-OF: R-23441-22541 The COLLATE operator has a higher
# precedence (binds more tightly) than any prefix unary operator or any
# binary operator.
#
do_execsql_test e_expr-9.1 { SELECT 'abcd' < 'bbbb' COLLATE reverse } 0
do_execsql_test e_expr-9.2 { SELECT ('abcd' < 'bbbb') COLLATE reverse } 1
do_execsql_test e_expr-9.3 { SELECT 'abcd' <= 'bbbb' COLLATE reverse } 0
do_execsql_test e_expr-9.4 { SELECT ('abcd' <= 'bbbb') COLLATE reverse } 1
do_execsql_test e_expr-9.5 { SELECT 'abcd' > 'bbbb' COLLATE reverse } 1
do_execsql_test e_expr-9.6 { SELECT ('abcd' > 'bbbb') COLLATE reverse } 0
do_execsql_test e_expr-9.7 { SELECT 'abcd' >= 'bbbb' COLLATE reverse } 1
do_execsql_test e_expr-9.8 { SELECT ('abcd' >= 'bbbb') COLLATE reverse } 0
do_execsql_test e_expr-9.10 { SELECT 'abcd' = 'ABCD' COLLATE nocase } 1
do_execsql_test e_expr-9.11 { SELECT ('abcd' = 'ABCD') COLLATE nocase } 0
do_execsql_test e_expr-9.12 { SELECT 'abcd' == 'ABCD' COLLATE nocase } 1
do_execsql_test e_expr-9.13 { SELECT ('abcd' == 'ABCD') COLLATE nocase } 0
do_execsql_test e_expr-9.14 { SELECT 'abcd' IS 'ABCD' COLLATE nocase } 1
do_execsql_test e_expr-9.15 { SELECT ('abcd' IS 'ABCD') COLLATE nocase } 0
do_execsql_test e_expr-9.16 { SELECT 'abcd' != 'ABCD' COLLATE nocase } 0
do_execsql_test e_expr-9.17 { SELECT ('abcd' != 'ABCD') COLLATE nocase } 1
do_execsql_test e_expr-9.18 { SELECT 'abcd' <> 'ABCD' COLLATE nocase } 0
do_execsql_test e_expr-9.19 { SELECT ('abcd' <> 'ABCD') COLLATE nocase } 1
do_execsql_test e_expr-9.20 { SELECT 'abcd' IS NOT 'ABCD' COLLATE nocase } 0
do_execsql_test e_expr-9.21 { SELECT ('abcd' IS NOT 'ABCD') COLLATE nocase } 1
do_execsql_test e_expr-9.22 {
SELECT 'bbb' BETWEEN 'AAA' AND 'CCC' COLLATE nocase
} 1
do_execsql_test e_expr-9.23 {
SELECT ('bbb' BETWEEN 'AAA' AND 'CCC') COLLATE nocase
} 0
# EVIDENCE-OF: R-58731-25439 The collating sequence set by the COLLATE
# operator overrides the collating sequence determined by the COLLATE
# clause in a table column definition.
#
do_execsql_test e_expr-9.24 {
CREATE TABLE t24(a COLLATE NOCASE, b);
INSERT INTO t24 VALUES('aaa', 1);
INSERT INTO t24 VALUES('bbb', 2);
INSERT INTO t24 VALUES('ccc', 3);
} {}
do_execsql_test e_expr-9.25 { SELECT 'BBB' = a FROM t24 } {0 1 0}
do_execsql_test e_expr-9.25 { SELECT a = 'BBB' FROM t24 } {0 1 0}
do_execsql_test e_expr-9.25 { SELECT 'BBB' = a COLLATE binary FROM t24 } {0 0 0}
do_execsql_test e_expr-9.25 { SELECT a COLLATE binary = 'BBB' FROM t24 } {0 0 0}
#-------------------------------------------------------------------------
# Test statements related to literal values.
#
# EVIDENCE-OF: R-31536-32008 Literal values may be integers, floating
# point numbers, strings, BLOBs, or NULLs.
#
do_execsql_test e_expr-10.1.1 { SELECT typeof(5) } {integer}
do_execsql_test e_expr-10.1.2 { SELECT typeof(5.1) } {real}
do_execsql_test e_expr-10.1.3 { SELECT typeof('5.1') } {text}
do_execsql_test e_expr-10.1.4 { SELECT typeof(X'ABCD') } {blob}
do_execsql_test e_expr-10.1.5 { SELECT typeof(NULL) } {null}
# EVIDENCE-OF: R-26921-59298 Scientific notation is supported for
# floating point literal values.
#
do_execsql_test e_expr-10.2.1 { SELECT typeof(3.4e-02) } {real}
do_execsql_test e_expr-10.2.2 { SELECT typeof(3e+5) } {real}
do_execsql_test e_expr-10.2.3 { SELECT 3.4e-02 } {0.034}
do_execsql_test e_expr-10.2.4 { SELECT 3e+4 } {30000.0}
# EVIDENCE-OF: R-35229-17830 A string constant is formed by enclosing
# the string in single quotes (').
#
# EVIDENCE-OF: R-07100-06606 A single quote within the string can be
# encoded by putting two single quotes in a row - as in Pascal.
#
do_execsql_test e_expr-10.3.1 { SELECT 'is not' } {{is not}}
do_execsql_test e_expr-10.3.2 { SELECT typeof('is not') } {text}
do_execsql_test e_expr-10.3.3 { SELECT 'isn''t' } {isn't}
do_execsql_test e_expr-10.3.4 { SELECT typeof('isn''t') } {text}
# EVIDENCE-OF: R-09593-03321 BLOB literals are string literals
# containing hexadecimal data and preceded by a single "x" or "X"
# character.
#
# EVIDENCE-OF: R-39344-59787 For example: X'53514C697465'
#
do_execsql_test e_expr-10.4.1 { SELECT typeof(X'0123456789ABCDEF') } blob
do_execsql_test e_expr-10.4.2 { SELECT typeof(x'0123456789ABCDEF') } blob
do_execsql_test e_expr-10.4.3 { SELECT typeof(X'0123456789abcdef') } blob
do_execsql_test e_expr-10.4.4 { SELECT typeof(x'0123456789abcdef') } blob
do_execsql_test e_expr-10.4.5 { SELECT typeof(X'53514C697465') } blob
# EVIDENCE-OF: R-23914-51476 A literal value can also be the token
# "NULL".
#
do_execsql_test e_expr-10.5.1 { SELECT NULL } {{}}
do_execsql_test e_expr-10.5.2 { SELECT typeof(NULL) } {null}
#-------------------------------------------------------------------------
# Test statements related to bound parameters
#
proc parameter_test {tn sql params result} {
set stmt [sqlite3_prepare_v2 db $sql -1]
foreach {number name} $params {
set nm [sqlite3_bind_parameter_name $stmt $number]
do_test $tn.name.$number [list set {} $nm] $name
sqlite3_bind_int $stmt $number [expr -1 * $number]
}
sqlite3_step $stmt
set res [list]
for {set i 0} {$i < [sqlite3_column_count $stmt]} {incr i} {
lappend res [sqlite3_column_text $stmt $i]
}
set rc [sqlite3_finalize $stmt]
do_test $tn.rc [list set {} $rc] SQLITE_OK
do_test $tn.res [list set {} $res] $result
}
# EVIDENCE-OF: R-33509-39458 A question mark followed by a number NNN
# holds a spot for the NNN-th parameter. NNN must be between 1 and
# SQLITE_MAX_VARIABLE_NUMBER.
#
set mvn $SQLITE_MAX_VARIABLE_NUMBER
parameter_test e_expr-11.1 "
SELECT ?1, ?123, ?$SQLITE_MAX_VARIABLE_NUMBER, ?123, ?4
" "1 ?1 123 ?123 $mvn ?$mvn 4 ?4" "-1 -123 -$mvn -123 -4"
set errmsg "variable number must be between ?1 and ?$SQLITE_MAX_VARIABLE_NUMBER"
foreach {tn param_number} [list \
2 0 \
3 [expr $SQLITE_MAX_VARIABLE_NUMBER+1] \
4 [expr $SQLITE_MAX_VARIABLE_NUMBER+2] \
5 12345678903456789034567890234567890 \
6 2147483648 \
7 2147483649 \
8 4294967296 \
9 4294967297 \
10 9223372036854775808 \
11 9223372036854775809 \
12 18446744073709551616 \
13 18446744073709551617 \
] {
do_catchsql_test e_expr-11.1.$tn "SELECT ?$param_number" [list 1 $errmsg]
}
# EVIDENCE-OF: R-33670-36097 A question mark that is not followed by a
# number creates a parameter with a number one greater than the largest
# parameter number already assigned.
#
# EVIDENCE-OF: R-42938-07030 If this means the parameter number is
# greater than SQLITE_MAX_VARIABLE_NUMBER, it is an error.
#
parameter_test e_expr-11.2.1 "SELECT ?" {1 {}} -1
parameter_test e_expr-11.2.2 "SELECT ?, ?" {1 {} 2 {}} {-1 -2}
parameter_test e_expr-11.2.3 "SELECT ?5, ?" {5 ?5 6 {}} {-5 -6}
parameter_test e_expr-11.2.4 "SELECT ?, ?5" {1 {} 5 ?5} {-1 -5}
parameter_test e_expr-11.2.5 "SELECT ?, ?456, ?" {
1 {} 456 ?456 457 {}
} {-1 -456 -457}
parameter_test e_expr-11.2.5 "SELECT ?, ?456, ?4, ?" {
1 {} 456 ?456 4 ?4 457 {}
} {-1 -456 -4 -457}
foreach {tn sql} [list \
1 "SELECT ?$mvn, ?" \
2 "SELECT ?[expr $mvn-5], ?, ?, ?, ?, ?, ?" \
3 "SELECT ?[expr $mvn], ?5, ?6, ?" \
] {
do_catchsql_test e_expr-11.3.$tn $sql [list 1 {too many SQL variables}]
}
# EVIDENCE-OF: R-11620-22743 A colon followed by an identifier name
# holds a spot for a named parameter with the name :AAAA.
#
# Identifiers in SQLite consist of alphanumeric, '_' and '$' characters,
# and any UTF characters with codepoints larger than 127 (non-ASCII
# characters).
#
parameter_test e_expr-11.2.1 {SELECT :AAAA} {1 :AAAA} -1
parameter_test e_expr-11.2.2 {SELECT :123} {1 :123} -1
parameter_test e_expr-11.2.3 {SELECT :__} {1 :__} -1
parameter_test e_expr-11.2.4 {SELECT :_$_} {1 :_$_} -1
parameter_test e_expr-11.2.5 "
SELECT :\u0e40\u0e2d\u0e28\u0e02\u0e39\u0e40\u0e2d\u0e25
" "1 :\u0e40\u0e2d\u0e28\u0e02\u0e39\u0e40\u0e2d\u0e25" -1
parameter_test e_expr-11.2.6 "SELECT :\u0080" "1 :\u0080" -1
# EVIDENCE-OF: R-49783-61279 An "at" sign works exactly like a colon,
# except that the name of the parameter created is @AAAA.
#
parameter_test e_expr-11.3.1 {SELECT @AAAA} {1 @AAAA} -1
parameter_test e_expr-11.3.2 {SELECT @123} {1 @123} -1
parameter_test e_expr-11.3.3 {SELECT @__} {1 @__} -1
parameter_test e_expr-11.3.4 {SELECT @_$_} {1 @_$_} -1
parameter_test e_expr-11.3.5 "
SELECT @\u0e40\u0e2d\u0e28\u0e02\u0e39\u0e40\u0e2d\u0e25
" "1 @\u0e40\u0e2d\u0e28\u0e02\u0e39\u0e40\u0e2d\u0e25" -1
parameter_test e_expr-11.3.6 "SELECT @\u0080" "1 @\u0080" -1
# EVIDENCE-OF: R-62610-51329 A dollar-sign followed by an identifier
# name also holds a spot for a named parameter with the name $AAAA.
#
# EVIDENCE-OF: R-55025-21042 The identifier name in this case can
# include one or more occurrences of "::" and a suffix enclosed in
# "(...)" containing any text at all.
#
# Note: Looks like an identifier cannot consist entirely of "::"
# characters or just a suffix. Also, the other named variable characters
# (: and @) work the same way internally. Why not just document it that way?
#
parameter_test e_expr-11.4.1 {SELECT $AAAA} {1 $AAAA} -1
parameter_test e_expr-11.4.2 {SELECT $123} {1 $123} -1
parameter_test e_expr-11.4.3 {SELECT $__} {1 $__} -1
parameter_test e_expr-11.4.4 {SELECT $_$_} {1 $_$_} -1
parameter_test e_expr-11.4.5 "
SELECT \$\u0e40\u0e2d\u0e28\u0e02\u0e39\u0e40\u0e2d\u0e25
" "1 \$\u0e40\u0e2d\u0e28\u0e02\u0e39\u0e40\u0e2d\u0e25" -1
parameter_test e_expr-11.4.6 "SELECT \$\u0080" "1 \$\u0080" -1
parameter_test e_expr-11.5.1 {SELECT $::::a(++--++)} {1 $::::a(++--++)} -1
parameter_test e_expr-11.5.2 {SELECT $::a()} {1 $::a()} -1
parameter_test e_expr-11.5.3 {SELECT $::1(::#$)} {1 $::1(::#$)} -1
# EVIDENCE-OF: R-11370-04520 Named parameters are also numbered. The
# number assigned is one greater than the largest parameter number
# already assigned.
#
# EVIDENCE-OF: R-42620-22184 If this means the parameter would be
# assigned a number greater than SQLITE_MAX_VARIABLE_NUMBER, it is an
# error.
#
parameter_test e_expr-11.6.1 "SELECT ?, @abc" {1 {} 2 @abc} {-1 -2}
parameter_test e_expr-11.6.2 "SELECT ?123, :a1" {123 ?123 124 :a1} {-123 -124}
parameter_test e_expr-11.6.3 {SELECT $a, ?8, ?, $b, ?2, $c} {
1 $a 8 ?8 9 {} 10 $b 2 ?2 11 $c
} {-1 -8 -9 -10 -2 -11}
foreach {tn sql} [list \
1 "SELECT ?$mvn, \$::a" \
2 "SELECT ?$mvn, ?4, @a1" \
3 "SELECT ?[expr $mvn-2], :bag, @123, \$x" \
] {
do_catchsql_test e_expr-11.7.$tn $sql [list 1 {too many SQL variables}]
}
# EVIDENCE-OF: R-14068-49671 Parameters that are not assigned values
# using sqlite3_bind() are treated as NULL.
#
do_test e_expr-11.7.1 {
set stmt [sqlite3_prepare_v2 db { SELECT ?, :a, @b, $d } -1]
sqlite3_step $stmt
list [sqlite3_column_type $stmt 0] \
[sqlite3_column_type $stmt 1] \
[sqlite3_column_type $stmt 2] \
[sqlite3_column_type $stmt 3]
} {NULL NULL NULL NULL}
do_test e_expr-11.7.1 { sqlite3_finalize $stmt } SQLITE_OK
#-------------------------------------------------------------------------
# "Test" the syntax diagrams in lang_expr.html.
#
# EVIDENCE-OF: R-04177-20688 -- syntax diagram signed-number
#
do_execsql_test e_expr-12.1.1 { SELECT 0, +0, -0 } {0 0 0}
do_execsql_test e_expr-12.1.2 { SELECT 1, +1, -1 } {1 1 -1}
do_execsql_test e_expr-12.1.3 { SELECT 2, +2, -2 } {2 2 -2}
do_execsql_test e_expr-12.1.4 {
SELECT 1.4, +1.4, -1.4
} {1.4 1.4 -1.4}
do_execsql_test e_expr-12.1.5 {
SELECT 1.5e+5, +1.5e+5, -1.5e+5
} {150000.0 150000.0 -150000.0}
do_execsql_test e_expr-12.1.6 {
SELECT 0.0001, +0.0001, -0.0001
} {0.0001 0.0001 -0.0001}
# EVIDENCE-OF: R-30740-26723 -- syntax diagram literal-value
#
set sqlite_current_time 1
do_execsql_test e_expr-12.2.1 {SELECT 123} {123}
do_execsql_test e_expr-12.2.2 {SELECT 123.4e05} {12340000.0}
do_execsql_test e_expr-12.2.3 {SELECT 'abcde'} {abcde}
do_execsql_test e_expr-12.2.4 {SELECT X'414243'} {ABC}
do_execsql_test e_expr-12.2.5 {SELECT NULL} {{}}
do_execsql_test e_expr-12.2.6 {SELECT CURRENT_TIME} {00:00:01}
do_execsql_test e_expr-12.2.7 {SELECT CURRENT_DATE} {1970-01-01}
do_execsql_test e_expr-12.2.8 {SELECT CURRENT_TIMESTAMP} {{1970-01-01 00:00:01}}
set sqlite_current_time 0
# EVIDENCE-OF: R-57598-59332 -- syntax diagram expr
#
file delete -force test.db2
execsql {
ATTACH 'test.db2' AS dbname;
CREATE TABLE dbname.tblname(cname);
}
proc glob {args} {return 1}
db function glob glob
db function match glob
db function regexp glob
foreach {tn expr} {
1 123
2 123.4e05
3 'abcde'
4 X'414243'
5 NULL
6 CURRENT_TIME
7 CURRENT_DATE
8 CURRENT_TIMESTAMP
9 ?
10 ?123
11 @hello
12 :world
13 $tcl
14 $tcl(array)
15 cname
16 tblname.cname
17 dbname.tblname.cname
18 "+ EXPR"
19 "- EXPR"
20 "NOT EXPR"
21 "~ EXPR"
22 "EXPR1 || EXPR2"
23 "EXPR1 * EXPR2"
24 "EXPR1 / EXPR2"
25 "EXPR1 % EXPR2"
26 "EXPR1 + EXPR2"
27 "EXPR1 - EXPR2"
28 "EXPR1 << EXPR2"
29 "EXPR1 >> EXPR2"
30 "EXPR1 & EXPR2"
31 "EXPR1 | EXPR2"
32 "EXPR1 < EXPR2"
33 "EXPR1 <= EXPR2"
34 "EXPR1 > EXPR2"
35 "EXPR1 >= EXPR2"
36 "EXPR1 = EXPR2"
37 "EXPR1 == EXPR2"
38 "EXPR1 != EXPR2"
39 "EXPR1 <> EXPR2"
40 "EXPR1 IS EXPR2"
41 "EXPR1 IS NOT EXPR2"
42 "EXPR1 AND EXPR2"
43 "EXPR1 OR EXPR2"
44 "count(*)"
45 "count(DISTINCT EXPR)"
46 "substr(EXPR, 10, 20)"
47 "changes()"
48 "( EXPR )"
49 "CAST ( EXPR AS integer )"
50 "CAST ( EXPR AS 'abcd' )"
51 "CAST ( EXPR AS 'ab$ $cd' )"
52 "EXPR COLLATE nocase"
53 "EXPR COLLATE binary"
54 "EXPR1 LIKE EXPR2"
55 "EXPR1 LIKE EXPR2 ESCAPE EXPR"
56 "EXPR1 GLOB EXPR2"
57 "EXPR1 GLOB EXPR2 ESCAPE EXPR"
58 "EXPR1 REGEXP EXPR2"
59 "EXPR1 REGEXP EXPR2 ESCAPE EXPR"
60 "EXPR1 MATCH EXPR2"
61 "EXPR1 MATCH EXPR2 ESCAPE EXPR"
62 "EXPR1 NOT LIKE EXPR2"
63 "EXPR1 NOT LIKE EXPR2 ESCAPE EXPR"
64 "EXPR1 NOT GLOB EXPR2"
65 "EXPR1 NOT GLOB EXPR2 ESCAPE EXPR"
66 "EXPR1 NOT REGEXP EXPR2"
67 "EXPR1 NOT REGEXP EXPR2 ESCAPE EXPR"
68 "EXPR1 NOT MATCH EXPR2"
69 "EXPR1 NOT MATCH EXPR2 ESCAPE EXPR"
70 "EXPR ISNULL"
71 "EXPR NOTNULL"
72 "EXPR NOT NULL"
73 "EXPR1 IS EXPR2"
74 "EXPR1 IS NOT EXPR2"
75 "EXPR NOT BETWEEN EXPR1 AND EXPR2"
76 "EXPR BETWEEN EXPR1 AND EXPR2"
77 "EXPR NOT IN (SELECT cname FROM tblname)"
78 "EXPR NOT IN (1)"
79 "EXPR NOT IN (1, 2, 3)"
80 "EXPR NOT IN tblname"
81 "EXPR NOT IN dbname.tblname"
82 "EXPR IN (SELECT cname FROM tblname)"
83 "EXPR IN (1)"
84 "EXPR IN (1, 2, 3)"
85 "EXPR IN tblname"
86 "EXPR IN dbname.tblname"
87 "EXISTS (SELECT cname FROM tblname)"
88 "NOT EXISTS (SELECT cname FROM tblname)"
89 "CASE EXPR WHEN EXPR1 THEN EXPR2 ELSE EXPR END"
90 "CASE EXPR WHEN EXPR1 THEN EXPR2 END"
91 "CASE EXPR WHEN EXPR1 THEN EXPR2 WHEN EXPR THEN EXPR1 ELSE EXPR2 END"
92 "CASE EXPR WHEN EXPR1 THEN EXPR2 WHEN EXPR THEN EXPR1 END"
93 "CASE WHEN EXPR1 THEN EXPR2 ELSE EXPR END"
94 "CASE WHEN EXPR1 THEN EXPR2 END"
95 "CASE WHEN EXPR1 THEN EXPR2 WHEN EXPR THEN EXPR1 ELSE EXPR2 END"
96 "CASE WHEN EXPR1 THEN EXPR2 WHEN EXPR THEN EXPR1 END"
} {
# If the expression string being parsed contains "EXPR2", then replace
# string "EXPR1" and "EXPR2" with arbitrary SQL expressions. If it
# contains "EXPR", then replace EXPR with an arbitrary SQL expression.
#
set elist [list $expr]
if {[string match *EXPR2* $expr]} {
set elist [list]
foreach {e1 e2} { cname "34+22" } {
lappend elist [string map [list EXPR1 $e1 EXPR2 $e2] $expr]
}
}
if {[string match *EXPR* $expr]} {
set elist2 [list]
foreach el $elist {
foreach e { cname "34+22" } {
lappend elist2 [string map [list EXPR $e] $el]
}
}
set elist $elist2
}
set x 0
foreach e $elist {
incr x
do_test e_expr-12.3.$tn.$x {
set rc [catch { execsql "SELECT $e FROM tblname" } msg]
} {0}
}
}
# EVIDENCE-OF: R-49462-56079 -- syntax diagram raise-function
#
foreach {tn raiseexpr} {
1 "RAISE(IGNORE)"
2 "RAISE(ROLLBACK, 'error message')"
3 "RAISE(ABORT, 'error message')"
4 "RAISE(FAIL, 'error message')"
} {
do_execsql_test e_expr-12.4.$tn "
CREATE TRIGGER dbname.tr$tn BEFORE DELETE ON tblname BEGIN
SELECT $raiseexpr ;
END;
" {}
}
#-------------------------------------------------------------------------
# Test the statements related to the BETWEEN operator.
#
# EVIDENCE-OF: R-40079-54503 The BETWEEN operator is logically
# equivalent to a pair of comparisons. "x BETWEEN y AND z" is equivalent
# to "x>=y AND x<=z" except that with BETWEEN, the x expression is
# only evaluated once.
#
db func x x
proc x {} { incr ::xcount ; return [expr $::x] }
foreach {tn x expr res nEval} {
1 10 "x() >= 5 AND x() <= 15" 1 2
2 10 "x() BETWEEN 5 AND 15" 1 1
3 5 "x() >= 5 AND x() <= 5" 1 2
4 5 "x() BETWEEN 5 AND 5" 1 1
} {
do_test e_expr-13.1.$tn {
set ::xcount 0
set a [execsql "SELECT $expr"]
list $::xcount $a
} [list $nEval $res]
}
# EVIDENCE-OF: R-05155-34454 The precedence of the BETWEEN operator is
# the same as the precedence as operators == and != and LIKE and groups
# left to right.
#
# Therefore, BETWEEN groups more tightly than operator "AND", but less
# so than "<".
#
do_execsql_test e_expr-13.2.1 { SELECT 1 == 10 BETWEEN 0 AND 2 } 1
do_execsql_test e_expr-13.2.2 { SELECT (1 == 10) BETWEEN 0 AND 2 } 1
do_execsql_test e_expr-13.2.3 { SELECT 1 == (10 BETWEEN 0 AND 2) } 0
do_execsql_test e_expr-13.2.4 { SELECT 6 BETWEEN 4 AND 8 == 1 } 1
do_execsql_test e_expr-13.2.5 { SELECT (6 BETWEEN 4 AND 8) == 1 } 1
do_execsql_test e_expr-13.2.6 { SELECT 6 BETWEEN 4 AND (8 == 1) } 0
do_execsql_test e_expr-13.2.7 { SELECT 5 BETWEEN 0 AND 0 != 1 } 1
do_execsql_test e_expr-13.2.8 { SELECT (5 BETWEEN 0 AND 0) != 1 } 1
do_execsql_test e_expr-13.2.9 { SELECT 5 BETWEEN 0 AND (0 != 1) } 0
do_execsql_test e_expr-13.2.10 { SELECT 1 != 0 BETWEEN 0 AND 2 } 1
do_execsql_test e_expr-13.2.11 { SELECT (1 != 0) BETWEEN 0 AND 2 } 1
do_execsql_test e_expr-13.2.12 { SELECT 1 != (0 BETWEEN 0 AND 2) } 0
do_execsql_test e_expr-13.2.13 { SELECT 1 LIKE 10 BETWEEN 0 AND 2 } 1
do_execsql_test e_expr-13.2.14 { SELECT (1 LIKE 10) BETWEEN 0 AND 2 } 1
do_execsql_test e_expr-13.2.15 { SELECT 1 LIKE (10 BETWEEN 0 AND 2) } 0
do_execsql_test e_expr-13.2.16 { SELECT 6 BETWEEN 4 AND 8 LIKE 1 } 1
do_execsql_test e_expr-13.2.17 { SELECT (6 BETWEEN 4 AND 8) LIKE 1 } 1
do_execsql_test e_expr-13.2.18 { SELECT 6 BETWEEN 4 AND (8 LIKE 1) } 0
do_execsql_test e_expr-13.2.19 { SELECT 0 AND 0 BETWEEN 0 AND 1 } 0
do_execsql_test e_expr-13.2.20 { SELECT 0 AND (0 BETWEEN 0 AND 1) } 0
do_execsql_test e_expr-13.2.21 { SELECT (0 AND 0) BETWEEN 0 AND 1 } 1
do_execsql_test e_expr-13.2.22 { SELECT 0 BETWEEN -1 AND 1 AND 0 } 0
do_execsql_test e_expr-13.2.23 { SELECT (0 BETWEEN -1 AND 1) AND 0 } 0
do_execsql_test e_expr-13.2.24 { SELECT 0 BETWEEN -1 AND (1 AND 0) } 1
do_execsql_test e_expr-13.2.25 { SELECT 2 < 3 BETWEEN 0 AND 1 } 1
do_execsql_test e_expr-13.2.26 { SELECT (2 < 3) BETWEEN 0 AND 1 } 1
do_execsql_test e_expr-13.2.27 { SELECT 2 < (3 BETWEEN 0 AND 1) } 0
do_execsql_test e_expr-13.2.28 { SELECT 2 BETWEEN 1 AND 2 < 3 } 0
do_execsql_test e_expr-13.2.29 { SELECT 2 BETWEEN 1 AND (2 < 3) } 0
do_execsql_test e_expr-13.2.30 { SELECT (2 BETWEEN 1 AND 2) < 3 } 1
#-------------------------------------------------------------------------
# Test the statements related to the LIKE and GLOB operators.
#
# EVIDENCE-OF: R-16584-60189 The LIKE operator does a pattern matching
# comparison.
#
# EVIDENCE-OF: R-11295-04657 The operand to the right of the LIKE
# operator contains the pattern and the left hand operand contains the
# string to match against the pattern.
#
do_execsql_test e_expr-14.1.1 { SELECT 'abc%' LIKE 'abcde' } 0
do_execsql_test e_expr-14.1.2 { SELECT 'abcde' LIKE 'abc%' } 1
# EVIDENCE-OF: R-55406-38524 A percent symbol ("%") in the LIKE pattern
# matches any sequence of zero or more characters in the string.
#
do_execsql_test e_expr-14.2.1 { SELECT 'abde' LIKE 'ab%de' } 1
do_execsql_test e_expr-14.2.2 { SELECT 'abXde' LIKE 'ab%de' } 1
do_execsql_test e_expr-14.2.3 { SELECT 'abABCde' LIKE 'ab%de' } 1
# EVIDENCE-OF: R-30433-25443 An underscore ("_") in the LIKE pattern
# matches any single character in the string.
#
do_execsql_test e_expr-14.3.1 { SELECT 'abde' LIKE 'ab_de' } 0
do_execsql_test e_expr-14.3.2 { SELECT 'abXde' LIKE 'ab_de' } 1
do_execsql_test e_expr-14.3.3 { SELECT 'abABCde' LIKE 'ab_de' } 0
# EVIDENCE-OF: R-59007-20454 Any other character matches itself or its
# lower/upper case equivalent (i.e. case-insensitive matching).
#
do_execsql_test e_expr-14.4.1 { SELECT 'abc' LIKE 'aBc' } 1
do_execsql_test e_expr-14.4.2 { SELECT 'aBc' LIKE 'aBc' } 1
do_execsql_test e_expr-14.4.3 { SELECT 'ac' LIKE 'aBc' } 0
# EVIDENCE-OF: R-23648-58527 SQLite only understands upper/lower case
# for ASCII characters by default.
#
# EVIDENCE-OF: R-04532-11527 The LIKE operator is case sensitive by
# default for unicode characters that are beyond the ASCII range.
#
# EVIDENCE-OF: R-44381-11669 the expression
# 'a'&nbsp;LIKE&nbsp;'A' is TRUE but
# '&aelig;'&nbsp;LIKE&nbsp;'&AElig;' is FALSE.
#
do_execsql_test e_expr-14.5.1 { SELECT 'A' LIKE 'a' } 1
do_execsql_test e_expr-14.5.2 "SELECT '\u00c6' LIKE '\u00e6'" 0
# EVIDENCE-OF: R-56683-13731 If the optional ESCAPE clause is present,
# then the expression following the ESCAPE keyword must evaluate to a
# string consisting of a single character.
#
do_catchsql_test e_expr-14.6.1 {
SELECT 'A' LIKE 'a' ESCAPE '12'
} {1 {ESCAPE expression must be a single character}}
do_catchsql_test e_expr-14.6.2 {
SELECT 'A' LIKE 'a' ESCAPE ''
} {1 {ESCAPE expression must be a single character}}
do_catchsql_test e_expr-14.6.3 { SELECT 'A' LIKE 'a' ESCAPE 'x' } {0 1}
do_catchsql_test e_expr-14.6.4 "SELECT 'A' LIKE 'a' ESCAPE '\u00e6'" {0 1}
# EVIDENCE-OF: R-02045-23762 This character may be used in the LIKE
# pattern to include literal percent or underscore characters.
#
# EVIDENCE-OF: R-13345-31830 The escape character followed by a percent
# symbol (%), underscore (_), or a second instance of the escape
# character itself matches a literal percent symbol, underscore, or a
# single escape character, respectively.
#
do_execsql_test e_expr-14.7.1 { SELECT 'abc%' LIKE 'abcX%' ESCAPE 'X' } 1
do_execsql_test e_expr-14.7.2 { SELECT 'abc5' LIKE 'abcX%' ESCAPE 'X' } 0
do_execsql_test e_expr-14.7.3 { SELECT 'abc' LIKE 'abcX%' ESCAPE 'X' } 0
do_execsql_test e_expr-14.7.4 { SELECT 'abcX%' LIKE 'abcX%' ESCAPE 'X' } 0
do_execsql_test e_expr-14.7.5 { SELECT 'abc%%' LIKE 'abcX%' ESCAPE 'X' } 0
do_execsql_test e_expr-14.7.6 { SELECT 'abc_' LIKE 'abcX_' ESCAPE 'X' } 1
do_execsql_test e_expr-14.7.7 { SELECT 'abc5' LIKE 'abcX_' ESCAPE 'X' } 0
do_execsql_test e_expr-14.7.8 { SELECT 'abc' LIKE 'abcX_' ESCAPE 'X' } 0
do_execsql_test e_expr-14.7.9 { SELECT 'abcX_' LIKE 'abcX_' ESCAPE 'X' } 0
do_execsql_test e_expr-14.7.10 { SELECT 'abc__' LIKE 'abcX_' ESCAPE 'X' } 0
do_execsql_test e_expr-14.7.11 { SELECT 'abcX' LIKE 'abcXX' ESCAPE 'X' } 1
do_execsql_test e_expr-14.7.12 { SELECT 'abc5' LIKE 'abcXX' ESCAPE 'X' } 0
do_execsql_test e_expr-14.7.13 { SELECT 'abc' LIKE 'abcXX' ESCAPE 'X' } 0
do_execsql_test e_expr-14.7.14 { SELECT 'abcXX' LIKE 'abcXX' ESCAPE 'X' } 0
# EVIDENCE-OF: R-51359-17496 The infix LIKE operator is implemented by
# calling the application-defined SQL functions like(Y,X) or like(Y,X,Z).
#
proc likefunc {args} {
eval lappend ::likeargs $args
return 1
}
db func like likefunc
set ::likeargs [list]
do_execsql_test e_expr-15.1.1 { SELECT 'abc' LIKE 'def' } 1
do_test e_expr-15.1.2 { set likeargs } {def abc}
set ::likeargs [list]
do_execsql_test e_expr-15.1.3 { SELECT 'abc' LIKE 'def' ESCAPE 'X' } 1
do_test e_expr-15.1.4 { set likeargs } {def abc X}
db close
sqlite3 db test.db
# EVIDENCE-OF: R-22868-25880 The LIKE operator can be made case
# sensitive using the case_sensitive_like pragma.
#
do_execsql_test e_expr-16.1.1 { SELECT 'abcxyz' LIKE 'ABC%' } 1
do_execsql_test e_expr-16.1.2 { PRAGMA case_sensitive_like = 1 } {}
do_execsql_test e_expr-16.1.3 { SELECT 'abcxyz' LIKE 'ABC%' } 0
do_execsql_test e_expr-16.1.4 { SELECT 'ABCxyz' LIKE 'ABC%' } 1
do_execsql_test e_expr-16.1.5 { PRAGMA case_sensitive_like = 0 } {}
do_execsql_test e_expr-16.1.6 { SELECT 'abcxyz' LIKE 'ABC%' } 1
do_execsql_test e_expr-16.1.7 { SELECT 'ABCxyz' LIKE 'ABC%' } 1
# EVIDENCE-OF: R-52087-12043 The GLOB operator is similar to LIKE but
# uses the Unix file globbing syntax for its wildcards.
#
# EVIDENCE-OF: R-09813-17279 Also, GLOB is case sensitive, unlike LIKE.
#
do_execsql_test e_expr-17.1.1 { SELECT 'abcxyz' GLOB 'abc%' } 0
do_execsql_test e_expr-17.1.2 { SELECT 'abcxyz' GLOB 'abc*' } 1
do_execsql_test e_expr-17.1.3 { SELECT 'abcxyz' GLOB 'abc___' } 0
do_execsql_test e_expr-17.1.4 { SELECT 'abcxyz' GLOB 'abc???' } 1
do_execsql_test e_expr-17.1.5 { SELECT 'abcxyz' GLOB 'abc*' } 1
do_execsql_test e_expr-17.1.6 { SELECT 'ABCxyz' GLOB 'abc*' } 0
do_execsql_test e_expr-17.1.7 { SELECT 'abcxyz' GLOB 'ABC*' } 0
# EVIDENCE-OF: R-39616-20555 Both GLOB and LIKE may be preceded by the
# NOT keyword to invert the sense of the test.
#
do_execsql_test e_expr-17.2.1 { SELECT 'abcxyz' NOT GLOB 'ABC*' } 1
do_execsql_test e_expr-17.2.2 { SELECT 'abcxyz' NOT GLOB 'abc*' } 0
do_execsql_test e_expr-17.2.3 { SELECT 'abcxyz' NOT LIKE 'ABC%' } 0
do_execsql_test e_expr-17.2.4 { SELECT 'abcxyz' NOT LIKE 'abc%' } 0
do_execsql_test e_expr-17.2.5 { SELECT 'abdxyz' NOT LIKE 'abc%' } 1
db nullvalue null
do_execsql_test e_expr-17.2.6 { SELECT 'abcxyz' NOT GLOB NULL } null
do_execsql_test e_expr-17.2.7 { SELECT 'abcxyz' NOT LIKE NULL } null
do_execsql_test e_expr-17.2.8 { SELECT NULL NOT GLOB 'abc*' } null
do_execsql_test e_expr-17.2.9 { SELECT NULL NOT LIKE 'ABC%' } null
db nullvalue {}
# EVIDENCE-OF: R-39414-35489 The infix GLOB operator is implemented by
# calling the function glob(Y,X) and can be modified by overriding that
# function.
proc globfunc {args} {
eval lappend ::globargs $args
return 1
}
db func glob -argcount 2 globfunc
set ::globargs [list]
do_execsql_test e_expr-17.3.1 { SELECT 'abc' GLOB 'def' } 1
do_test e_expr-17.3.2 { set globargs } {def abc}
set ::globargs [list]
do_execsql_test e_expr-17.3.3 { SELECT 'X' NOT GLOB 'Y' } 0
do_test e_expr-17.3.4 { set globargs } {Y X}
sqlite3 db test.db
# EVIDENCE-OF: R-41650-20872 No regexp() user function is defined by
# default and so use of the REGEXP operator will normally result in an
# error message.
#
do_catchsql_test e_expr-18.1.1 {
SELECT regexp('abc', 'def')
} {1 {no such function: regexp}}
do_catchsql_test e_expr-18.1.2 {
SELECT 'abc' REGEXP 'def'
} {1 {no such function: REGEXP}}
# EVIDENCE-OF: R-33693-50180 The REGEXP operator is a special syntax for
# the regexp() user function.
#
# EVIDENCE-OF: R-57289-13578 If a application-defined SQL function named
# "regexp" is added at run-time, that function will be called in order
# to implement the REGEXP operator.
#
proc regexpfunc {args} {
eval lappend ::regexpargs $args
return 1
}
db func regexp -argcount 2 regexpfunc
set ::regexpargs [list]
do_execsql_test e_expr-18.2.1 { SELECT 'abc' REGEXP 'def' } 1
do_test e_expr-18.2.2 { set regexpargs } {def abc}
set ::regexpargs [list]
do_execsql_test e_expr-18.2.3 { SELECT 'X' NOT REGEXP 'Y' } 0
do_test e_expr-18.2.4 { set regexpargs } {Y X}
sqlite3 db test.db
# EVIDENCE-OF: R-42037-37826 The default match() function implementation
# raises an exception and is not really useful for anything.
#
do_catchsql_test e_expr-19.1.1 {
SELECT 'abc' MATCH 'def'
} {1 {unable to use function MATCH in the requested context}}
do_catchsql_test e_expr-19.1.2 {
SELECT match('abc', 'def')
} {1 {unable to use function MATCH in the requested context}}
# EVIDENCE-OF: R-37916-47407 The MATCH operator is a special syntax for
# the match() application-defined function.
#
# EVIDENCE-OF: R-06021-09373 But extensions can override the match()
# function with more helpful logic.
#
proc matchfunc {args} {
eval lappend ::matchargs $args
return 1
}
db func match -argcount 2 matchfunc
set ::matchargs [list]
do_execsql_test e_expr-19.2.1 { SELECT 'abc' MATCH 'def' } 1
do_test e_expr-19.2.2 { set matchargs } {def abc}
set ::matchargs [list]
do_execsql_test e_expr-19.2.3 { SELECT 'X' NOT MATCH 'Y' } 0
do_test e_expr-19.2.4 { set matchargs } {Y X}
sqlite3 db test.db
finish_test
+6
View File
@@ -253,6 +253,11 @@ db2 close
# from being inspected externally.
#
if {$tcl_platform(platform) != "windows"} {
# Return a list of two booleans (either 0 or 1). The first is true
# if the named file exists. The second is true only if the file
# exists and the first 28 bytes contain at least one non-zero byte.
#
proc filestate {fname} {
set exists 0
set content 0
@@ -263,6 +268,7 @@ if {$tcl_platform(platform) != "windows"} {
}
list $exists $content
}
do_test exclusive-3.0 {
filestate test.db-journal
} {0 0}
+146
View File
@@ -0,0 +1,146 @@
# 2010 July 28
#
# 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
file_control_chunksize_test db main [expr 1024*1024]
do_test fallocate-1.1 {
execsql {
PRAGMA page_size = 1024;
PRAGMA auto_vacuum = 1;
CREATE TABLE t1(a, b);
}
file size test.db
} [expr 1*1024*1024]
do_test fallocate-1.2 {
execsql { INSERT INTO t1 VALUES(1, zeroblob(1024*900)) }
file size test.db
} [expr 1*1024*1024]
do_test fallocate-1.3 {
execsql { INSERT INTO t1 VALUES(2, zeroblob(1024*900)) }
file size test.db
} [expr 2*1024*1024]
do_test fallocate-1.4 {
execsql { DELETE FROM t1 WHERE a = 1 }
file size test.db
} [expr 1*1024*1024]
do_test fallocate-1.5 {
execsql { DELETE FROM t1 WHERE a = 2 }
file size test.db
} [expr 1*1024*1024]
do_test fallocate-1.6 {
execsql { PRAGMA freelist_count }
} {0}
# Start a write-transaction and read the "database file size" field from
# the journal file. This field should be set to the number of pages in
# the database file based on the size of the file on disk, not the actual
# logical size of the database within the file.
#
# We need to check this to verify that if in the unlikely event a rollback
# causes a database file to grow, the database grows to its previous size
# on disk, not to the minimum size required to hold the database image.
#
do_test fallocate-1.7 {
execsql { BEGIN; INSERT INTO t1 VALUES(1, 2); }
if {[permutation] != "inmemory_journal"} {
hexio_get_int [hexio_read test.db-journal 16 4]
} else {
set {} 1024
}
} {1024}
do_test fallocate-1.8 { execsql { COMMIT } } {}
#-------------------------------------------------------------------------
# The following tests - fallocate-2.* - test that things work in WAL
# mode as well.
#
set skipwaltests [expr {
[permutation]=="journaltest" || [permutation]=="inmemory_journal"
}]
ifcapable !wal { set skipwaltests 1 }
if {!$skipwaltests} {
db close
file delete -force test.db
sqlite3 db test.db
file_control_chunksize_test db main [expr 32*1024]
do_test fallocate-2.1 {
execsql {
PRAGMA page_size = 1024;
PRAGMA journal_mode = WAL;
CREATE TABLE t1(a, b);
}
file size test.db
} [expr 32*1024]
do_test fallocate-2.2 {
execsql { INSERT INTO t1 VALUES(1, zeroblob(35*1024)) }
execsql { PRAGMA wal_checkpoint }
file size test.db
} [expr 64*1024]
do_test fallocate-2.3 {
execsql { DELETE FROM t1 }
execsql { VACUUM }
file size test.db
} [expr 64*1024]
do_test fallocate-2.4 {
execsql { PRAGMA wal_checkpoint }
file size test.db
} [expr 32*1024]
do_test fallocate-2.5 {
execsql {
INSERT INTO t1 VALUES(2, randomblob(35*1024));
PRAGMA wal_checkpoint;
INSERT INTO t1 VALUES(3, randomblob(128));
DELETE FROM t1 WHERE a = 2;
VACUUM;
}
file size test.db
} [expr 64*1024]
do_test fallocate-2.6 {
sqlite3 db2 test.db
execsql { BEGIN ; SELECT count(a) FROM t1 } db2
execsql {
INSERT INTO t1 VALUES(4, randomblob(128));
PRAGMA wal_checkpoint;
}
file size test.db
} [expr 64*1024]
do_test fallocate-2.7 {
execsql { SELECT count(b) FROM t1 } db2
} {1}
do_test fallocate-2.8 {
execsql { COMMIT } db2
execsql { PRAGMA wal_checkpoint }
file size test.db
} [expr 32*1024]
}
finish_test
+45
View File
@@ -1936,5 +1936,50 @@ do_test fkey2-dd08e5.1.6 {
}
} {1 {foreign key constraint failed}}
#-------------------------------------------------------------------------
# Verify that ticket ce7c133ea6cc9ccdc1a60d80441f80b6180f5eba
# fixed.
#
do_test fkey2-ce7c13.1.1 {
execsql {
CREATE TABLE tce71(a INTEGER PRIMARY KEY, b);
CREATE UNIQUE INDEX ice71 ON tce71(a,b);
INSERT INTO tce71 VALUES(100,200);
CREATE TABLE tce72(w, x, y, FOREIGN KEY(x,y) REFERENCES tce71(a,b));
INSERT INTO tce72 VALUES(300,100,200);
UPDATE tce71 set b = 200 where a = 100;
SELECT * FROM tce71, tce72;
}
} {100 200 300 100 200}
do_test fkey2-ce7c13.1.2 {
catchsql {
UPDATE tce71 set b = 201 where a = 100;
}
} {1 {foreign key constraint failed}}
do_test fkey2-ce7c13.1.3 {
catchsql {
UPDATE tce71 set a = 101 where a = 100;
}
} {1 {foreign key constraint failed}}
do_test fkey2-ce7c13.1.4 {
execsql {
CREATE TABLE tce73(a INTEGER PRIMARY KEY, b, UNIQUE(a,b));
INSERT INTO tce73 VALUES(100,200);
CREATE TABLE tce74(w, x, y, FOREIGN KEY(x,y) REFERENCES tce73(a,b));
INSERT INTO tce74 VALUES(300,100,200);
UPDATE tce73 set b = 200 where a = 100;
SELECT * FROM tce73, tce74;
}
} {100 200 300 100 200}
do_test fkey2-ce7c13.1.5 {
catchsql {
UPDATE tce73 set b = 201 where a = 100;
}
} {1 {foreign key constraint failed}}
do_test fkey2-ce7c13.1.6 {
catchsql {
UPDATE tce73 set a = 101 where a = 100;
}
} {1 {foreign key constraint failed}}
finish_test
+19
View File
@@ -114,4 +114,23 @@ do_test icu-4.3 {
}
} {apricot cherry chokecherry yamot peach plum}
#-------------------------------------------------------------------------
# Test that it is not possible to call the ICU regex() function with
# anything other than exactly two arguments. See also:
#
# http://src.chromium.org/viewvc/chrome/trunk/src/third_party/sqlite/icu-regexp.patch?revision=34807&view=markup
#
do_catchsql_test icu-5.1 { SELECT regexp('a[abc]c.*', 'abc') } {0 1}
do_catchsql_test icu-5.2 {
SELECT regexp('a[abc]c.*')
} {1 {wrong number of arguments to function regexp()}}
do_catchsql_test icu-5.3 {
SELECT regexp('a[abc]c.*', 'abc', 'c')
} {1 {wrong number of arguments to function regexp()}}
do_catchsql_test icu-5.4 {
SELECT 'abc' REGEXP 'a[abc]c.*'
} {0 1}
do_catchsql_test icu-5.4 { SELECT 'abc' REGEXP } {1 {near " ": syntax error}}
do_catchsql_test icu-5.5 { SELECT 'abc' REGEXP, 1 } {1 {near ",": syntax error}}
finish_test
+10
View File
@@ -123,6 +123,16 @@ do_test indexedby-4.1 {
do_test indexedby-4.2 {
EQP { SELECT * FROM t1 INDEXED BY i1, t2 WHERE a = c }
} {0 1 {TABLE t2} 1 0 {TABLE t1 WITH INDEX i1}}
do_test indexedby-4.3 {
catchsql {
SELECT * FROM t1 INDEXED BY i1, t2 INDEXED BY i3 WHERE a=c
}
} {1 {cannot use index: i1}}
do_test indexedby-4.4 {
catchsql {
SELECT * FROM t2 INDEXED BY i3, t1 INDEXED BY i1 WHERE a=c
}
} {1 {cannot use index: i3}}
# Test embedding an INDEXED BY in a CREATE VIEW statement. This block
# also tests that nothing bad happens if an index refered to by
+12 -17
View File
@@ -91,6 +91,15 @@ foreach locking_mode {normal exclusive} {
INSERT INTO a VALUES(1, 'ABCDEFGHIJKLMNOP');
}
} {}
# Open a read-only cursor on table "a". If the COMMIT below is
# interrupted by a persistent IO error, the pager will transition to
# PAGER_ERROR state. If there are no other read-only cursors open,
# from there the pager immediately discards all cached data and
# switches to PAGER_OPEN state. This read-only cursor stops that
# from happening, leaving the pager stuck in PAGER_ERROR state.
#
set channel [db incrblob -readonly a Name [db last_insert_rowid]]
# Now try to commit the transaction. Cause an IO error to occur
# within this operation, which moves the pager into the error state.
@@ -118,25 +127,11 @@ foreach locking_mode {normal exclusive} {
# with the dirty page.
#
do_test ioerr5-1.$locking_mode-$iFail.3 {
set bt [btree_from_db db]
sqlite3_soft_heap_limit 1024
compilesql16 "SELECT 10"
array set stats [btree_pager_stats $bt]
} {SQLITE_OK}
# If the pager made it all the way to PAGER_SYNCED state, then
# both in-memory pages are clean. Following the calls to
# release_memory() that were made as part of the [compilesql16]
# above, there will be zero pages left in the cache.
#
# If the pager did not make it as far as PAGER_SYNCED, the two
# in memory pages are still dirty. So there will be 2 pages left
# in the cache following the release_memory() calls.
#
if {$stats(state)==5} {
set nPage 0
}
expr {$stats(page)==$nPage}
} {1}
close $channel
# Ensure that nothing was written to the database while reclaiming
# memory from the pager in error state.
@@ -148,7 +143,7 @@ foreach locking_mode {normal exclusive} {
close $fd
expr {$zDatabase eq $zDatabase2}
} {1}
if {$rc eq [list 0 {}]} {
do_test ioerr5.1-$locking_mode-$iFail.3 {
execsql { SELECT count(*) FROM a }
+31
View File
@@ -524,4 +524,35 @@ ifcapable pragma {
do_test jrnlmode-7.2 { file size test.db } {1024}
}
do_execsql_test jrnlmode-8.1 { PRAGMA locking_mode=EXCLUSIVE } {exclusive}
do_execsql_test jrnlmode-8.2 { CREATE TABLE t1(x) } {}
do_execsql_test jrnlmode-8.3 { INSERT INTO t1 VALUES(123) } {}
do_execsql_test jrnlmode-8.4 { SELECT * FROM t1 } {123}
do_execsql_test jrnlmode-8.5 { PRAGMA journal_mode=PERSIST } {persist}
do_execsql_test jrnlmode-8.6 { PRAGMA journal_mode=DELETE } {delete}
do_execsql_test jrnlmode-8.7 { PRAGMA journal_mode=TRUNCATE } {truncate}
do_execsql_test jrnlmode-8.8 { PRAGMA journal_mode=DELETE } {delete}
do_execsql_test jrnlmode-8.9 { CREATE TABLE t2(y) } {}
do_execsql_test jrnlmode-8.10 { INSERT INTO t2 VALUES(456) } {}
do_execsql_test jrnlmode-8.11 { SELECT * FROM t1, t2 } {123 456}
do_execsql_test jrnlmode-8.12 { PRAGMA locking_mode=NORMAL } {normal}
do_execsql_test jrnlmode-8.13 { PRAGMA journal_mode=PERSIST } {persist}
do_execsql_test jrnlmode-8.14 { PRAGMA journal_mode=TRUNCATE } {truncate}
do_execsql_test jrnlmode-8.15 { PRAGMA journal_mode=PERSIST } {persist}
do_execsql_test jrnlmode-8.16 { PRAGMA journal_mode=DELETE } {delete}
do_execsql_test jrnlmode-8.17 { PRAGMA journal_mode=TRUNCATE } {truncate}
do_execsql_test jrnlmode-8.18 { PRAGMA locking_mode=EXCLUSIVE } {exclusive}
do_execsql_test jrnlmode-8.19 { CREATE TABLE t3(z) } {}
do_execsql_test jrnlmode-8.20 { BEGIN IMMEDIATE } {}
do_execsql_test jrnlmode-8.21 { PRAGMA journal_mode=DELETE } {delete}
do_execsql_test jrnlmode-8.22 { COMMIT } {}
do_execsql_test jrnlmode-8.23 { PRAGMA journal_mode=DELETE } {delete}
do_execsql_test jrnlmode-8.24 { PRAGMA journal_mode=TRUNCATE } {truncate}
do_execsql_test jrnlmode-8.25 { PRAGMA locking_mode=NORMAL } {normal}
do_execsql_test jrnlmode-8.26 { CREATE TABLE t4(w) } {}
do_execsql_test jrnlmode-8.27 { BEGIN IMMEDIATE } {}
do_execsql_test jrnlmode-8.28 { PRAGMA journal_mode=DELETE } {delete}
do_execsql_test jrnlmode-8.29 { COMMIT } {}
do_execsql_test jrnlmode-8.30 { PRAGMA journal_mode=DELETE } {delete}
finish_test
+134
View File
@@ -194,6 +194,31 @@ do_test like-3.4 {
set sqlite_like_count
} 0
# The LIKE optimization still works when the RHS is a string with no
# wildcard. Ticket [e090183531fc2747]
#
do_test like-3.4.2 {
queryplan {
SELECT x FROM t1 WHERE x LIKE 'a' ORDER BY 1;
}
} {a nosort {} i1}
do_test like-3.4.3 {
queryplan {
SELECT x FROM t1 WHERE x LIKE 'ab' ORDER BY 1;
}
} {ab nosort {} i1}
do_test like-3.4.4 {
queryplan {
SELECT x FROM t1 WHERE x LIKE 'abcd' ORDER BY 1;
}
} {abcd nosort {} i1}
do_test like-3.4.5 {
queryplan {
SELECT x FROM t1 WHERE x LIKE 'abcde' ORDER BY 1;
}
} {nosort {} i1}
# Partial optimization when the pattern does not end in '%'
#
do_test like-3.5 {
@@ -309,6 +334,26 @@ do_test like-3.24 {
set sqlite_like_count
} 6
# GLOB optimization when there is no wildcard. Ticket [e090183531fc2747]
#
do_test like-3.25 {
queryplan {
SELECT x FROM t1 WHERE x GLOB 'a' ORDER BY 1;
}
} {a nosort {} i1}
do_test like-3.26 {
queryplan {
SELECT x FROM t1 WHERE x GLOB 'abcd' ORDER BY 1;
}
} {abcd nosort {} i1}
do_test like-3.27 {
queryplan {
SELECT x FROM t1 WHERE x GLOB 'abcde' ORDER BY 1;
}
} {nosort {} i1}
# No optimization if the LHS of the LIKE is not a column name or
# if the RHS is not a string.
#
@@ -733,5 +778,94 @@ do_test like-10.15 {
}
} {12 123 scan 5 like 6}
# LIKE and GLOB where the default collating sequence is not appropriate
# but an index with the appropriate collating sequence exists.
#
do_test like-11.0 {
execsql {
CREATE TABLE t11(
a INTEGER PRIMARY KEY,
b TEXT COLLATE nocase,
c TEXT COLLATE binary
);
INSERT INTO t11 VALUES(1, 'a','a');
INSERT INTO t11 VALUES(2, 'ab','ab');
INSERT INTO t11 VALUES(3, 'abc','abc');
INSERT INTO t11 VALUES(4, 'abcd','abcd');
INSERT INTO t11 VALUES(5, 'A','A');
INSERT INTO t11 VALUES(6, 'AB','AB');
INSERT INTO t11 VALUES(7, 'ABC','ABC');
INSERT INTO t11 VALUES(8, 'ABCD','ABCD');
INSERT INTO t11 VALUES(9, 'x','x');
INSERT INTO t11 VALUES(10, 'yz','yz');
INSERT INTO t11 VALUES(11, 'X','X');
INSERT INTO t11 VALUES(12, 'YZ','YZ');
SELECT count(*) FROM t11;
}
} {12}
do_test like-11.1 {
queryplan {
PRAGMA case_sensitive_like=OFF;
SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
}
} {abc abcd ABC ABCD nosort t11 *}
do_test like-11.2 {
queryplan {
PRAGMA case_sensitive_like=ON;
SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
}
} {abc abcd nosort t11 *}
do_test like-11.3 {
queryplan {
PRAGMA case_sensitive_like=OFF;
CREATE INDEX t11b ON t11(b);
SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
}
} {abc abcd ABC ABCD sort {} t11b}
do_test like-11.4 {
queryplan {
PRAGMA case_sensitive_like=ON;
SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
}
} {abc abcd nosort t11 *}
do_test like-11.5 {
queryplan {
PRAGMA case_sensitive_like=OFF;
DROP INDEX t11b;
CREATE INDEX t11bnc ON t11(b COLLATE nocase);
SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
}
} {abc abcd ABC ABCD sort {} t11bnc}
do_test like-11.6 {
queryplan {
CREATE INDEX t11bb ON t11(b COLLATE binary);
SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
}
} {abc abcd ABC ABCD sort {} t11bnc}
do_test like-11.7 {
queryplan {
PRAGMA case_sensitive_like=ON;
SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a;
}
} {abc abcd sort {} t11bb}
do_test like-11.8 {
queryplan {
PRAGMA case_sensitive_like=OFF;
SELECT b FROM t11 WHERE b GLOB 'abc*' ORDER BY a;
}
} {abc abcd sort {} t11bb}
do_test like-11.9 {
queryplan {
CREATE INDEX t11cnc ON t11(c COLLATE nocase);
CREATE INDEX t11cb ON t11(c COLLATE binary);
SELECT c FROM t11 WHERE c LIKE 'abc%' ORDER BY a;
}
} {abc abcd ABC ABCD sort {} t11cnc}
do_test like-11.10 {
queryplan {
SELECT c FROM t11 WHERE c GLOB 'abc*' ORDER BY a;
}
} {abc abcd sort {} t11cb}
finish_test
+12 -6
View File
@@ -27,6 +27,8 @@ proc do_multiclient_test {varname script} {
set tn 2
}] {
faultsim_delete_and_reopen
proc code1 {tcl} { uplevel #0 $tcl }
# Open connections [db2] and [db3]. Depending on which iteration this
# is, the connections may be created in this interpreter, or in
@@ -63,15 +65,19 @@ proc do_multiclient_test {varname script} {
# channel name is returned that may be passed as the first argument to proc
# 'testfixture' to execute a command. The child testfixture process is shut
# down by closing the channel.
proc launch_testfixture {} {
proc launch_testfixture {{prg ""}} {
write_main_loop
set prg [info nameofexec]
if {$prg eq ""} {
set prg [file join . testfixture]
}
if {$prg eq ""} { set prg [info nameofexec] }
if {$prg eq ""} { set prg testfixture }
if {[file tail $prg]==$prg} { set prg [file join . $prg] }
set chan [open "|$prg tf_main.tcl" r+]
fconfigure $chan -buffering line
testfixture $chan "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
set rc [catch {
testfixture $chan "sqlite3_test_control_pending_byte $::sqlite_pending_byte"
}]
if {$rc} {
testfixture $chan "set ::sqlite_pending_byte $::sqlite_pending_byte"
}
return $chan
}
+51 -44
View File
@@ -92,50 +92,57 @@ set noerr {{0 {}}}
# it is possible to use the unlock-notify mechanism to determine when
# the ATTACH might succeed.
#
foreach {
tn
db1_loaded
db2_loaded
enable_extended_errors
result
error1 error2
} "
0 0 0 0 $err SQLITE_LOCKED SQLITE_LOCKED_SHAREDCACHE
1 0 0 1 $err SQLITE_LOCKED_SHAREDCACHE SQLITE_LOCKED_SHAREDCACHE
2 0 1 0 $err SQLITE_LOCKED SQLITE_LOCKED_SHAREDCACHE
3 0 1 1 $err SQLITE_LOCKED_SHAREDCACHE SQLITE_LOCKED_SHAREDCACHE
4 1 0 0 $err SQLITE_LOCKED SQLITE_LOCKED_SHAREDCACHE
5 1 0 1 $err SQLITE_LOCKED_SHAREDCACHE SQLITE_LOCKED_SHAREDCACHE
6 1 1 0 $noerr SQLITE_OK SQLITE_OK
7 1 1 1 $noerr SQLITE_OK SQLITE_OK
" {
do_test notify3-2.$tn.1 {
catch { db1 close }
catch { db2 close }
sqlite3 db1 test.db
sqlite3 db2 test.db2
sqlite3_extended_result_codes db1 $enable_extended_errors
sqlite3_extended_result_codes db2 $enable_extended_errors
if { $db1_loaded } { db1 eval "SELECT * FROM sqlite_master" }
if { $db2_loaded } { db2 eval "SELECT * FROM sqlite_master" }
db2 eval "BEGIN EXCLUSIVE"
catchsql "ATTACH 'test.db2' AS two" db1
} $result
do_test notify3-2.$tn.2 {
list [sqlite3_errcode db1] [sqlite3_extended_errcode db1]
} [list $error1 $error2]
do_test notify3-2.$tn.3 {
db1 unlock_notify {set invoked 1}
set invoked 0
db2 eval commit
set invoked
} [lindex $result 0]
# This test does not work for test-permutations that specify SQL to
# be executed as part of the [sqlite3] command that opens the database.
# Executing such SQL causes SQLite to load the database schema into memory
# earlier than expected, causing test cases to fail.
#
if {[presql] == ""} {
foreach {
tn
db1_loaded
db2_loaded
enable_extended_errors
result
error1 error2
} "
0 0 0 0 $err SQLITE_LOCKED SQLITE_LOCKED_SHAREDCACHE
1 0 0 1 $err SQLITE_LOCKED_SHAREDCACHE SQLITE_LOCKED_SHAREDCACHE
2 0 1 0 $err SQLITE_LOCKED SQLITE_LOCKED_SHAREDCACHE
3 0 1 1 $err SQLITE_LOCKED_SHAREDCACHE SQLITE_LOCKED_SHAREDCACHE
4 1 0 0 $err SQLITE_LOCKED SQLITE_LOCKED_SHAREDCACHE
5 1 0 1 $err SQLITE_LOCKED_SHAREDCACHE SQLITE_LOCKED_SHAREDCACHE
6 1 1 0 $noerr SQLITE_OK SQLITE_OK
7 1 1 1 $noerr SQLITE_OK SQLITE_OK
" {
do_test notify3-2.$tn.1 {
catch { db1 close }
catch { db2 close }
sqlite3 db1 test.db
sqlite3 db2 test.db2
sqlite3_extended_result_codes db1 $enable_extended_errors
sqlite3_extended_result_codes db2 $enable_extended_errors
if { $db1_loaded } { db1 eval "SELECT * FROM sqlite_master" }
if { $db2_loaded } { db2 eval "SELECT * FROM sqlite_master" }
db2 eval "BEGIN EXCLUSIVE"
catchsql "ATTACH 'test.db2' AS two" db1
} $result
do_test notify3-2.$tn.2 {
list [sqlite3_errcode db1] [sqlite3_extended_errcode db1]
} [list $error1 $error2]
do_test notify3-2.$tn.3 {
db1 unlock_notify {set invoked 1}
set invoked 0
db2 eval commit
set invoked
} [lindex $result 0]
}
}
catch { db1 close }
catch { db2 close }
+108 -3
View File
@@ -15,7 +15,7 @@ source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl
# 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).
#
@@ -502,7 +502,7 @@ foreach {tn ofst value result} {
7 24 511 {1 2 3 4}
8 24 513 {1 2 3 4}
9 24 65536 {1 2 3 4}
9 24 131072 {1 2 3 4}
10 32 65536 {1 2}
} {
@@ -1062,6 +1062,10 @@ do_execsql_test pager1-6.8 {
} {11}
do_execsql_test pager1-6.9 { COMMIT } {}
do_execsql_test pager1-6.10 { PRAGMA max_page_count = 10 } {10}
do_execsql_test pager1-6.11 { SELECT * FROM t11 } {1 2 3 4}
do_execsql_test pager1-6.12 { PRAGMA max_page_count } {11}
#-------------------------------------------------------------------------
# The following tests work with "PRAGMA journal_mode=TRUNCATE" and
@@ -1742,7 +1746,7 @@ do_multiclient_test tn {
}
} {1 2 3 4 5 6}
do_test pager1-17.$tn.3.2 {
csql1 { INSERT INTO t1 VALUES(3, 4) }
csql1 { INSERT INTO t1 VALUES(3, 4) }
} {1 {database is locked}}
do_test pager1-17.$tn.3.3 { sql2 COMMIT } {}
}
@@ -2232,6 +2236,7 @@ db close
tv delete
#-------------------------------------------------------------------------
#
do_test pager1.27.1 {
faultsim_delete_and_reopen
sqlite3_pager_refcounts db
@@ -2243,4 +2248,104 @@ do_test pager1.27.1 {
execsql COMMIT
} {}
#-------------------------------------------------------------------------
# Test that attempting to open a write-transaction with
# locking_mode=exclusive in WAL mode fails if there are other clients on
# the same database.
#
catch { db close }
do_multiclient_test tn {
do_test pager1-28.$tn.1 {
sql1 {
PRAGMA journal_mode = WAL;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES('a', 'b');
}
} {wal}
do_test pager1-28.$tn.2 { sql2 { SELECT * FROM t1 } } {a b}
do_test pager1-28.$tn.3 { sql1 { PRAGMA locking_mode=exclusive } } {exclusive}
do_test pager1-28.$tn.4 {
csql1 { BEGIN; INSERT INTO t1 VALUES('c', 'd'); }
} {1 {database is locked}}
code2 { db2 close ; sqlite3 db2 test.db }
do_test pager1-28.$tn.4 {
sql1 { INSERT INTO t1 VALUES('c', 'd'); COMMIT }
} {}
}
#-------------------------------------------------------------------------
# Normally, when changing from journal_mode=PERSIST to DELETE the pager
# attempts to delete the journal file. However, if it cannot obtain a
# RESERVED lock on the database file, this step is skipped.
#
do_multiclient_test tn {
do_test pager1-28.$tn.1 {
sql1 {
PRAGMA journal_mode = PERSIST;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES('a', 'b');
}
} {persist}
do_test pager1-28.$tn.2 { file exists test.db-journal } 1
do_test pager1-28.$tn.3 { sql1 { PRAGMA journal_mode = DELETE } } delete
do_test pager1-28.$tn.4 { file exists test.db-journal } 0
do_test pager1-28.$tn.5 {
sql1 {
PRAGMA journal_mode = PERSIST;
INSERT INTO t1 VALUES('c', 'd');
}
} {persist}
do_test pager1-28.$tn.6 { file exists test.db-journal } 1
do_test pager1-28.$tn.7 {
sql2 { BEGIN; INSERT INTO t1 VALUES('e', 'f'); }
} {}
do_test pager1-28.$tn.8 { file exists test.db-journal } 1
do_test pager1-28.$tn.9 { sql1 { PRAGMA journal_mode = DELETE } } delete
do_test pager1-28.$tn.10 { file exists test.db-journal } 1
do_test pager1-28.$tn.11 { sql2 COMMIT } {}
do_test pager1-28.$tn.12 { file exists test.db-journal } 0
do_test pager1-28-$tn.13 {
code1 { set channel [db incrblob -readonly t1 a 2] }
sql1 {
PRAGMA journal_mode = PERSIST;
INSERT INTO t1 VALUES('g', 'h');
}
} {persist}
do_test pager1-28.$tn.14 { file exists test.db-journal } 1
do_test pager1-28.$tn.15 {
sql2 { BEGIN; INSERT INTO t1 VALUES('e', 'f'); }
} {}
do_test pager1-28.$tn.16 { sql1 { PRAGMA journal_mode = DELETE } } delete
do_test pager1-28.$tn.17 { file exists test.db-journal } 1
do_test pager1-28.$tn.17 { csql2 { COMMIT } } {1 {database is locked}}
do_test pager1-28-$tn.18 { code1 { read $channel } } c
do_test pager1-28-$tn.19 { code1 { close $channel } } {}
do_test pager1-28.$tn.20 { sql2 { COMMIT } } {}
}
do_test pager1-29.1 {
faultsim_delete_and_reopen
execsql {
PRAGMA page_size = 1024;
PRAGMA auto_vacuum = full;
PRAGMA locking_mode=exclusive;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
}
file size test.db
} [expr 1024*3]
do_test pager1-29.2 {
execsql {
PRAGMA page_size = 4096;
VACUUM;
}
file size test.db
} [expr 4096*3]
finish_test
+32
View File
@@ -116,4 +116,36 @@ foreach code [list {
db close
tv delete
#-------------------------------------------------------------------------
#
# pager2-2.1: Test a ROLLBACK with journal_mode=off.
# pager2-2.2: Test shrinking the database (auto-vacuum) with
# journal_mode=off
#
do_test pager2-2.1 {
faultsim_delete_and_reopen
execsql {
CREATE TABLE t1(a, b);
PRAGMA journal_mode = off;
BEGIN;
INSERT INTO t1 VALUES(1, 2);
ROLLBACK;
SELECT * FROM t1;
}
} {off 1 2}
do_test pager2-2.2 {
faultsim_delete_and_reopen
execsql {
PRAGMA auto_vacuum = incremental;
PRAGMA page_size = 1024;
PRAGMA journal_mode = off;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(zeroblob(5000), zeroblob(5000));
DELETE FROM t1;
PRAGMA incremental_vacuum;
}
file size test.db
} {3072}
finish_test
+33
View File
@@ -0,0 +1,33 @@
# 2010 June 15
#
# 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
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl
foreach {tn sql res j} {
1 "PRAGMA journal_mode = DELETE" delete 0
2 "CREATE TABLE t1(a, b)" {} 0
3 "PRAGMA locking_mode=EXCLUSIVE" {exclusive} 0
4 "INSERT INTO t1 VALUES(1, 2)" {} 1
5 "PRAGMA locking_mode=NORMAL" {normal} 1
6 "SELECT * FROM t1" {1 2} 0
} {
do_execsql_test pager3-1.$tn.1 $sql $res
do_test pager3-1.$tn.2 { file exists test.db-journal } $j
}
finish_test
+156 -1
View File
@@ -52,7 +52,7 @@ do_faultsim_test pagerfault-1 -prep {
} -body {
execsql { SELECT count(*) FROM t1 }
} -test {
faultsim_test_result {0 4}
faultsim_test_result {0 4}
faultsim_integrity_check
if {[db one { SELECT count(*) FROM t1 }] != 4} {
error "Database content appears incorrect"
@@ -1078,4 +1078,159 @@ do_faultsim_test pagerfault-22 -prep {
faultsim_integrity_check
}
#-------------------------------------------------------------------------
# Provoke an OOM error during a commit of multi-file transaction. One of
# the databases written during the transaction is an in-memory database.
# This test causes rollback of the in-memory database after CommitPhaseOne()
# has successfully returned. i.e. the series of calls for the aborted commit
# is:
#
# PagerCommitPhaseOne(<in-memory-db>) -> SQLITE_OK
# PagerCommitPhaseOne(<file-db>) -> SQLITE_IOERR
# PagerRollback(<in-memory-db>)
# PagerRollback(<file-db>)
#
do_faultsim_test pagerfault-23 -prep {
foreach f [glob -nocomplain test.db*] { file delete -force $f }
sqlite3 db :memory:
db eval {
ATTACH 'test.db2' AS aux;
CREATE TABLE t1(a, b);
CREATE TABLE aux.t2(a, b);
}
} -body {
execsql {
BEGIN;
INSERT INTO t1 VALUES(1,2);
INSERT INTO t2 VALUES(3,4);
COMMIT;
}
} -test {
faultsim_test_result {0 {}}
faultsim_integrity_check
}
do_faultsim_test pagerfault-24 -prep {
faultsim_delete_and_reopen
db eval { PRAGMA temp_store = file }
execsql { CREATE TABLE x(a, b) }
} -body {
execsql { CREATE TEMP TABLE t1(a, b) }
} -test {
faultsim_test_result {0 {}} \
{1 {unable to open a temporary database file for storing temporary tables}}
set ic [db eval { PRAGMA temp.integrity_check }]
if {$ic != "ok"} { error "Integrity check: $ic" }
}
proc lockrows {n} {
if {$n==0} { return "" }
db eval { SELECT * FROM t1 WHERE oid = $n } {
return [lockrows [expr {$n-1}]]
}
}
do_test pagerfault-25-pre1 {
faultsim_delete_and_reopen
db func a_string a_string
execsql {
PRAGMA page_size = 1024;
PRAGMA auto_vacuum = 0;
CREATE TABLE t1(a);
INSERT INTO t1 VALUES(a_string(500));
INSERT INTO t1 SELECT a_string(500) FROM t1;
INSERT INTO t1 SELECT a_string(500) FROM t1;
INSERT INTO t1 SELECT a_string(500) FROM t1;
INSERT INTO t1 SELECT a_string(500) FROM t1;
INSERT INTO t1 SELECT a_string(500) FROM t1;
}
faultsim_save_and_close
} {}
do_faultsim_test pagerfault-25 -prep {
faultsim_restore_and_reopen
db func a_string a_string
set ::channel [db incrblob -readonly t1 a 1]
execsql {
PRAGMA cache_size = 10;
BEGIN;
INSERT INTO t1 VALUES(a_string(3000));
INSERT INTO t1 VALUES(a_string(3000));
}
} -body {
lockrows 30
} -test {
catch { lockrows 30 }
catch { db eval COMMIT }
close $::channel
faultsim_test_result {0 {}}
}
do_faultsim_test pagerfault-26 -prep {
faultsim_delete_and_reopen
execsql {
PRAGMA page_size = 1024;
PRAGMA journal_mode = truncate;
PRAGMA auto_vacuum = full;
PRAGMA locking_mode=exclusive;
CREATE TABLE t1(a, b);
INSERT INTO t1 VALUES(1, 2);
PRAGMA page_size = 4096;
}
} -body {
execsql {
VACUUM;
}
} -test {
faultsim_test_result {0 {}}
set contents [db eval {SELECT * FROM t1}]
if {$contents != "1 2"} { error "Bad database contents ($contents)" }
set sz [file size test.db]
if {$testrc!=0 && $sz!=1024*3 && $sz!=4096*3} {
error "Expected file size to be 3072 or 12288 bytes - actual size $sz bytes"
}
if {$testrc==0 && $sz!=4096*3} {
error "Expected file size to be 12288 bytes - actual size $sz bytes"
}
}
do_test pagerfault-27-pre {
faultsim_delete_and_reopen
db func a_string a_string
execsql {
PRAGMA page_size = 1024;
CREATE TABLE t1(a, b);
CREATE TABLE t2(a UNIQUE, b UNIQUE);
INSERT INTO t2 VALUES( a_string(800), a_string(800) );
INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
INSERT INTO t2 SELECT a_string(800), a_string(800) FROM t2;
INSERT INTO t1 VALUES (a_string(20000), a_string(20000));
}
faultsim_save_and_close
} {}
do_faultsim_test pagerfault-27 -faults ioerr-persistent -prep {
faultsim_restore_and_reopen
db func a_string a_string
execsql {
PRAGMA cache_size = 10;
BEGIN EXCLUSIVE;
}
set ::channel [db incrblob t1 a 1]
} -body {
puts $::channel [string repeat abc 6000]
flush $::channel
} -test {
catchsql { UPDATE t2 SET a = a_string(800), b = a_string(800) }
catch { close $::channel }
catchsql { ROLLBACK }
faultsim_integrity_check
}
finish_test
+1 -1
View File
@@ -129,7 +129,7 @@ test_suite "veryquick" -prefix "" -description {
This test suite is the same as the "quick" tests, except that some files
that test malloc and IO errors are omitted.
} -files [
test_set $allquicktests -exclude *malloc* *ioerr* *fault*
test_set $allquicktests -exclude *malloc* *ioerr* *fault*
]
test_suite "quick" -prefix "" -description {
+23
View File
@@ -210,4 +210,27 @@ do_test selectC-3.3 {
}
} {xxx abcxxx yyy defyyy}
proc udf {} { incr ::udf }
set ::udf 0
db function udf udf
do_execsql_test selectC-4.1 {
create table t_distinct_bug (a, b, c);
insert into t_distinct_bug values ('1', '1', 'a');
insert into t_distinct_bug values ('1', '2', 'b');
insert into t_distinct_bug values ('1', '3', 'c');
insert into t_distinct_bug values ('1', '1', 'd');
insert into t_distinct_bug values ('1', '2', 'e');
insert into t_distinct_bug values ('1', '3', 'f');
} {}
do_execsql_test selectC-4.2 {
select a from (select distinct a, b from t_distinct_bug)
} {1 1 1}
do_execsql_test selectC-4.3 {
select a, udf() from (select distinct a, b from t_distinct_bug)
} {1 1 1 2 1 3}
finish_test

Some files were not shown because too many files have changed in this diff Show More