Compare commits

..

46 Commits

Author SHA1 Message Date
mistachkin 14b60775ab Use 'binary' mode for popen with MSVC.
FossilOrigin-Name: 7b84641e55654f8e81b62893d0bb66b12dedfcf2
2015-06-17 19:06:23 +00:00
mistachkin 073664de88 Improve spacing and comment style for the shell. No changes to code.
FossilOrigin-Name: 5b547da00d131a494a6b348339af3d91dfa6e3b6
2015-06-17 18:57:37 +00:00
drh 00452196d8 Improved comments on the fuzzcheck.c test program. No changes to code.
FossilOrigin-Name: a7e27d19280048bcfff6d2e796eed72287b9dabe
2015-06-17 18:24:40 +00:00
drh bbe031f9f1 Fix a uninitialized variable use in the command-line shell when the
".open" command is invoked without any arguments.

FossilOrigin-Name: fc4f4d1eccec2e09b5d2e6c4da082204f4d5a016
2015-06-17 17:08:22 +00:00
drh b0870486aa Performance optimization and comment fixes for the LIKE and GLOB operators.
FossilOrigin-Name: c89d772628564a808173f6f73bc1798ec714276b
2015-06-17 13:20:54 +00:00
drh c5b41ac8ee Make getCellInfo() a real function instead of a macro, for a size reduction
and a 0.2% performance gain.

FossilOrigin-Name: 55c393ea14197ae5fa56ebca7a47e7d980511fa7
2015-06-17 02:11:46 +00:00
drh f1aabd6b78 Optimizations to two VDBE accessory routines for a 0.2% performance increase.
FossilOrigin-Name: 66d033b9c9a8c16b9a342be0b325bd85b8487c03
2015-06-17 01:31:28 +00:00
drh 0dd5cdaea5 Ensure that the CREATE TABLE AS statement correctly undoes partial changes
to the sqlite_master table if the SELECT on the right-hand side aborts with
an error.  Fix for ticket [873cae2b6e25b]

FossilOrigin-Name: 400e025e7c61efab71b891743c07a0862e5bb934
2015-06-16 16:39:01 +00:00
drh 07d694c750 Adjust ICU tests to account for recent changes in the official
Unicode definition of whitespace.

FossilOrigin-Name: 0816525386ac51454b7b09a507e45b6a2cb8bf6e
2015-06-15 16:40:38 +00:00
drh 3e24a34324 Fix a harmless comment typo. No code changes.
FossilOrigin-Name: ae6876521819e7a8ce473c8f96617cba35e2156d
2015-06-15 16:09:35 +00:00
drh f5ed7ad63e Fix harmless compiler warnings.
FossilOrigin-Name: b0badb99023e23bef0e2064cec58f2b279af0c0b
2015-06-15 14:43:25 +00:00
drh e4d38707ea Improved detection of database corruption in freeSpace().
FossilOrigin-Name: 29bcb56887f862a1f06677a7b4bfae6475d29732
2015-06-15 12:58:15 +00:00
drh c056e4b257 Comment typo fix. No code changes.
FossilOrigin-Name: 17f185adb960b1fa4faa13cdf685b92a20a52072
2015-06-15 10:49:01 +00:00
drh 74a043607e Omit mutex calls in pcache1 when the mutex is NULL, for a significant
performance improvement.

FossilOrigin-Name: caf8f574e5c64da461c6dfba8a06cf3fb18aaa42
2015-06-13 11:19:47 +00:00
drh 982215a2c5 Avoid unnecessary mutex usage in pcache1, for a significant speedup.
FossilOrigin-Name: dcf4fb8d764611de60afea27cda0a8548ba7ca82
2015-06-13 11:10:55 +00:00
drh 55a46c9b0e Add a fast-path implementation of pcache1Fetch() for the common case of
separate caches that do not use a mutex.

FossilOrigin-Name: 760700edb3ff1f5d6bf3058f874cc8e2808905c7
2015-06-12 13:49:26 +00:00
drh b230a52892 Minor performance optimization in pcache1.c.
FossilOrigin-Name: 2e8ad2ead9d146e312c693d9b967bbd5b92429d9
2015-06-12 13:04:51 +00:00
drh 36b80349b7 Add the OP_ColumnsUsed opcode (when compiled with
SQLITE_ENABLE_COLUMN_USED_MASK) as a hint to the b-tree layer as to which
columns of a btree cursor will be used.

FossilOrigin-Name: 711a176cbfad5dde6defa9648fba6d0d663af134
2015-06-12 12:54:15 +00:00
drh aca55cfec3 Remove stray outputs from the test suite.
FossilOrigin-Name: afc6db9b105f32110112b877f06091757888a5f2
2015-06-11 14:19:05 +00:00
drh 72bc8208f0 When generating code for partial indexes, be sure not to modify the
index condition expression in the schema.

FossilOrigin-Name: e63d01c69c3e50f49ee3022a519c4f3e91f00520
2015-06-11 13:58:35 +00:00
mistachkin eeb31ff59b More test output refinements.
FossilOrigin-Name: e64a5681793238fa04fe3636f48d34b2dd36cdfa
2015-06-10 23:02:38 +00:00
mistachkin 7b96f2fa7e Remove possibly stray output from various tests.
FossilOrigin-Name: f38e0be56fc086a3ce08134ade83ab61c9fca106
2015-06-10 22:51:02 +00:00
mistachkin 033eb6c8d3 Fix minor typo in the quicktest MSVC makefile target.
FossilOrigin-Name: 75b65f9d49daaf48e97042cb82ea554e2ec74eec
2015-06-10 22:03:40 +00:00
drh 905da63a82 "test" targets on all makefiles use --verbose=file --output=test-out.txt.
Add the new "quicktest" target to all makefiles - designed to run in under
three minutes.  The --quick option on releasetest.tcl now uses quicktest.

FossilOrigin-Name: 6ddef2ad35ceb5822fc14c65bc7c6a2662edb63c
2015-06-10 18:53:09 +00:00
dan 84dff7a20e Avoid passing constraints that are unusable due to LEFT or CROSS joins to virtual table xBestIndex() methods.
FossilOrigin-Name: 7b446771cadedafbe8924ad0658adc2597816dc7
2015-06-10 14:27:40 +00:00
dan 17c0823bda Add the --output=$file and --verbose=(0|1|file) options to tester.tcl.
FossilOrigin-Name: f7b2c70362f10ee0347c1d2318918ffefa53243d
2015-06-09 15:58:28 +00:00
dan 4430b40934 Remove some repeated lines of source code. Probably introduced by careless cut'n'pasting.
FossilOrigin-Name: a34cd71c8aafaece04a2332a127e9b8e99c1403c
2015-06-09 10:58:51 +00:00
drh d1f2f9b90c Add the valgrindfuzz target to unix makefile.
FossilOrigin-Name: e62aed01f1a6dbc12d6e21386c1671eb640b8d49
2015-06-08 19:15:50 +00:00
dan 35175bf7ab If a query contains "FROM t1 LEFT JOIN t2, t3, t4", ensure that tables t3 and t4 are not scanned before t2. The trunk already does this.
FossilOrigin-Name: 0d9edfab9fb61322620f188b48ae2a1798a07581
2015-06-08 18:48:29 +00:00
dan 4f20cd402b Avoid passing constraints that are unusable due to LEFT or CROSS joins to virtual table xBestIndex() methods.
FossilOrigin-Name: 80ee56dda7db3860f8be5f6968c8745138f8453f
2015-06-08 18:05:54 +00:00
mistachkin f5b5f9b972 Fix typo in comment. No changes to code.
FossilOrigin-Name: e49c291735e613e384f6da044ef865dd274cabc8
2015-06-08 17:42:57 +00:00
drh 6dcb2dbaf6 Split out some source code into new files: wherecode.c, whereexpr.c, and
treeview.c.  Other minor refactoring changes.

FossilOrigin-Name: 50f336818c8509d8b8bde282e9399d2b2b5ea70a
2015-06-08 17:40:30 +00:00
drh 38b4149ca1 Factor out the TreeView parse tree printing module into a separate file.
FossilOrigin-Name: c32ce54ca46a4be4373983be6fd44b1f3a0250d1
2015-06-08 15:08:15 +00:00
drh 6c1f4ef217 Split more subfunctions of where.c out into a new whereexpr.c source file,
for improved maintainability.

FossilOrigin-Name: 46ef95c108ad8961f2bf3d2dc839d4fb1fddd770
2015-06-08 14:23:15 +00:00
drh 6f82e85a80 Split out the bulk of the actual VDBE code generation logic from where.c
into a new file, leaving behind the analysis logic.  This makes the original
where.c smaller and hopefully easier to edit.

FossilOrigin-Name: faa0e420e93a2bc1c84df9eb9fef4748d29ce339
2015-06-06 20:12:09 +00:00
drh b121dd14ac Code simplifications in select.c and where.c.
FossilOrigin-Name: 4f20ac90bce8bd7ba43ef59af5cc4ef7aa282fe8
2015-06-06 18:30:17 +00:00
drh adc57f6834 Minor cleanup of the sqlite3Select() procedure.
FossilOrigin-Name: f4c90d06bb941453d8110680c7b279e471e8f034
2015-06-06 00:18:01 +00:00
drh 4490c40b90 Split FROM-clause subquery flattening and code generation into separate loops.
FossilOrigin-Name: be8e3fc70e4c13b28b07985df3457960f58ffddd
2015-06-05 22:33:39 +00:00
drh bc8edba10a Provide one final Select tree dump prior to WHERE clause analysis
when ".selecttrace 0x400" tracing bit is set with SELECTTRACE_ENABLED.
Analysis and debug changes only - normal builds are unaffected.

FossilOrigin-Name: 283bf0b64da7acc5aa5812fc659954965002d409
2015-06-05 20:27:26 +00:00
drh 97bae794c2 Add a new opcode to the VDBE that gives the b-tree a hint about the set
of columns in a table or index that are actually used by the query.

FossilOrigin-Name: f167bba446b78dd7538d0b2bae3e6678f3b1ba28
2015-06-05 15:59:57 +00:00
drh d62fbb50e6 Change the name of SrcList.a[].zIndex to the more descriptive
SrcList.a[0].zIndexedBy.

FossilOrigin-Name: 6a9cf063379118dbb95c6cdc6d60af50e9867177
2015-06-04 12:08:53 +00:00
drh 24dee9d214 Always check for cell overflow before returning a slot from the
pageFindSlot routine in btree.c.

FossilOrigin-Name: 9f035c45a4b84203e67b6e1b23cf11691dc43f1e
2015-06-02 19:36:29 +00:00
drh 4c393a82df For FROM-clause subqueries that cannot be flattened, try to push relevant
WHERE clause terms of the outer query down into the subquery in order to help
the subquery run faster and/or use less memory.

FossilOrigin-Name: 6df18e949d3676290785143993513ea1b917d729
2015-06-02 18:09:18 +00:00
drh 467c1c70fb Add test cases for type affinity rules.
FossilOrigin-Name: 9678646d9a14ba283a83839be329599a676a537a
2015-06-02 17:25:05 +00:00
drh a88994ee57 Rename SQLITE_AFF_NONE to SQLITE_AFF_BLOB to avoid confusion with
"no affinity".

FossilOrigin-Name: 29ad9e917330969810ac1bc685bba4282401bdae
2015-06-02 16:19:56 +00:00
drh 69b72d5a29 For FROM-clause subqueries that cannot be flattened, try to push WHERE clause
terms of the outer query down into the subquery in order to help the subquery
run faster and/or use less memory.

FossilOrigin-Name: 297fae7551a2af9e600d833801ff79fca0602ad5
2015-06-01 20:28:03 +00:00
60 changed files with 4502 additions and 3726 deletions
+38 -12
View File
@@ -181,10 +181,11 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
table.lo threads.lo tokenize.lo trigger.lo \
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
update.lo util.lo vacuum.lo \
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo
vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
utf.lo vtab.lo
# Object files for the amalgamation.
#
@@ -273,6 +274,7 @@ SRC = \
$(TOP)/src/threads.c \
$(TOP)/src/tclsqlite.c \
$(TOP)/src/tokenize.c \
$(TOP)/src/treeview.c \
$(TOP)/src/trigger.c \
$(TOP)/src/utf.c \
$(TOP)/src/update.c \
@@ -293,6 +295,8 @@ SRC = \
$(TOP)/src/wal.h \
$(TOP)/src/walker.c \
$(TOP)/src/where.c \
$(TOP)/src/wherecode.c \
$(TOP)/src/whereexpr.c \
$(TOP)/src/whereInt.h
# Source code for extensions
@@ -454,6 +458,8 @@ TESTSRC2 = \
$(TOP)/src/vdbemem.c \
$(TOP)/src/vdbetrace.c \
$(TOP)/src/where.c \
$(TOP)/src/wherecode.c \
$(TOP)/src/whereexpr.c \
parse.c \
$(TOP)/ext/fts3/fts3.c \
$(TOP)/ext/fts3/fts3_aux.c \
@@ -529,6 +535,10 @@ FUZZDATA = \
$(TOP)/test/fuzzdata2.db \
$(TOP)/test/fuzzdata3.db
# Standard options to testfixture
#
TESTOPTS = --verbose=file --output=test-out.txt
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
#
@@ -801,6 +811,9 @@ threads.lo: $(TOP)/src/threads.c $(HDR)
tokenize.lo: $(TOP)/src/tokenize.c keywordhash.h $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/tokenize.c
treeview.lo: $(TOP)/src/treeview.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/treeview.c
trigger.lo: $(TOP)/src/trigger.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/trigger.c
@@ -849,6 +862,12 @@ walker.lo: $(TOP)/src/walker.c $(HDR)
where.lo: $(TOP)/src/where.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/where.c
wherecode.lo: $(TOP)/src/wherecode.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/wherecode.c
whereexpr.lo: $(TOP)/src/whereexpr.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/whereexpr.c
tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR)
$(LTCOMPILE) -DUSE_TCL_STUBS=1 -c $(TOP)/src/tclsqlite.c
@@ -978,39 +997,46 @@ testfixture$(TEXE): $(TESTFIXTURE_SRC)
# A very detailed test running most or all test cases
fulltest: $(TESTPROGS) fuzztest
./testfixture$(TEXE) $(TOP)/test/all.test
./testfixture$(TEXE) $(TOP)/test/all.test $(TESTOPTS)
# Really really long testing
soaktest: $(TESTPROGS)
./testfixture$(TEXE) $(TOP)/test/all.test -soak=1
./testfixture$(TEXE) $(TOP)/test/all.test -soak=1 $(TESTOPTS)
# Do extra testing but not everything.
fulltestonly: $(TESTPROGS)
./testfixture$(TEXE) $(TOP)/test/full.test
# Fuzz testing
fuzztest: fuzzcheck$(TEXE)
fuzztest: fuzzcheck$(TEXE) $(FUZZDATA)
./fuzzcheck$(TEXE) $(FUZZDATA)
# This is the common case. Run many tests but not those that take
# a really long time.
valgrindfuzz: fuzzcheck$(TEXT) $(FUZZDATA)
valgrind ./fuzzcheck$(TEXE) --cell-size-check --quiet $(FUZZDATA)
# Minimal testing that runs in less than 3 minutes
#
quicktest: ./testfixture$(TEXE)
./testfixture$(TEXE) $(TOP)/test/extraquick.test $(TESTOPTS)
# This is the common case. Run many tests that do not take too long,
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
#
test: $(TESTPROGS) fuzztest
./testfixture$(TEXE) $(TOP)/test/veryquick.test
./testfixture$(TEXE) $(TOP)/test/veryquick.test $(TESTOPTS)
# Run a test using valgrind. This can take a really long time
# because valgrind is so much slower than a native machine.
#
valgrindtest: $(TESTPROGS) fuzzcheck$(TEXE)
valgrind -v ./fuzzcheck$(TEXE) --cell-size-check --quiet $(FUZZDATA)
OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind
valgrindtest: $(TESTPROGS) valgrindfuzz
OMIT_MISUSE=1 valgrind -v ./testfixture$(TEXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS)
# A very fast test that checks basic sanity. The name comes from
# the 60s-era electronics testing: "Turn it on and see if smoke
# comes out."
#
smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
./testfixture$(TEXE) $(TOP)/test/main.test
./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
echo "#define TCLSH 2" > $@
+34 -8
View File
@@ -835,10 +835,11 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
table.lo threads.lo tokenize.lo trigger.lo \
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
update.lo util.lo vacuum.lo \
vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo
vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \
utf.lo vtab.lo
# Object files for the amalgamation.
#
@@ -939,6 +940,7 @@ SRC2 = \
$(TOP)\src\threads.c \
$(TOP)\src\tclsqlite.c \
$(TOP)\src\tokenize.c \
$(TOP)\src\treeview.c \
$(TOP)\src\trigger.c \
$(TOP)\src\utf.c \
$(TOP)\src\update.c \
@@ -959,6 +961,8 @@ SRC2 = \
$(TOP)\src\wal.h \
$(TOP)\src\walker.c \
$(TOP)\src\where.c \
$(TOP)\src\wherecode.c \
$(TOP)\src\whereexpr.c \
$(TOP)\src\whereInt.h
# Source code for extensions
@@ -1121,6 +1125,8 @@ TESTSRC2 = \
$(TOP)\src\vdbesort.c \
$(TOP)\src\vdbetrace.c \
$(TOP)\src\where.c \
$(TOP)\src\wherecode.c \
$(TOP)\src\whereexpr.c \
parse.c \
$(TOP)\ext\fts3\fts3.c \
$(TOP)\ext\fts3\fts3_aux.c \
@@ -1197,6 +1203,9 @@ FUZZDATA = \
$(TOP)\test\fuzzdata2.db \
$(TOP)\test\fuzzdata3.db
# Standard options to testfixture
#
TESTOPTS = --verbose=file --output=test-out.txt
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
@@ -1482,6 +1491,9 @@ threads.lo: $(TOP)\src\threads.c $(HDR)
tokenize.lo: $(TOP)\src\tokenize.c keywordhash.h $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\tokenize.c
treeview.lo: $(TOP)\src\treeview.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\treeview.c
trigger.lo: $(TOP)\src\trigger.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\trigger.c
@@ -1530,6 +1542,12 @@ walker.lo: $(TOP)\src\walker.c $(HDR)
where.lo: $(TOP)\src\where.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\where.c
wherecode.lo: $(TOP)\src\wherecode.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\wherecode.c
whereexpr.lo: $(TOP)\src\whereexpr.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\whereexpr.c
tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR)
$(LTCOMPILE) $(NO_WARN) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
@@ -1662,28 +1680,36 @@ testfixture.exe: $(TESTFIXTURE_SRC) $(LIBRESOBJS) $(HDR)
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
extensiontest: testfixture.exe testloadext.dll
.\testfixture.exe $(TOP)\test\loadext.test
.\testfixture.exe $(TOP)\test\loadext.test $(TESTOPTS)
fulltest: $(TESTPROGS) fuzztest
.\testfixture.exe $(TOP)\test\all.test
.\testfixture.exe $(TOP)\test\all.test $(TESTOPTS)
soaktest: $(TESTPROGS)
.\testfixture.exe $(TOP)\test\all.test -soak=1
.\testfixture.exe $(TOP)\test\all.test -soak=1 $(TESTOPTS)
fulltestonly: $(TESTPROGS) fuzztest
.\testfixture.exe $(TOP)\test\full.test
queryplantest: testfixture.exe sqlite3.exe
.\testfixture.exe $(TOP)\test\permutations.test queryplanner
.\testfixture.exe $(TOP)\test\permutations.test queryplanner $(TESTOPTS)
fuzztest: fuzzcheck.exe
.\fuzzcheck.exe $(FUZZDATA)
# Minimal testing that runs in less than 3 minutes (on a fast machine)
#
quicktest: testfixture.exe
.\testfixture.exe $(TOP)\test\extraquick.test $(TESTOPTS)
# This is the common case. Run many tests that do not take too long,
# including fuzzcheck, sqlite3_analyzer, and sqldiff tests.
#
test: $(TESTPROGS) fuzztest
.\testfixture.exe $(TOP)\test\veryquick.test
.\testfixture.exe $(TOP)\test\veryquick.test $(TESTOPTS)
smoketest: $(TESTPROGS)
.\testfixture.exe $(TOP)\test\main.test
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
echo #define TCLSH 2 > $@
+7 -6
View File
@@ -240,12 +240,13 @@ static int icuNext(
** The set of routines that implement the simple tokenizer
*/
static const sqlite3_tokenizer_module icuTokenizerModule = {
0, /* iVersion */
icuCreate, /* xCreate */
icuDestroy, /* xCreate */
icuOpen, /* xOpen */
icuClose, /* xClose */
icuNext, /* xNext */
0, /* iVersion */
icuCreate, /* xCreate */
icuDestroy, /* xCreate */
icuOpen, /* xOpen */
icuClose, /* xClose */
icuNext, /* xNext */
0, /* xLanguageid */
};
/*
+1 -1
View File
@@ -83,7 +83,6 @@ static int icuLikeCompare(
/* Read (and consume) the next character from the input pattern. */
UChar32 uPattern;
U8_NEXT_UNSAFE(zPattern, iPattern, uPattern);
assert(uPattern!=0);
/* There are now 4 possibilities:
**
@@ -422,6 +421,7 @@ static void icuLoadCollation(
int rc; /* Return code from sqlite3_create_collation_x() */
assert(nArg==2);
(void)nArg; /* Unused parameter */
zLocale = (const char *)sqlite3_value_text(apArg[0]);
zName = (const char *)sqlite3_value_text(apArg[1]);
+83
View File
@@ -269,5 +269,88 @@ ifcapable rtree {
db close
}
#--------------------------------------------------------------------
# Test that queries featuring LEFT or CROSS JOINS are handled correctly.
# Handled correctly in this case means:
#
# * Terms with prereqs that appear to the left of a LEFT JOIN against
# the virtual table are always available to xBestIndex.
#
# * Terms with prereqs that appear to the right of a LEFT JOIN against
# the virtual table are never available to xBestIndex.
#
# And the same behaviour for CROSS joins.
#
reset_db
do_execsql_test 7.0 {
CREATE TABLE xdir(x1);
CREATE TABLE ydir(y1);
CREATE VIRTUAL TABLE rt USING rtree_i32(id, xmin, xmax, ymin, ymax);
INSERT INTO xdir VALUES(5);
INSERT INTO ydir VALUES(10);
INSERT INTO rt VALUES(1, 2, 7, 12, 14); -- Not a hit
INSERT INTO rt VALUES(2, 2, 7, 8, 12); -- A hit!
INSERT INTO rt VALUES(3, 7, 11, 8, 12); -- Not a hit!
INSERT INTO rt VALUES(4, 5, 5, 10, 10); -- A hit!
}
proc do_eqp_execsql_test {tn sql res} {
set query "EXPLAIN QUERY PLAN $sql ; $sql "
uplevel [list do_execsql_test $tn $query $res]
}
do_eqp_execsql_test 7.1 {
SELECT id FROM xdir, rt, ydir
ON (y1 BETWEEN ymin AND ymax)
WHERE (x1 BETWEEN xmin AND xmax);
} {
0 0 0 {SCAN TABLE xdir}
0 1 2 {SCAN TABLE ydir}
0 2 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1}
2 4
}
do_eqp_execsql_test 7.2 {
SELECT * FROM xdir, rt LEFT JOIN ydir
ON (y1 BETWEEN ymin AND ymax)
WHERE (x1 BETWEEN xmin AND xmax);
} {
0 0 0 {SCAN TABLE xdir}
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
0 2 2 {SCAN TABLE ydir}
5 1 2 7 12 14 {}
5 2 2 7 8 12 10
5 4 5 5 10 10 10
}
do_eqp_execsql_test 7.3 {
SELECT id FROM xdir, rt CROSS JOIN ydir
ON (y1 BETWEEN ymin AND ymax)
WHERE (x1 BETWEEN xmin AND xmax);
} {
0 0 0 {SCAN TABLE xdir}
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
0 2 2 {SCAN TABLE ydir}
2 4
}
do_eqp_execsql_test 7.4 {
SELECT id FROM rt, xdir CROSS JOIN ydir
ON (y1 BETWEEN ymin AND ymax)
WHERE (x1 BETWEEN xmin AND xmax);
} {
0 0 1 {SCAN TABLE xdir}
0 1 0 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
0 2 2 {SCAN TABLE ydir}
2 4
}
finish_test
finish_test
+33 -11
View File
@@ -66,10 +66,11 @@ LIBOBJ+= vdbe.o parse.o \
notify.o opcodes.o os.o os_unix.o os_win.o \
pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
random.o resolve.o rowset.o rtree.o select.o sqlite3ota.o status.o \
table.o threads.o tokenize.o trigger.o \
table.o threads.o tokenize.o treeview.o trigger.o \
update.o userauth.o util.o vacuum.o \
vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
vdbetrace.o wal.o walker.o where.o utf.o vtab.o
vdbetrace.o wal.o walker.o where.o wherecode.o whereexpr.o \
utf.o vtab.o
@@ -151,6 +152,7 @@ SRC = \
$(TOP)/src/tclsqlite.c \
$(TOP)/src/threads.c \
$(TOP)/src/tokenize.c \
$(TOP)/src/treeview.c \
$(TOP)/src/trigger.c \
$(TOP)/src/utf.c \
$(TOP)/src/update.c \
@@ -171,6 +173,8 @@ SRC = \
$(TOP)/src/wal.h \
$(TOP)/src/walker.c \
$(TOP)/src/where.c \
$(TOP)/src/wherecode.c \
$(TOP)/src/whereexpr.c \
$(TOP)/src/whereInt.h
# Source code for extensions
@@ -337,6 +341,8 @@ TESTSRC2 = \
$(TOP)/src/vdbe.c \
$(TOP)/src/vdbemem.c \
$(TOP)/src/where.c \
$(TOP)/src/wherecode.c \
$(TOP)/src/whereexpr.c \
parse.c \
$(TOP)/ext/fts3/fts3.c \
$(TOP)/ext/fts3/fts3_aux.c \
@@ -410,6 +416,10 @@ FUZZDATA = \
$(TOP)/test/fuzzdata2.db \
$(TOP)/test/fuzzdata3.db
# Standard options to testfixture
#
TESTOPTS = --verbose=file --output=test-out.txt
# This is the default Makefile target. The objects listed here
# are what get build when you type just "make" with no arguments.
#
@@ -662,36 +672,48 @@ fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c
-o testfixture$(EXE) $(LIBTCL) $(THREADLIB)
fulltest: $(TESTPROGS) fuzztest
./testfixture$(EXE) $(TOP)/test/all.test
./testfixture$(EXE) $(TOP)/test/all.test $(TESTOPTS)
soaktest: $(TESTPROGS)
./testfixture$(EXE) $(TOP)/test/all.test -soak=1
./testfixture$(EXE) $(TOP)/test/all.test -soak=1 $(TESTOPTS)
fulltestonly: $(TESTPROGS) fuzztest
./testfixture$(EXE) $(TOP)/test/full.test
./testfixture$(EXE) $(TOP)/test/full.test $(TESTOPTS)
queryplantest: testfixture$(EXE) sqlite3$(EXE)
./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner
./testfixture$(EXE) $(TOP)/test/permutations.test queryplanner $(TESTOPTS)
fuzztest: fuzzcheck$(EXE) $(FUZZDATA)
./fuzzcheck$(EXE) $(FUZZDATA)
valgrindfuzz: fuzzcheck$(EXE) $(FUZZDATA)
valgrind ./fuzzcheck$(EXE) --cell-size-check --quiet $(FUZZDATA)
# A very quick test using only testfixture and omitting all the slower
# tests. Designed to run in under 3 minutes on a workstation.
#
quicktest: ./testfixture$(EXE)
./testfixture$(EXE) $(TOP)/test/extraquick.test $(TESTOPTS)
# The default test case. Runs most of the faster standard TCL tests,
# and fuzz tests, and sqlite3_analyzer and sqldiff tests.
#
test: $(TESTPROGS) fuzztest
./testfixture$(EXE) $(TOP)/test/veryquick.test
./testfixture$(EXE) $(TOP)/test/veryquick.test $(TESTOPTS)
# Run a test using valgrind. This can take a really long time
# because valgrind is so much slower than a native machine.
#
valgrindtest: $(TESTPROGS) fuzzcheck$(EXE) $(FUZZDATA)
valgrind -v ./fuzzcheck$(EXE) --cell-size-check --quiet $(FUZZDATA)
OMIT_MISUSE=1 valgrind -v ./testfixture$(EXE) $(TOP)/test/permutations.test valgrind
valgrindtest: $(TESTPROGS) valgrindfuzz
OMIT_MISUSE=1 valgrind -v \
./testfixture$(EXE) $(TOP)/test/permutations.test valgrind $(TESTOPTS)
# A very fast test that checks basic sanity. The name comes from
# the 60s-era electronics testing: "Turn it on and see if smoke
# comes out."
#
smoketest: $(TESTPROGS) fuzzcheck$(EXE)
./testfixture$(EXE) $(TOP)/test/main.test
./testfixture$(EXE) $(TOP)/test/main.test $(TESTOPTS)
# The next two rules are used to support the "threadtest" target. Building
# threadtest runs a few thread-safety tests that are implemented in C. This
+66 -62
View File
@@ -1,9 +1,9 @@
C Add\sthe\sbuilt-in\saffinity()\sSQL\sfunction.\s\sThis\sturns\sout\sto\sbe\snot\sas\suseful\nas\soriginally\senvisioned,\sso\sabandon\sit\son\sa\sbranch.
D 2015-06-02T16:09:58.099
C Use\s'binary'\smode\sfor\spopen\swith\sMSVC.
D 2015-06-17T19:06:23.479
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 994bab32a3a69e0c35bd148b65cde49879772964
F Makefile.in 1063c58075b7400d93326b0eb332b48a54f53025
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc d37d2c2323df3acae6e24c71a478889421c17264
F Makefile.msc b7db9ccbbad1c495b98e5326a06cac03aa206127
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION ce0ae95abd7121c534f6917c1c8f2b70d9acd4db
@@ -85,7 +85,7 @@ F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
F ext/fts3/fts3_expr.c 71c063da9c2a4167fb54aec089dd5ef33a58c9cb
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
F ext/fts3/fts3_icu.c deb46f7020d87ea7a14a433fb7a7f4bef42a9652
F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009
F ext/fts3/fts3_snippet.c 68ae118b0f834ea53d2b89e4087fc0f0b8c4ee4e
F ext/fts3/fts3_term.c 88c55a6fa1a51ab494e33dced0401a6c28791fd7
@@ -104,7 +104,7 @@ F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
F ext/fts3/unicode/mkunicode.tcl a2567f9d6ad6779879a2e394c120ad8718557e65
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
F ext/icu/icu.c d415ccf984defeb9df2c0e1afcfaa2f6dc05eacb
F ext/icu/icu.c b2732aef0b076e4276d9b39b5a33cec7a05e1413
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/misc/amatch.c 27b9b601fb1453084e18a3432ea0240d7af8decb
F ext/misc/closure.c 636024302cde41b2bf0c542f81c40c624cfb7012
@@ -156,7 +156,7 @@ F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a
F ext/rtree/rtree9.test b5eb13849545dfd271a54ff16784cb00d8792aea
F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf
F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e
F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06
F ext/rtree/rtreeC.test 90aaaffe2fd4f0dcd12289cad5515f6d41f45ffd
F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca
F ext/rtree/rtreeE.test 45a147a64a76306172819562309681d8e90f94bb
F ext/rtree/rtreeF.test 66deb9fd1611c7ca2e374adba63debdc2dbb12b4
@@ -171,7 +171,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk 8d418497da6a152a59b00d64ae3d66f3c665974c
F main.mk 68f86c21505d6b66765a13c193f00a53dde6a212
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk d5e22023b5238985bb54a72d33e0ac71fe4f8a32
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@@ -192,30 +192,30 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
F src/bitvec.c 5eb7958c3bf65210211cbcfc44eff86d0ded7c9d
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
F src/btree.c c73a170115df068764126a85288cdec092ec180c
F src/btree.c 02caf39192ed1f5c7157a1aac0b2ff23389233de
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
F src/build.c 73da2b9e9311abc4fcb4e36f76c7800c2d2504a4
F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575
F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a
F src/delete.c 37964e6c1d73ff49cbea9ff690c9605fb15f600e
F src/expr.c 5abe19af1c41dd8b334318611c6614cc21155b88
F src/delete.c 8857a6f27560718f65d43bdbec86c967ae1f8dfa
F src/expr.c fbde754df3fa10bbd3a1dcea08e77b0f1684d188
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
F src/func.c c215efa308b831f7ea147c7a6a03080c870caf8a
F src/func.c a98ea5880dc50e9ca6dd6f57079a37b9cfcdecf1
F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c d6e1623a97ce33e9af2f1a0c1f0085a2f63327ef
F src/insert.c b5f8b35a1b7924020e48cade5b2b5017bca7906b
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
F src/loadext.c 29255bbe1cfb2ce9bbff2526a5ecfddcb49b9271
F src/main.c 3a610587018485d9a12e38899dd8b8129b04d836
F src/loadext.c e722f4b832f923744788365df5fb8515c0bc8a47
F src/main.c c0061a4f8ba86f957534be93b7026dab324f12c2
F src/malloc.c 908c780fdddd472163c2d1b1820ae4081f01ad20
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c abe6ee469b6c5a35c7f22bfeb9c9bac664a1c987
@@ -224,7 +224,7 @@ F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
F src/mem5.c 61eeb90134f9a5be6c2e68d8daae7628b25953fb
F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85
F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495
F src/mutex.c 19bf9acba69ca2f367c3761080f8a9f0cf4670a8
F src/mutex.c 529e95739f815300a33c73fd8a7d6bdf0c24bd18
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
F src/mutex_noop.c 529bab0743c3321c940f32c3464de494fd38cfa9
F src/mutex_unix.c 5cf676464bd19e0a866297515d146e8bf1669dfb
@@ -242,20 +242,20 @@ F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77
F src/parse.y 6d60dda8f8d418b6dc034f1fbccd816c459983a8
F src/pcache.c 10539fb959849ad6efff80050541cab3d25089d4
F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8
F src/pcache1.c 69d137620a305f814398bd29a0c998038c0695e9
F src/pcache1.c 8e3799b33c41d517d86444d4abefc80d4f02adca
F src/pragma.c c1f4d012ea9f6b1ce52d341b2cd0ad72d560afd7
F src/pragma.h b8632d7cdda7b25323fa580e3e558a4f0d4502cc
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
F src/printf.c 13ce37e5574f9b0682fa86dbcf9faf76b9d82a15
F src/printf.c db11b5960105ee661dcac690f2ae6276e49bf251
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 84c571794e3ee5806274d95158a4c0177c6c4708
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
F src/select.c 7bb5c6334128877a30d4644fb948098a3ec41bbc
F src/shell.c 07dda7cd692911d2f22269953418d049f2e2c0ee
F src/sqlite.h.in d165beeceb6b40af60f352a4d4e37e02d9af7df0
F src/select.c 45a814a755f90c1a6345164d2da4a8ef293da53d
F src/shell.c 5ebff868cf3124a484d7b107907589bf4f127f82
F src/sqlite.h.in 76d2f5637eb795b6300d9dd3c3ec3632ffafd721
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 2ebeb634e751a61a6f0eebfa0f4669f46a42f6cd
F src/sqliteInt.h 98c49cbd565f08f2e516399734e497340ca9549c
F src/sqlite3ext.h be1a718b7d2ce40ceba725ae92c8eb5f18003066
F src/sqliteInt.h 95b99b2821811af1f2a1190fa829ffb8e6c04135
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e
@@ -306,19 +306,20 @@ F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
F src/tokenize.c baa0e550dfa76a8d781732a7bfb1f0aa094942f2
F src/tokenize.c 57cb3720f53f84d811def2069c2b169b6be539a5
F src/treeview.c 84aa2d2ed26627ccc8dd3a2becfa18dc86ee4607
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
F src/update.c 487747b328b7216bb7f6af0695d6937d5c9e605f
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c a6431c92803b975b7322724a7b433e538d243539
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
F src/vdbe.c 0a6a1df5c31415a0e974e74e7bd412616889453d
F src/vdbe.h 7e538ecf47dccb307ea2d087c3ddc2dd8d70e79d
F src/vdbeInt.h f0ccddac48583d5f762dc554a9f79e85ea8807e0
F src/vdbe.c c9b8985dfc5df9bd512342ea2e56af4be30cb31a
F src/vdbe.h 90048aea1910f9df93e6044592bd4a466dc9c5e7
F src/vdbeInt.h 20295e482121d13437f69985f77db211cdc8bac1
F src/vdbeapi.c 6a0d7757987018ff6b1b81bc5293219cd26bb299
F src/vdbeaux.c 46f9bc4b32866082eb87a36b461e487a0bbdbe8e
F src/vdbeaux.c 4c82d6f686f72ea7d266d26d528a171b728626f7
F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90
F src/vdbemem.c 67b302dc6df64b4d6785881c5d22bd4f9b17739d
F src/vdbemem.c 15c5ca36201efc5a603e6eb3786e09bec08b9a64
F src/vdbesort.c f5009e7a35e3065635d8918b9a31f498a499976b
F src/vdbetrace.c 8befe829faff6d9e6f6e4dee5a7d3f85cc85f1a0
F src/vtab.c c535e80259ebe616467181a83a4263555b97c694
@@ -326,10 +327,12 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
F src/where.c dcdfee81d35ae9261a4c5bda6289ed5fa6d7e1ae
F src/whereInt.h a6f5a762bc1b4b1c76e1cea79976b437ac35a435
F src/where.c 909eba3b6db984eb2adfbca9de2c237ee7056adb
F src/whereInt.h 5f87e3c4b0551747d119730dfebddd3c54f04047
F src/wherecode.c 0669481cabaf5caf934b6bb825df15bc57f60d40
F src/whereexpr.c 9ce1c9cfedbf80c93c7d899497025ec8256ce652
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity1.test 3f68d94550f47bac467f916844d939c94882b557
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
@@ -354,7 +357,7 @@ F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
F test/analyzeD.test 08f9d0bee4e118a66fff3a32d02dbe0ee0a2b594
F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
F test/analyzeF.test 7ccd7a04f7d3061bde1a8a4dacc4792edccf6bf2
F test/analyzer1.test e3bccac3be49382050464952998a631bf51e3ce1
F test/analyzer1.test 498e2ff4b62740c2751c3a2f8b744fe26689fae9
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
@@ -507,7 +510,7 @@ F test/e_update.test 312cb8f5ccfe41515a6bb092f8ea562a9bd54d52
F test/e_uri.test 5ae33760fb2039c61aa2d90886f1664664173585
F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
F test/e_walauto.test 6544af03423abc61b53cfb976839385ddc2a0a70
F test/e_walauto.test 280714ddf14e1a47dcbc59d515cd0b026dfd5567
F test/e_walckpt.test 65e29b6631e51f210f83e4ff11571e647ba93608
F test/e_walhook.test da3ea8b3483d1af72190337bda50155a91a4b664
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
@@ -523,8 +526,9 @@ F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
F test/expr.test 79c3e7502d9e571553b85f0ecc8ff2ac7d0e4931
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a
F test/filectrl.test 7c13f96457435238da99aff7343ad6a3a4885787
F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146
F test/fkey1.test de5b287f6a480b36bd51e8debcf48168e26e4ed2
F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9
@@ -599,7 +603,7 @@ F test/fts3conf.test ee8500c86dd58ec075e8831a1e216a79989436de
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
F test/fts3d.test 95c17d1b67b33a5eac0bf5a0d11116a0c0ac7a3a
F test/fts3d.test d3e9c8fb75135ada06bf3bab4f9666224965d708
F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
F test/fts3defer2.test c540f5f5c2840f70c68fd9b597df817ec7170468
F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd
@@ -633,14 +637,14 @@ F test/fts4content.test abb0c77bc3da3df64fec72e00844d2257a90025d
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53
F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d
F test/fts4incr.test 361960ed3550e781f3f313e17e2182ef9cefc0e9
F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7
F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
F test/fts4noti.test 524807f0c36d49deea7920cdd4cd687408b58849
F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36
F test/fts4unicode.test 27378af76394542cf490cf001d8d1505fe55f6a9
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
@@ -653,10 +657,10 @@ F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test efd384b896c647b61a2c1848ba70d42aad60a7b3
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
F test/fuzzcheck.c a60f926e3fa86c8d33908406d75eec868c22b9ca
F test/fuzzcheck.c 5805b2236292f8643d56e727a3a6e4d88e0856a5
F test/fuzzdata1.db b60254eeb6bc11474071b883059662a73c48da7f
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
F test/fuzzdata3.db 3632e598ff8574228aadf09897bd040d3c5f5ffb
F test/fuzzdata3.db f4ca6fa92973501cec63ac5d1992ef88f6a78e7f
F test/fuzzer1.test d4c52aaf3ef923da293a2653cfab33d02f718a36
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
F test/genesis.tcl 1e2e2e8e5cc4058549a154ff1892fe5c9de19f98
@@ -684,8 +688,8 @@ F test/index.test 4d990005a67a36984e4f1a5f1bdccea8d08da4ee
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
F test/index3.test b6ec456cf3b81d9a32123fe7e449bde434db338b
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
F test/index5.test 25b0b451aceed4ac5f7d49f856f6de7257470b3e
F test/index6.test 3ae54e53c53f2adcacda269237d8e52bdb05a481
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
F test/index6.test fbf45ceb39eb8a01b837d22623b93b208e6509ef
F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c
F test/indexedby.test 5f527a78bae74c61b8046ae3037f9dfb0bf0c353
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
@@ -706,7 +710,7 @@ F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
F test/join.test 52d4d49f86d0cf46926672878c4eaf0da399104a
F test/join.test f9d4a28dec81c6e9dc21b73518e024d73b5ebf57
F test/join2.test f2171c265e57ee298a27e57e7051d22962f9f324
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
@@ -821,13 +825,13 @@ F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
F test/permutations.test 32e2b82e0dfbe5c6b6b38a5c1f4cac194298ad4e
F test/permutations.test 6b0f339a4d5f00041555a986dde8fbe8f54c25bc
F test/pragma.test be7195f0aa72bdb8a512133e9640ac40f15b57a2
F test/pragma2.test f624a496a95ee878e81e59961eade66d5c00c028
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
F test/printf2.test 0b61566dd1c0f0b802f59dffa228c5dc5aa6b054
F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
@@ -840,7 +844,7 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.tcl 3e906a8bbd047b8e1f035984fbdc96df4caaea47
F test/releasetest.tcl 2aaffa548a8f8d10053b20bcf68a1b5a01081e51
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
@@ -872,7 +876,7 @@ F test/select4.test 6d5bc6d178a367e8b48fa1c1d3ea12cae9c2d650
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
F test/selectA.test e452bdb975f488ea46d091382a9185b5853ed2c7
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
@@ -885,7 +889,7 @@ F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118
F test/shared.test 1da9dbad400cee0d93f252ccf76e1ae007a63746
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
F test/shared3.test fcd65cb11d189eff5f5c85cc4fad246fb0933108
F test/shared4.test 72d90821e8d2fc918a08f16d32880868d8ee8e9d
F test/shared4.test c75f476804e76e26bf6fa0e7b421fb0ca7d07558
F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
F test/shared7.test a81e99f83e6c51b02ac99c96fb3a2a7b5978c956
F test/shared8.test 00a07bf5e1337ecf72e94542bdefdc330d7a2538
@@ -926,7 +930,7 @@ F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 9f1b745c24886cced3f70ffc666300152a39013c
F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49
F test/sqldiff1.test e5ecfe95b3a2ff6380f0db6ea8bec246b675e122
F test/sqldiff1.test 8f6bc7c6a5b3585d350d779c6078869ba402f8f5
F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68
F test/stat.test 8de91498c99f5298b303f70f1d1f3b9557af91bf
F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1
@@ -939,14 +943,14 @@ F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
F test/table.test bd841e8df69b99172ce9c7d53587463913d711ca
F test/table.test 33bf0d1fd07f304582695184b8e6feb017303816
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
F test/tester.tcl c18dbf42f4b0c1fb889b0efeb8a59d5143dd9828
F test/tester.tcl b3a41e20f98a029a76e930b33d0711c5854267bb
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1144,7 +1148,7 @@ F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
F test/view.test f311691d696a5cc27e3c1b875cec1b0866b4ccd9
F test/vtab1.test dbe0e9e121102d0ba365f20d126a72676aa2343f
F test/vtab1.test 6210e076997f176bedc300a87ad6404651b601dd
F test/vtab2.test f8cd1bb9aba7143eba97812d9617880a36d247ad
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
@@ -1247,7 +1251,7 @@ F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl 40c287d3f929ece67da6e9e7c49885789960accf
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 69bae8ce4aa52d2ff82d4a8a856bf283ec035b2e
F tool/mksqlite3c.tcl fdeab4c1eed90b7ab741ec12a7bc5c2fb60188bd
F tool/mksqlite3c.tcl d79e450048b0bbf04d53677e01c249a012981182
F tool/mksqlite3h.tcl 44730d586c9031638cdd2eb443b801c0d2dbd9f8
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mkvsix.tcl 3b58b9398f91c7dbf18d49eb87cefeee9efdbce1
@@ -1280,12 +1284,12 @@ F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c
F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P bce3f04186cd2d69414a5a98b5b77dc8f060554a
R 98be638f0f819b9a8a15b45777fdc534
T *branch * affinity-func
T *sym-affinity-func *
T -sym-blob-affinity-rename *
U drh
Z 13640b2e248aab3cf67f2fff3528da6a
P 5b547da00d131a494a6b348339af3d91dfa6e3b6
R 8612529b13f9ca5434e4332b04ad8958
T *branch * popenMsvc
T *sym-popenMsvc *
T -sym-trunk *
U mistachkin
Z 113266189542ecf55e5f2a32a4472f5b
+1 -1
View File
@@ -1 +1 @@
80889306bf57b886a248b880bc90197b8975a666
7b84641e55654f8e81b62893d0bb66b12dedfcf2
+14 -33
View File
@@ -1272,7 +1272,10 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc, int *pbDefrag){
int x = size - nByte;
testcase( x==4 );
testcase( x==3 );
if( x<4 ){
if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){
*pRc = SQLITE_CORRUPT_BKPT;
return 0;
}else if( x<4 ){
/* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
** number of bytes in fragments may not exceed 60. */
if( aData[hdr+7]>=60 ){
@@ -1283,9 +1286,6 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc, int *pbDefrag){
** fragmented bytes within the page. */
memcpy(&aData[iAddr], &aData[pc], 2);
aData[hdr+7] += (u8)x;
}else if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){
*pRc = SQLITE_CORRUPT_BKPT;
return 0;
}else{
/* The slot remains on the free-list. Reduce its size to account
** for the portion used by the new allocation. */
@@ -1441,7 +1441,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
/* At this point:
** iFreeBlk: First freeblock after iStart, or zero if none
** iPtr: The address of a pointer iFreeBlk
** iPtr: The address of a pointer to iFreeBlk
**
** Check to see if iFreeBlk should be coalesced onto the end of iStart.
*/
@@ -1449,6 +1449,7 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
nFrag = iFreeBlk - iEnd;
if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_BKPT;
iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]);
if( iEnd > pPage->pBt->usableSize ) return SQLITE_CORRUPT_BKPT;
iSize = iEnd - iStart;
iFreeBlk = get2byte(&data[iFreeBlk]);
}
@@ -3984,13 +3985,6 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
**
** BtCursor.info is a cache of the information in the current cell.
** Using this cache reduces the number of calls to btreeParseCell().
**
** 2007-06-25: There is a bug in some versions of MSVC that cause the
** compiler to crash when getCellInfo() is implemented as a macro.
** But there is a measureable speed advantage to using the macro on gcc
** (when less compiler optimizations like -Os or -O0 are used and the
** compiler is not doing aggressive inlining.) So we use a real function
** for MSVC and a macro for everything else. Ticket #2457.
*/
#ifndef NDEBUG
static void assertCellInfo(BtCursor *pCur){
@@ -4003,28 +3997,15 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
#else
#define assertCellInfo(x)
#endif
#ifdef _MSC_VER
/* Use a real function in MSVC to work around bugs in that compiler. */
static void getCellInfo(BtCursor *pCur){
if( pCur->info.nSize==0 ){
int iPage = pCur->iPage;
btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);
pCur->curFlags |= BTCF_ValidNKey;
}else{
assertCellInfo(pCur);
}
static SQLITE_NOINLINE void getCellInfo(BtCursor *pCur){
if( pCur->info.nSize==0 ){
int iPage = pCur->iPage;
pCur->curFlags |= BTCF_ValidNKey;
btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);
}else{
assertCellInfo(pCur);
}
#else /* if not _MSC_VER */
/* Use a macro in all other compilers so that the function is inlined */
#define getCellInfo(pCur) \
if( pCur->info.nSize==0 ){ \
int iPage = pCur->iPage; \
btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \
pCur->curFlags |= BTCF_ValidNKey; \
}else{ \
assertCellInfo(pCur); \
}
#endif /* _MSC_VER */
}
#ifndef NDEBUG /* The next routine used only within assert() statements */
/*
+5 -4
View File
@@ -976,7 +976,7 @@ void sqlite3StartTable(
int j1;
int fileFormat;
int reg1, reg2, reg3;
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3BeginWriteOperation(pParse, 1, iDb);
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( isVirtual ){
@@ -1924,6 +1924,7 @@ void sqlite3EndTable(
regRec = ++pParse->nMem;
regRowid = ++pParse->nMem;
assert(pParse->nTab==1);
sqlite3MayAbort(pParse);
sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
sqlite3VdbeChangeP5(v, OPFLAG_P2ISREG);
pParse->nTab = 2;
@@ -3701,7 +3702,7 @@ void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
sqlite3DbFree(db, pItem->zDatabase);
sqlite3DbFree(db, pItem->zName);
sqlite3DbFree(db, pItem->zAlias);
sqlite3DbFree(db, pItem->zIndex);
sqlite3DbFree(db, pItem->zIndexedBy);
sqlite3DeleteTable(db, pItem->pTab);
sqlite3SelectDelete(db, pItem->pSelect);
sqlite3ExprDelete(db, pItem->pOn);
@@ -3774,13 +3775,13 @@ void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
assert( pIndexedBy!=0 );
if( p && ALWAYS(p->nSrc>0) ){
struct SrcList_item *pItem = &p->a[p->nSrc-1];
assert( pItem->notIndexed==0 && pItem->zIndex==0 );
assert( pItem->notIndexed==0 && pItem->zIndexedBy==0 );
if( pIndexedBy->n==1 && !pIndexedBy->z ){
/* A "NOT INDEXED" clause was supplied. See parse.y
** construct "indexed_opt" for details. */
pItem->notIndexed = 1;
}else{
pItem->zIndex = sqlite3NameFromToken(pParse->db, pIndexedBy);
pItem->zIndexedBy = sqlite3NameFromToken(pParse->db, pIndexedBy);
}
}
}
+2 -2
View File
@@ -798,8 +798,8 @@ int sqlite3GenerateIndexKey(
*piPartIdxLabel = sqlite3VdbeMakeLabel(v);
pParse->iPartIdxTab = iDataCur;
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
SQLITE_JUMPIFNULL);
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
SQLITE_JUMPIFNULL);
}else{
*piPartIdxLabel = 0;
}
+18 -296
View File
@@ -1041,7 +1041,7 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
pNewItem->isCorrelated = pOldItem->isCorrelated;
pNewItem->viaCoroutine = pOldItem->viaCoroutine;
pNewItem->isRecursive = pOldItem->isRecursive;
pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex);
pNewItem->zIndexedBy = sqlite3DbStrDup(db, pOldItem->zIndexedBy);
pNewItem->notIndexed = pOldItem->notIndexed;
pNewItem->pIndex = pOldItem->pIndex;
pTab = pNewItem->pTab = pOldItem->pTab;
@@ -2208,17 +2208,6 @@ static void sqlite3ExprCodeIN(
}
#endif /* SQLITE_OMIT_SUBQUERY */
/*
** Duplicate an 8-byte value
*/
static char *dup8bytes(Vdbe *v, const char *in){
char *out = sqlite3DbMallocRaw(sqlite3VdbeDb(v), 8);
if( out ){
memcpy(out, in, 8);
}
return out;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Generate an instruction that will put the floating point
@@ -2231,12 +2220,10 @@ static char *dup8bytes(Vdbe *v, const char *in){
static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
if( ALWAYS(z!=0) ){
double value;
char *zV;
sqlite3AtoF(z, &value, sqlite3Strlen30(z), SQLITE_UTF8);
assert( !sqlite3IsNaN(value) ); /* The new AtoF never returns NaN */
if( negateFlag ) value = -value;
zV = dup8bytes(v, (char*)&value);
sqlite3VdbeAddOp4(v, OP_Real, 0, iMem, 0, zV, P4_REAL);
sqlite3VdbeAddOp4Dup8(v, OP_Real, 0, iMem, 0, (u8*)&value, P4_REAL);
}
}
#endif
@@ -2262,10 +2249,8 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
assert( z!=0 );
c = sqlite3DecOrHexToI64(z, &value);
if( c==0 || (c==2 && negFlag) ){
char *zV;
if( negFlag ){ value = c==2 ? SMALLEST_INT64 : -value; }
zV = dup8bytes(v, (char*)&value);
sqlite3VdbeAddOp4(v, OP_Int64, 0, iMem, 0, zV, P4_INT64);
sqlite3VdbeAddOp4Dup8(v, OP_Int64, 0, iMem, 0, (u8*)&value, P4_INT64);
}else{
#ifdef SQLITE_OMIT_FLOATING_POINT
sqlite3ErrorMsg(pParse, "oversized integer: %s%s", negFlag ? "-" : "", z);
@@ -2874,22 +2859,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
break;
}
/* The AFFINITY() function returns the type affinity of its argument.
** The type affinity is a compile-time value, so we might as well
** code it directly.
*/
if( pDef->funcFlags & SQLITE_FUNC_AFFINITY ){
int aff;
static const char *const azAffName[] = {
"", "BLOB", "TEXT", "NUMERIC", "INTEGER", "REAL"
};
assert( nFarg==1 );
aff = sqlite3ExprAffinity(pFarg->a[0].pExpr);
if( aff ) aff -= SQLITE_AFF_BLOB - 1;
sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, azAffName[aff], 0);
break;
}
for(i=0; i<nFarg; i++){
if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
testcase( i==31 );
@@ -3327,268 +3296,6 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
exprToRegister(pExpr, iMem);
}
#ifdef SQLITE_DEBUG
/*
** Generate a human-readable explanation of an expression tree.
*/
void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
const char *zBinOp = 0; /* Binary operator */
const char *zUniOp = 0; /* Unary operator */
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( pExpr==0 ){
sqlite3TreeViewLine(pView, "nil");
sqlite3TreeViewPop(pView);
return;
}
switch( pExpr->op ){
case TK_AGG_COLUMN: {
sqlite3TreeViewLine(pView, "AGG{%d:%d}",
pExpr->iTable, pExpr->iColumn);
break;
}
case TK_COLUMN: {
if( pExpr->iTable<0 ){
/* This only happens when coding check constraints */
sqlite3TreeViewLine(pView, "COLUMN(%d)", pExpr->iColumn);
}else{
sqlite3TreeViewLine(pView, "{%d:%d}",
pExpr->iTable, pExpr->iColumn);
}
break;
}
case TK_INTEGER: {
if( pExpr->flags & EP_IntValue ){
sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
}else{
sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
}
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
case TK_FLOAT: {
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_STRING: {
sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
break;
}
case TK_NULL: {
sqlite3TreeViewLine(pView,"NULL");
break;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_VARIABLE: {
sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
pExpr->u.zToken, pExpr->iColumn);
break;
}
case TK_REGISTER: {
sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
break;
}
case TK_AS: {
sqlite3TreeViewLine(pView,"AS %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_ID: {
sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
break;
}
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
#endif /* SQLITE_OMIT_CAST */
case TK_LT: zBinOp = "LT"; break;
case TK_LE: zBinOp = "LE"; break;
case TK_GT: zBinOp = "GT"; break;
case TK_GE: zBinOp = "GE"; break;
case TK_NE: zBinOp = "NE"; break;
case TK_EQ: zBinOp = "EQ"; break;
case TK_IS: zBinOp = "IS"; break;
case TK_ISNOT: zBinOp = "ISNOT"; break;
case TK_AND: zBinOp = "AND"; break;
case TK_OR: zBinOp = "OR"; break;
case TK_PLUS: zBinOp = "ADD"; break;
case TK_STAR: zBinOp = "MUL"; break;
case TK_MINUS: zBinOp = "SUB"; break;
case TK_REM: zBinOp = "REM"; break;
case TK_BITAND: zBinOp = "BITAND"; break;
case TK_BITOR: zBinOp = "BITOR"; break;
case TK_SLASH: zBinOp = "DIV"; break;
case TK_LSHIFT: zBinOp = "LSHIFT"; break;
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
case TK_CONCAT: zBinOp = "CONCAT"; break;
case TK_DOT: zBinOp = "DOT"; break;
case TK_UMINUS: zUniOp = "UMINUS"; break;
case TK_UPLUS: zUniOp = "UPLUS"; break;
case TK_BITNOT: zUniOp = "BITNOT"; break;
case TK_NOT: zUniOp = "NOT"; break;
case TK_ISNULL: zUniOp = "ISNULL"; break;
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
case TK_COLLATE: {
sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_AGG_FUNCTION:
case TK_FUNCTION: {
ExprList *pFarg; /* List of function arguments */
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
}else{
pFarg = pExpr->x.pList;
}
if( pExpr->op==TK_AGG_FUNCTION ){
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
pExpr->op2, pExpr->u.zToken);
}else{
sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
}
if( pFarg ){
sqlite3TreeViewExprList(pView, pFarg, 0, 0);
}
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_EXISTS: {
sqlite3TreeViewLine(pView, "EXISTS-expr");
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_SELECT: {
sqlite3TreeViewLine(pView, "SELECT-expr");
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_IN: {
sqlite3TreeViewLine(pView, "IN");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
}else{
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
}
break;
}
#endif /* SQLITE_OMIT_SUBQUERY */
/*
** x BETWEEN y AND z
**
** This is equivalent to
**
** x>=y AND x<=z
**
** X is stored in pExpr->pLeft.
** Y is stored in pExpr->pList->a[0].pExpr.
** Z is stored in pExpr->pList->a[1].pExpr.
*/
case TK_BETWEEN: {
Expr *pX = pExpr->pLeft;
Expr *pY = pExpr->x.pList->a[0].pExpr;
Expr *pZ = pExpr->x.pList->a[1].pExpr;
sqlite3TreeViewLine(pView, "BETWEEN");
sqlite3TreeViewExpr(pView, pX, 1);
sqlite3TreeViewExpr(pView, pY, 1);
sqlite3TreeViewExpr(pView, pZ, 0);
break;
}
case TK_TRIGGER: {
/* If the opcode is TK_TRIGGER, then the expression is a reference
** to a column in the new.* or old.* pseudo-tables available to
** trigger programs. In this case Expr.iTable is set to 1 for the
** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
** is set to the column of the pseudo-table to read, or to -1 to
** read the rowid field.
*/
sqlite3TreeViewLine(pView, "%s(%d)",
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
break;
}
case TK_CASE: {
sqlite3TreeViewLine(pView, "CASE");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
break;
}
#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
const char *zType = "unk";
switch( pExpr->affinity ){
case OE_Rollback: zType = "rollback"; break;
case OE_Abort: zType = "abort"; break;
case OE_Fail: zType = "fail"; break;
case OE_Ignore: zType = "ignore"; break;
}
sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
break;
}
#endif
default: {
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
break;
}
}
if( zBinOp ){
sqlite3TreeViewLine(pView, "%s", zBinOp);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
}else if( zUniOp ){
sqlite3TreeViewLine(pView, "%s", zUniOp);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
}
sqlite3TreeViewPop(pView);
}
#endif /* SQLITE_DEBUG */
#ifdef SQLITE_DEBUG
/*
** Generate a human-readable explanation of an expression list.
*/
void sqlite3TreeViewExprList(
TreeView *pView,
const ExprList *pList,
u8 moreToFollow,
const char *zLabel
){
int i;
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
if( pList==0 ){
sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
}else{
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; i<pList->nExpr; i++){
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1);
#if 0
if( pList->a[i].zName ){
sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName);
}
if( pList->a[i].bSpanIsTab ){
sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan);
}
#endif
}
}
sqlite3TreeViewPop(pView);
}
#endif /* SQLITE_DEBUG */
/*
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
@@ -3980,6 +3687,21 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
sqlite3ReleaseTempReg(pParse, regFree2);
}
/*
** Like sqlite3ExprIfFalse() except that a copy is made of pExpr before
** code generation, and that copy is deleted after code generation. This
** ensures that the original pExpr is unchanged.
*/
void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,int jumpIfNull){
sqlite3 *db = pParse->db;
Expr *pCopy = sqlite3ExprDup(db, pExpr, 0);
if( db->mallocFailed==0 ){
sqlite3ExprIfFalse(pParse, pCopy, dest, jumpIfNull);
}
sqlite3ExprDelete(db, pCopy);
}
/*
** Do a deep comparison of two expression trees. Return 0 if the two
** expressions are completely identical. Return 1 if they differ only
+10 -14
View File
@@ -575,17 +575,15 @@ struct compareInfo {
/*
** For LIKE and GLOB matching on EBCDIC machines, assume that every
** character is exactly one byte in size. Also, all characters are
** able to participate in upper-case-to-lower-case mappings in EBCDIC
** whereas only characters less than 0x80 do in ASCII.
** character is exactly one byte in size. Also, provde the Utf8Read()
** macro for fast reading of the next character in the common case where
** the next character is ASCII.
*/
#if defined(SQLITE_EBCDIC)
# define sqlite3Utf8Read(A) (*((*A)++))
# define GlobUpperToLower(A) A = sqlite3UpperToLower[A]
# define GlobUpperToLowerAscii(A) A = sqlite3UpperToLower[A]
# define Utf8Read(A) (*(A++))
#else
# define GlobUpperToLower(A) if( A<=0x7f ){ A = sqlite3UpperToLower[A]; }
# define GlobUpperToLowerAscii(A) A = sqlite3UpperToLower[A]
# define Utf8Read(A) (A[0]<0x80?*(A++):sqlite3Utf8Read(&A))
#endif
static const struct compareInfo globInfo = { '*', '?', '[', 0 };
@@ -627,7 +625,7 @@ static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };
** Ec Where E is the "esc" character and c is any other
** character, including '%', '_', and esc, match exactly c.
**
** The comments through this routine usually assume glob matching.
** The comments within this routine usually assume glob matching.
**
** This routine is usually quick, but can be N**2 in the worst case.
*/
@@ -651,13 +649,12 @@ static int patternCompare(
*/
matchOther = esc ? esc : pInfo->matchSet;
while( (c = sqlite3Utf8Read(&zPattern))!=0 ){
while( (c = Utf8Read(zPattern))!=0 ){
if( c==matchAll ){ /* Match "*" */
/* Skip over multiple "*" characters in the pattern. If there
** are also "?" characters, skip those as well, but consume a
** single character of the input string for each "?" skipped */
while( (c=sqlite3Utf8Read(&zPattern)) == matchAll
|| c == matchOne ){
while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){
if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
return 0;
}
@@ -702,7 +699,7 @@ static int patternCompare(
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
}
}else{
while( (c2 = sqlite3Utf8Read(&zString))!=0 ){
while( (c2 = Utf8Read(zString))!=0 ){
if( c2!=c ) continue;
if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
}
@@ -748,7 +745,7 @@ static int patternCompare(
continue;
}
}
c2 = sqlite3Utf8Read(&zString);
c2 = Utf8Read(zString);
if( c==c2 ) continue;
if( noCase && c<0x80 && c2<0x80 && sqlite3Tolower(c)==sqlite3Tolower(c2) ){
continue;
@@ -1717,7 +1714,6 @@ void sqlite3RegisterGlobalFunctions(void){
AGGREGATE2(max, 1, 1, 1, minmaxStep, minMaxFinalize,
SQLITE_FUNC_MINMAX ),
FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY),
FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
FUNCTION(instr, 2, 0, 0, instrFunc ),
FUNCTION(substr, 2, 0, 0, substrFunc ),
+2 -2
View File
@@ -1381,8 +1381,8 @@ void sqlite3GenerateConstraintChecks(
if( pIdx->pPartIdxWhere ){
sqlite3VdbeAddOp2(v, OP_Null, 0, aRegIdx[ix]);
pParse->ckBase = regNewData+1;
sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, addrUniqueOk,
SQLITE_JUMPIFNULL);
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, addrUniqueOk,
SQLITE_JUMPIFNULL);
pParse->ckBase = 0;
}
+4 -1
View File
@@ -402,7 +402,10 @@ static const sqlite3_api_routines sqlite3Apis = {
sqlite3_reset_auto_extension,
sqlite3_result_blob64,
sqlite3_result_text64,
sqlite3_strglob
sqlite3_strglob,
/* Version 3.8.11 and later */
(sqlite3_value*(*)(const sqlite3_value*))sqlite3_value_dup,
sqlite3_value_free
};
/*
+5 -1
View File
@@ -2082,9 +2082,11 @@ int sqlite3TempInMemory(const sqlite3 *db){
return ( db->temp_store!=1 );
#endif
#if SQLITE_TEMP_STORE==3
UNUSED_PARAMETER(db);
return 1;
#endif
#if SQLITE_TEMP_STORE<1 || SQLITE_TEMP_STORE>3
UNUSED_PARAMETER(db);
return 0;
#endif
}
@@ -3356,7 +3358,9 @@ int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
*/
int sqlite3_test_control(int op, ...){
int rc = 0;
#ifndef SQLITE_OMIT_BUILTIN_TEST
#ifdef SQLITE_OMIT_BUILTIN_TEST
UNUSED_PARAMETER(op);
#else
va_list ap;
va_start(ap, op);
switch( op ){
+8 -3
View File
@@ -45,9 +45,14 @@ int sqlite3MutexInit(void){
}else{
pFrom = sqlite3NoopMutex();
}
memcpy(pTo, pFrom, offsetof(sqlite3_mutex_methods, xMutexAlloc));
memcpy(&pTo->xMutexFree, &pFrom->xMutexFree,
sizeof(*pTo) - offsetof(sqlite3_mutex_methods, xMutexFree));
pTo->xMutexInit = pFrom->xMutexInit;
pTo->xMutexEnd = pFrom->xMutexEnd;
pTo->xMutexFree = pFrom->xMutexFree;
pTo->xMutexEnter = pFrom->xMutexEnter;
pTo->xMutexTry = pFrom->xMutexTry;
pTo->xMutexLeave = pFrom->xMutexLeave;
pTo->xMutexHeld = pFrom->xMutexHeld;
pTo->xMutexNotheld = pFrom->xMutexNotheld;
pTo->xMutexAlloc = pFrom->xMutexAlloc;
}
rc = sqlite3GlobalConfig.mutex.xMutexInit();
+72 -24
View File
@@ -148,8 +148,15 @@ static SQLITE_WSD struct PCacheGlobal {
/*
** Macros to enter and leave the PCache LRU mutex.
*/
#define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
#define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)
#if !defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0
# define pcache1EnterMutex(X) assert((X)->mutex==0)
# define pcache1LeaveMutex(X) assert((X)->mutex==0)
# define PCACHE1_MIGHT_USE_GROUP_MUTEX 0
#else
# define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
# define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)
# define PCACHE1_MIGHT_USE_GROUP_MUTEX 1
#endif
/******************************************************************************/
/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
@@ -425,31 +432,30 @@ static void pcache1ResizeHash(PCache1 *p){
**
** The PGroup mutex must be held when this function is called.
*/
static void pcache1PinPage(PgHdr1 *pPage){
static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){
PCache1 *pCache;
PGroup *pGroup;
assert( pPage!=0 );
assert( pPage->isPinned==0 );
pCache = pPage->pCache;
pGroup = pCache->pGroup;
assert( pPage->pLruNext || pPage==pGroup->pLruTail );
assert( pPage->pLruPrev || pPage==pGroup->pLruHead );
assert( sqlite3_mutex_held(pGroup->mutex) );
assert( pPage->pLruNext || pPage==pCache->pGroup->pLruTail );
assert( pPage->pLruPrev || pPage==pCache->pGroup->pLruHead );
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
if( pPage->pLruPrev ){
pPage->pLruPrev->pLruNext = pPage->pLruNext;
}else{
pGroup->pLruHead = pPage->pLruNext;
pCache->pGroup->pLruHead = pPage->pLruNext;
}
if( pPage->pLruNext ){
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
}else{
pGroup->pLruTail = pPage->pLruPrev;
pCache->pGroup->pLruTail = pPage->pLruPrev;
}
pPage->pLruNext = 0;
pPage->pLruPrev = 0;
pPage->isPinned = 1;
pCache->nRecyclable--;
return pPage;
}
@@ -530,10 +536,12 @@ static int pcache1Init(void *NotUsed){
UNUSED_PARAMETER(NotUsed);
assert( pcache1.isInit==0 );
memset(&pcache1, 0, sizeof(pcache1));
#if SQLITE_THREADSAFE
if( sqlite3GlobalConfig.bCoreMutex ){
pcache1.grp.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_LRU);
pcache1.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PMEM);
}
#endif
pcache1.grp.mxPinned = 10;
pcache1.isInit = 1;
return SQLITE_OK;
@@ -729,9 +737,9 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
** attempt to allocate a new one.
*/
if( !pPage ){
if( createFlag==1 ) sqlite3BeginBenignMalloc();
if( createFlag==1 ){ sqlite3BeginBenignMalloc(); }
pPage = pcache1AllocPage(pCache);
if( createFlag==1 ) sqlite3EndBenignMalloc();
if( createFlag==1 ){ sqlite3EndBenignMalloc(); }
}
if( pPage ){
@@ -805,8 +813,13 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
** proceed to step 5.
**
** 5. Otherwise, allocate and return a new page buffer.
**
** There are two versions of this routine. pcache1FetchWithMutex() is
** the general case. pcache1FetchNoMutex() is a faster implementation for
** the common case where pGroup->mutex is NULL. The pcache1Fetch() wrapper
** invokes the appropriate routine.
*/
static sqlite3_pcache_page *pcache1Fetch(
static PgHdr1 *pcache1FetchNoMutex(
sqlite3_pcache *p,
unsigned int iKey,
int createFlag
@@ -814,28 +827,63 @@ static sqlite3_pcache_page *pcache1Fetch(
PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage = 0;
assert( offsetof(PgHdr1,page)==0 );
assert( pCache->bPurgeable || createFlag!=1 );
assert( pCache->bPurgeable || pCache->nMin==0 );
assert( pCache->bPurgeable==0 || pCache->nMin==10 );
assert( pCache->nMin==0 || pCache->bPurgeable );
assert( pCache->nHash>0 );
pcache1EnterMutex(pCache->pGroup);
/* Step 1: Search the hash table for an existing entry. */
pPage = pCache->apHash[iKey % pCache->nHash];
while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; }
/* Step 2: Abort if no existing page is found and createFlag is 0 */
if( pPage ){
if( !pPage->isPinned ) pcache1PinPage(pPage);
if( !pPage->isPinned ){
return pcache1PinPage(pPage);
}else{
return pPage;
}
}else if( createFlag ){
/* Steps 3, 4, and 5 implemented by this subroutine */
pPage = pcache1FetchStage2(pCache, iKey, createFlag);
return pcache1FetchStage2(pCache, iKey, createFlag);
}else{
return 0;
}
}
#if PCACHE1_MIGHT_USE_GROUP_MUTEX
static PgHdr1 *pcache1FetchWithMutex(
sqlite3_pcache *p,
unsigned int iKey,
int createFlag
){
PCache1 *pCache = (PCache1 *)p;
PgHdr1 *pPage;
pcache1EnterMutex(pCache->pGroup);
pPage = pcache1FetchNoMutex(p, iKey, createFlag);
assert( pPage==0 || pCache->iMaxKey>=iKey );
pcache1LeaveMutex(pCache->pGroup);
return (sqlite3_pcache_page*)pPage;
return pPage;
}
#endif
static sqlite3_pcache_page *pcache1Fetch(
sqlite3_pcache *p,
unsigned int iKey,
int createFlag
){
#if PCACHE1_MIGHT_USE_GROUP_MUTEX || defined(SQLITE_DEBUG)
PCache1 *pCache = (PCache1 *)p;
#endif
assert( offsetof(PgHdr1,page)==0 );
assert( pCache->bPurgeable || createFlag!=1 );
assert( pCache->bPurgeable || pCache->nMin==0 );
assert( pCache->bPurgeable==0 || pCache->nMin==10 );
assert( pCache->nMin==0 || pCache->bPurgeable );
assert( pCache->nHash>0 );
#if PCACHE1_MIGHT_USE_GROUP_MUTEX
if( pCache->pGroup->mutex ){
return (sqlite3_pcache_page*)pcache1FetchWithMutex(p, iKey, createFlag);
}else
#endif
{
return (sqlite3_pcache_page*)pcache1FetchNoMutex(p, iKey, createFlag);
}
}
+2 -66
View File
@@ -1,16 +1,13 @@
/*
** The "printf" code that follows dates from the 1980's. It is in
** the public domain. The original comments are included here for
** completeness. They are very out-of-date but might be useful as
** an historical reference. Most of the "enhancements" have been backed
** out so that the functionality is now the same as standard printf().
** the public domain.
**
**************************************************************************
**
** This file contains code for a set of "printf"-like routines. These
** routines format strings much like the printf() from the standard C
** library, though the implementation here has enhancements to support
** SQLlite.
** SQLite.
*/
#include "sqliteInt.h"
@@ -1058,67 +1055,6 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
}
#endif
#ifdef SQLITE_DEBUG
/*************************************************************************
** Routines for implementing the "TreeView" display of hierarchical
** data structures for debugging.
**
** The main entry points (coded elsewhere) are:
** sqlite3TreeViewExpr(0, pExpr, 0);
** sqlite3TreeViewExprList(0, pList, 0, 0);
** sqlite3TreeViewSelect(0, pSelect, 0);
** Insert calls to those routines while debugging in order to display
** a diagram of Expr, ExprList, and Select objects.
**
*/
/* Add a new subitem to the tree. The moreToFollow flag indicates that this
** is not the last item in the tree. */
TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
if( p==0 ){
p = sqlite3_malloc64( sizeof(*p) );
if( p==0 ) return 0;
memset(p, 0, sizeof(*p));
}else{
p->iLevel++;
}
assert( moreToFollow==0 || moreToFollow==1 );
if( p->iLevel<sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
return p;
}
/* Finished with one layer of the tree */
void sqlite3TreeViewPop(TreeView *p){
if( p==0 ) return;
p->iLevel--;
if( p->iLevel<0 ) sqlite3_free(p);
}
/* Generate a single line of output for the tree, with a prefix that contains
** all the appropriate tree lines */
void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_list ap;
int i;
StrAccum acc;
char zBuf[500];
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
if( p ){
for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4);
}
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
}
va_start(ap, zFormat);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
va_end(ap);
if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1);
sqlite3StrAccumFinish(&acc);
fprintf(stdout,"%s", zBuf);
fflush(stdout);
}
/* Shorthand for starting a new tree item that consists of a single label */
void sqlite3TreeViewItem(TreeView *p, const char *zLabel, u8 moreToFollow){
p = sqlite3TreeViewPush(p, moreToFollow);
sqlite3TreeViewLine(p, "%s", zLabel);
}
#endif /* SQLITE_DEBUG */
/*
** variable-argument wrapper around sqlite3VXPrintf().
+186 -173
View File
@@ -21,7 +21,8 @@
/***/ int sqlite3SelectTrace = 0;
# define SELECTTRACE(K,P,S,X) \
if(sqlite3SelectTrace&(K)) \
sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",(S)->zSelName,(S)),\
sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",\
(S)->zSelName,(S)),\
sqlite3DebugPrintf X
#else
# define SELECTTRACE(K,P,S,X)
@@ -774,7 +775,8 @@ static void selectInnerLoop(
default: {
assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED );
codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol, regResult);
codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol,
regResult);
break;
}
}
@@ -827,7 +829,8 @@ static void selectInnerLoop(
** current row to the index and proceed with writing it to the
** output table as well. */
int addr = sqlite3VdbeCurrentAddr(v) + 4;
sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v);
sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0);
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1);
assert( pSort==0 );
}
@@ -1310,28 +1313,27 @@ static void generateSortTail(
*/
#ifdef SQLITE_ENABLE_COLUMN_METADATA
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F)
#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
#endif
static const char *columnTypeImpl(
NameContext *pNC,
Expr *pExpr,
#ifdef SQLITE_ENABLE_COLUMN_METADATA
const char **pzOrigDb,
const char **pzOrigTab,
const char **pzOrigCol,
#endif
u8 *pEstWidth
){
char const *zOrigDb = 0;
char const *zOrigTab = 0;
char const *zOrigCol = 0;
#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
static const char *columnTypeImpl(
NameContext *pNC,
Expr *pExpr,
u8 *pEstWidth
){
#endif /* !defined(SQLITE_ENABLE_COLUMN_METADATA) */
char const *zType = 0;
int j;
u8 estWidth = 1;
#ifdef SQLITE_ENABLE_COLUMN_METADATA
char const *zOrigDb = 0;
char const *zOrigTab = 0;
char const *zOrigCol = 0;
#endif
if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
switch( pExpr->op ){
@@ -1705,7 +1707,8 @@ static void selectAddColumnTypeAndCollation(
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
p = a[i].pExpr;
if( pCol->zType==0 ){
pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
pCol->zType = sqlite3DbStrDup(db,
columnType(&sNC, p,0,0,0, &pCol->szEst));
}
szAll += pCol->szEst;
pCol->affinity = sqlite3ExprAffinity(p);
@@ -3215,8 +3218,8 @@ static void substSelect(
**
** (**) Restriction (10) was removed from the code on 2005-02-05 but we
** accidently carried the comment forward until 2014-09-15. Original
** text: "The subquery does not use aggregates or the outer query does not
** use LIMIT."
** text: "The subquery does not use aggregates or the outer query
** does not use LIMIT."
**
** (11) The subquery and the outer query do not both have ORDER BY clauses.
**
@@ -3709,7 +3712,7 @@ static int flattenSubquery(
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
sqlite3DebugPrintf("After flattening:\n");
SELECTTRACE(0x100,pParse,p,("After flattening:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -3718,6 +3721,73 @@ static int flattenSubquery(
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** Make copies of relevant WHERE clause terms of the outer query into
** the WHERE clause of subquery. Example:
**
** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1) WHERE x=5 AND y=10;
**
** Transformed into:
**
** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10)
** WHERE x=5 AND y=10;
**
** The hope is that the terms added to the inner query will make it more
** efficient.
**
** Do not attempt this optimization if:
**
** (1) The inner query is an aggregate. (In that case, we'd really want
** to copy the outer WHERE-clause terms onto the HAVING clause of the
** inner query. But they probably won't help there so do not bother.)
**
** (2) The inner query is the recursive part of a common table expression.
**
** (3) The inner query has a LIMIT clause (since the changes to the WHERE
** close would change the meaning of the LIMIT).
**
** (4) The inner query is the right operand of a LEFT JOIN. (The caller
** enforces this restriction since this routine does not have enough
** information to know.)
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
*/
static int pushDownWhereTerms(
sqlite3 *db, /* The database connection (for malloc()) */
Select *pSubq, /* The subquery whose WHERE clause is to be augmented */
Expr *pWhere, /* The WHERE clause of the outer query */
int iCursor /* Cursor number of the subquery */
){
Expr *pNew;
int nChng = 0;
if( pWhere==0 ) return 0;
if( (pSubq->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
return 0; /* restrictions (1) and (2) */
}
if( pSubq->pLimit!=0 ){
return 0; /* restriction (3) */
}
while( pWhere->op==TK_AND ){
nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor);
pWhere = pWhere->pLeft;
}
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
nChng++;
while( pSubq ){
pNew = sqlite3ExprDup(db, pWhere, 0);
pNew = substExpr(db, pNew, iCursor, pSubq->pEList);
pSubq->pWhere = sqlite3ExprAnd(db, pSubq->pWhere, pNew);
pSubq = pSubq->pPrior;
}
}
return nChng;
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
/*
** Based on the contents of the AggInfo structure indicated by the first
** argument, this function checks if the following are true:
@@ -3801,16 +3871,16 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
** pFrom->pIndex and return SQLITE_OK.
*/
int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
if( pFrom->pTab && pFrom->zIndex ){
if( pFrom->pTab && pFrom->zIndexedBy ){
Table *pTab = pFrom->pTab;
char *zIndex = pFrom->zIndex;
char *zIndexedBy = pFrom->zIndexedBy;
Index *pIdx;
for(pIdx=pTab->pIndex;
pIdx && sqlite3StrICmp(pIdx->zName, zIndex);
pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy);
pIdx=pIdx->pNext
);
if( !pIdx ){
sqlite3ErrorMsg(pParse, "no such index: %s", zIndex, 0);
sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0);
pParse->checkSchema = 1;
return SQLITE_ERROR;
}
@@ -4747,12 +4817,11 @@ int sqlite3Select(
memset(&sSort, 0, sizeof(sSort));
sSort.pOrderBy = p->pOrderBy;
pTabList = p->pSrc;
pEList = p->pEList;
if( pParse->nErr || db->mallocFailed ){
goto select_end;
}
assert( p->pEList!=0 );
isAgg = (p->selFlags & SF_Aggregate)!=0;
assert( pEList!=0 );
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p, ("after name resolution:\n"));
@@ -4761,29 +4830,67 @@ int sqlite3Select(
#endif
/* Begin generating code.
*/
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto select_end;
/* If writing to memory or generating a set
** only a single column may be output.
*/
#ifndef SQLITE_OMIT_SUBQUERY
if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){
if( checkForMultiColumnSelectError(pParse, pDest, p->pEList->nExpr) ){
goto select_end;
}
#endif
/* Try to flatten subqueries in the FROM clause up into the main query
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
struct SrcList_item *pItem = &pTabList->a[i];
Select *pSub = pItem->pSelect;
int isAggSub;
if( pSub==0 ) continue;
isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
/* This subquery can be absorbed into its parent. */
if( isAggSub ){
isAgg = 1;
p->selFlags |= SF_Aggregate;
}
i = -1;
}
pTabList = p->pSrc;
if( db->mallocFailed ) goto select_end;
if( !IgnorableOrderby(pDest) ){
sSort.pOrderBy = p->pOrderBy;
}
}
#endif
/* Get a pointer the VDBE under construction, allocating a new VDBE if one
** does not already exist */
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto select_end;
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* Handle compound SELECT statements using the separate multiSelect()
** procedure.
*/
if( p->pPrior ){
rc = multiSelect(pParse, p, pDest);
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p,("end compound-select processing\n"));
pParse->nSelectIndent--;
#endif
return rc;
}
#endif
/* Generate code for all sub-queries in the FROM clause
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
for(i=0; !p->pPrior && i<pTabList->nSrc; i++){
for(i=0; i<pTabList->nSrc; i++){
struct SrcList_item *pItem = &pTabList->a[i];
SelectDest dest;
Select *pSub = pItem->pSelect;
int isAggSub;
if( pSub==0 ) continue;
/* Sometimes the code for a subquery will be generated more than
@@ -4808,17 +4915,25 @@ int sqlite3Select(
*/
pParse->nHeight += sqlite3SelectExprHeight(p);
isAggSub = (pSub->selFlags & SF_Aggregate)!=0;
if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){
/* This subquery can be absorbed into its parent. */
if( isAggSub ){
isAgg = 1;
p->selFlags |= SF_Aggregate;
/* Make copies of constant WHERE-clause terms in the outer query down
** inside the subquery. This can help the subquery to run more efficiently.
*/
if( (pItem->jointype & JT_OUTER)==0
&& pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor)
){
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
i = -1;
}else if( pTabList->nSrc==1
&& (p->selFlags & SF_All)==0
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
#endif
}
/* Generate code to implement the subquery
*/
if( pTabList->nSrc==1
&& (p->selFlags & SF_All)==0
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
){
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
@@ -4869,33 +4984,23 @@ int sqlite3Select(
sqlite3VdbeChangeP1(v, topAddr, retAddr);
sqlite3ClearTempRegCache(pParse);
}
if( /*pParse->nErr ||*/ db->mallocFailed ){
goto select_end;
}
if( db->mallocFailed ) goto select_end;
pParse->nHeight -= sqlite3SelectExprHeight(p);
pTabList = p->pSrc;
if( !IgnorableOrderby(pDest) ){
sSort.pOrderBy = p->pOrderBy;
}
}
pEList = p->pEList;
#endif
/* Various elements of the SELECT copied into local variables for
** convenience */
pEList = p->pEList;
pWhere = p->pWhere;
pGroupBy = p->pGroupBy;
pHaving = p->pHaving;
sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* If there is are a sequence of queries, do the earlier ones first.
*/
if( p->pPrior ){
rc = multiSelect(pParse, p, pDest);
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p,("end compound-select processing\n"));
pParse->nSelectIndent--;
#endif
return rc;
if( sqlite3SelectTrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -4915,23 +5020,23 @@ int sqlite3Select(
** BY and DISTINCT, and an index or separate temp-table for the other.
*/
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
&& sqlite3ExprListCompare(sSort.pOrderBy, p->pEList, -1)==0
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
){
p->selFlags &= ~SF_Distinct;
p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
pGroupBy = p->pGroupBy;
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
** the sDistinct.isTnct is still set. Hence, isTnct represents the
** original setting of the SF_Distinct flag, not the current setting */
assert( sDistinct.isTnct );
}
/* If there is an ORDER BY clause, then this sorting
** index might end up being unused if the data can be
** extracted in pre-sorted order. If that is the case, then the
** OP_OpenEphemeral instruction will be changed to an OP_Noop once
** we figure out that the sorting index is not needed. The addrSortIndex
** variable is used to facilitate that change.
/* If there is an ORDER BY clause, then create an ephemeral index to
** do the sorting. But this sorting ephemeral index might end up
** being unused if the data can be extracted in pre-sorted order.
** If that is the case, then the OP_OpenEphemeral instruction will be
** changed to an OP_Noop once we figure out that the sorting index is
** not needed. The sSort.addrSortIndex variable is used to facilitate
** that change.
*/
if( sSort.pOrderBy ){
KeyInfo *pKeyInfo;
@@ -4962,14 +5067,14 @@ int sqlite3Select(
sSort.sortFlags |= SORTFLAG_UseSorter;
}
/* Open a virtual index to use for the distinct set.
/* Open an ephemeral index to use for the distinct set.
*/
if( p->selFlags & SF_Distinct ){
sDistinct.tabTnct = pParse->nTab++;
sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
sDistinct.tabTnct, 0, 0,
(char*)keyInfoFromExprList(pParse, p->pEList,0,0),
P4_KEYINFO);
sDistinct.tabTnct, 0, 0,
(char*)keyInfoFromExprList(pParse, p->pEList,0,0),
P4_KEYINFO);
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
}else{
@@ -5047,11 +5152,10 @@ int sqlite3Select(
p->nSelectRow = 1;
}
/* If there is both a GROUP BY and an ORDER BY clause and they are
** identical, then it may be possible to disable the ORDER BY clause
** on the grounds that the GROUP BY will cause elements to come out
** in the correct order. It also may not - the GROUP BY may use a
** in the correct order. It also may not - the GROUP BY might use a
** database index that causes rows to be grouped together as required
** but not actually sorted. Either way, record the fact that the
** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
@@ -5229,7 +5333,8 @@ int sqlite3Select(
addrTopOfLoop = sqlite3VdbeCurrentAddr(v);
sqlite3ExprCacheClear(pParse);
if( groupBySort ){
sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, sortOut,sortPTab);
sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx,
sortOut, sortPTab);
}
for(j=0; j<pGroupBy->nExpr; j++){
if( groupBySort ){
@@ -5301,7 +5406,8 @@ int sqlite3Select(
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
sqlite3VdbeResolveLabel(v, addrOutputRow);
addrOutputRow = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2);
VdbeCoverage(v);
VdbeComment((v, "Groupby result generator entry point"));
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow);
finalizeAggFunctions(pParse, &sAggInfo);
@@ -5465,7 +5571,8 @@ int sqlite3Select(
** and send them to the callback one by one.
*/
if( sSort.pOrderBy ){
explainTempTable(pParse, sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY");
explainTempTable(pParse,
sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY");
generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest);
}
@@ -5497,97 +5604,3 @@ select_end:
#endif
return rc;
}
#ifdef SQLITE_DEBUG
/*
** Generate a human-readable description of a the Select object.
*/
void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0;
pView = sqlite3TreeViewPush(pView, moreToFollow);
sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags
);
if( p->pSrc && p->pSrc->nSrc ) n++;
if( p->pWhere ) n++;
if( p->pGroupBy ) n++;
if( p->pHaving ) n++;
if( p->pOrderBy ) n++;
if( p->pLimit ) n++;
if( p->pOffset ) n++;
if( p->pPrior ) n++;
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
if( p->pSrc && p->pSrc->nSrc ){
int i;
pView = sqlite3TreeViewPush(pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
for(i=0; i<p->pSrc->nSrc; i++){
struct SrcList_item *pItem = &p->pSrc->a[i];
StrAccum x;
char zLine[100];
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor);
if( pItem->zDatabase ){
sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName);
}else if( pItem->zName ){
sqlite3XPrintf(&x, 0, " %s", pItem->zName);
}
if( pItem->pTab ){
sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName);
}
if( pItem->zAlias ){
sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias);
}
if( pItem->jointype & JT_LEFT ){
sqlite3XPrintf(&x, 0, " LEFT-JOIN");
}
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1);
if( pItem->pSelect ){
sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
}
sqlite3TreeViewPop(pView);
}
sqlite3TreeViewPop(pView);
}
if( p->pWhere ){
sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
sqlite3TreeViewExpr(pView, p->pWhere, 0);
sqlite3TreeViewPop(pView);
}
if( p->pGroupBy ){
sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
}
if( p->pHaving ){
sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
sqlite3TreeViewExpr(pView, p->pHaving, 0);
sqlite3TreeViewPop(pView);
}
if( p->pOrderBy ){
sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
}
if( p->pLimit ){
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit, 0);
sqlite3TreeViewPop(pView);
}
if( p->pOffset ){
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
sqlite3TreeViewExpr(pView, p->pOffset, 0);
sqlite3TreeViewPop(pView);
}
if( p->pPrior ){
const char *zOp = "UNION";
switch( p->op ){
case TK_ALL: zOp = "UNION ALL"; break;
case TK_INTERSECT: zOp = "INTERSECT"; break;
case TK_EXCEPT: zOp = "EXCEPT"; break;
}
sqlite3TreeViewItem(pView, zOp, (n--)>0);
sqlite3TreeViewSelect(pView, p->pPrior, 0);
sqlite3TreeViewPop(pView);
}
sqlite3TreeViewPop(pView);
}
#endif /* SQLITE_DEBUG */
+42 -32
View File
@@ -101,28 +101,34 @@
#if defined(_WIN32) || defined(WIN32)
# include <io.h>
# include <fcntl.h>
#define isatty(h) _isatty(h)
#ifndef access
# define access(f,m) _access((f),(m))
#endif
#undef popen
#define popen _popen
#undef pclose
#define pclose _pclose
# define isatty(h) _isatty(h)
# ifndef access
# define access(f,m) _access((f),(m))
# endif
# undef popen
# define popen _popen
# undef pclose
# define pclose _pclose
# if !defined(SQLITE_POPEN_MODE) && defined(_MSC_VER)
# define SQLITE_POPEN_MODE "b"
# else
# define SQLITE_POPEN_MODE ""
# endif
#else
/* Make sure isatty() has a prototype.
*/
extern int isatty(int);
#if !defined(__RTP__) && !defined(_WRS_KERNEL)
/* popen and pclose are not C89 functions and so are sometimes omitted from
** the <stdio.h> header */
extern FILE *popen(const char*,const char*);
extern int pclose(FILE*);
#else
# define SQLITE_OMIT_POPEN 1
#endif
/* Make sure isatty() has a prototype. */
extern int isatty(int);
# if !defined(__RTP__) && !defined(_WRS_KERNEL)
/* popen and pclose are not C89 functions and so are
** sometimes omitted from the <stdio.h> header */
extern FILE *popen(const char*,const char*);
extern int pclose(FILE*);
# ifndef SQLITE_POPEN_MODE
# define SQLITE_POPEN_MODE ""
# endif
# else
# define SQLITE_OMIT_POPEN 1
# endif
#endif
#if defined(_WIN32_WCE)
@@ -1331,7 +1337,10 @@ static void display_scanstats(
sqlite3 *db, /* Database to query */
ShellState *pArg /* Pointer to ShellState */
){
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
UNUSED_PARAMETER(db);
UNUSED_PARAMETER(pArg);
#else
int i, k, n, mx;
fprintf(pArg->out, "-------- scanstats --------\n");
mx = 0;
@@ -1866,6 +1875,7 @@ static void readfileFunc(
long nIn;
void *pBuf;
UNUSED_PARAMETER(argc);
zName = (const char*)sqlite3_value_text(argv[0]);
if( zName==0 ) return;
in = fopen(zName, "rb");
@@ -1898,6 +1908,7 @@ static void writefileFunc(
sqlite3_int64 rc;
const char *zFile;
UNUSED_PARAMETER(argc);
zFile = (const char*)sqlite3_value_text(argv[0]);
if( zFile==0 ) return;
out = fopen(zFile, "wb");
@@ -2577,7 +2588,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
fprintf(p->out, "%-20s %d\n", "write format:", aHdr[18]);
fprintf(p->out, "%-20s %d\n", "read format:", aHdr[19]);
fprintf(p->out, "%-20s %d\n", "reserved bytes:", aHdr[20]);
for(i=0; i<sizeof(aField)/sizeof(aField[0]); i++){
for(i=0; i<ArraySize(aField); i++){
int ofst = aField[i].ofst;
unsigned int val = get4byteInt(aHdr + ofst);
fprintf(p->out, "%-20s %u", aField[i].zName, val);
@@ -2597,7 +2608,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
}else{
zSchemaTab = sqlite3_mprintf("\"%w\".sqlite_master", zDb);
}
for(i=0; i<sizeof(aQuery)/sizeof(aQuery[0]); i++){
for(i=0; i<ArraySize(aQuery); i++){
char *zSql = sqlite3_mprintf(aQuery[i].zSql, zSchemaTab);
int val = db_int(p, zSql);
sqlite3_free(zSql);
@@ -3001,7 +3012,7 @@ static int do_meta_command(char *zLine, ShellState *p){
fprintf(stderr, "Error: pipes are not supported in this OS\n");
return 1;
#else
sCtx.in = popen(sCtx.zFile+1, "r");
sCtx.in = popen(sCtx.zFile+1, "r" SQLITE_POPEN_MODE);
sCtx.zFile = "<pipe>";
xCloser = pclose;
#endif
@@ -3228,7 +3239,7 @@ static int do_meta_command(char *zLine, ShellState *p){
int i, n2;
open_db(p, 0);
if( nArg==1 ){
for(i=0; i<sizeof(aLimit)/sizeof(aLimit[0]); i++){
for(i=0; i<ArraySize(aLimit); i++){
printf("%20s %d\n", aLimit[i].zLimitName,
sqlite3_limit(p->db, aLimit[i].limitCode, -1));
}
@@ -3239,7 +3250,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}else{
int iLimit = -1;
n2 = strlen30(azArg[1]);
for(i=0; i<sizeof(aLimit)/sizeof(aLimit[0]); i++){
for(i=0; i<ArraySize(aLimit); i++){
if( sqlite3_strnicmp(aLimit[i].zLimitName, azArg[1], n2)==0 ){
if( iLimit<0 ){
iLimit = i;
@@ -3349,9 +3360,8 @@ static int do_meta_command(char *zLine, ShellState *p){
const char *zSavedFilename = p->zDbFilename;
char *zNewFilename = 0;
p->db = 0;
if( nArg>=2 ){
p->zDbFilename = zNewFilename = sqlite3_mprintf("%s", azArg[1]);
}
if( nArg>=2 ) zNewFilename = sqlite3_mprintf("%s", azArg[1]);
p->zDbFilename = zNewFilename;
open_db(p, 1);
if( p->db!=0 ){
sqlite3_close(savedDb);
@@ -3390,7 +3400,7 @@ static int do_meta_command(char *zLine, ShellState *p){
rc = 1;
p->out = stdout;
#else
p->out = popen(zFile + 1, "w");
p->out = popen(zFile + 1, "w" SQLITE_POPEN_MODE);
if( p->out==0 ){
fprintf(stderr,"Error: cannot open pipe \"%s\"\n", zFile + 1);
p->out = stdout;
@@ -3815,7 +3825,7 @@ static int do_meta_command(char *zLine, ShellState *p){
/* convert testctrl text option to value. allow any unique prefix
** of the option name, or a numerical value. */
n2 = strlen30(azArg[1]);
for(i=0; i<(int)(sizeof(aCtrl)/sizeof(aCtrl[0])); i++){
for(i=0; i<ArraySize(aCtrl); i++){
if( strncmp(azArg[1], aCtrl[i].zCtrlName, n2)==0 ){
if( testctrl<0 ){
testctrl = aCtrl[i].ctrlCode;
@@ -4792,7 +4802,7 @@ int SQLITE_CDECL main(int argc, char **argv){
sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
}
}
if( zHistory ) shell_read_history(zHistory);
if( zHistory ){ shell_read_history(zHistory); }
rc = process_input(&data, 0);
if( zHistory ){
shell_stifle_history(100);
+1 -1
View File
@@ -23,7 +23,7 @@
**
** The official C-language API documentation for SQLite is derived
** from comments in this file. This file is the authoritative source
** on how SQLite interfaces are suppose to operate.
** on how SQLite interfaces are supposed to operate.
**
** The name of this file under configuration management is "sqlite.h.in".
** The makefile makes some minor changes to this file (such as inserting
+2 -1
View File
@@ -267,7 +267,8 @@ struct sqlite3_api_routines {
void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64,
void(*)(void*), unsigned char);
int (*strglob)(const char*,const char*);
sqlite3_value (*value_dup)(const sqlite3_value*);
/* Version 3.8.11 and later */
sqlite3_value *(*value_dup)(const sqlite3_value*);
void (*value_free)(sqlite3_value*);
};
+22 -18
View File
@@ -1348,19 +1348,18 @@ struct FuncDestructor {
** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. There
** are assert() statements in the code to verify this.
*/
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
#define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */
#define SQLITE_FUNC_CASE 0x0008 /* Case-sensitive LIKE-type function */
#define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */
#define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq might be called */
#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
#define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
#define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */
#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
#define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
#define SQLITE_FUNC_AFFINITY 0x2000 /* Built-in affinity() function */
#define SQLITE_FUNC_ENCMASK 0x003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
#define SQLITE_FUNC_LIKE 0x004 /* Candidate for the LIKE optimization */
#define SQLITE_FUNC_CASE 0x008 /* Case-sensitive LIKE-type function */
#define SQLITE_FUNC_EPHEM 0x010 /* Ephemeral. Delete with VDBE */
#define SQLITE_FUNC_NEEDCOLL 0x020 /* sqlite3GetFuncCollSeq() might be called */
#define SQLITE_FUNC_LENGTH 0x040 /* Built-in length() function */
#define SQLITE_FUNC_TYPEOF 0x080 /* Built-in typeof() function */
#define SQLITE_FUNC_COUNT 0x100 /* Built-in count(*) aggregate */
#define SQLITE_FUNC_COALESCE 0x200 /* Built-in coalesce() or ifnull() */
#define SQLITE_FUNC_UNLIKELY 0x400 /* Built-in unlikely() function */
#define SQLITE_FUNC_CONSTANT 0x800 /* Constant inputs give a constant output */
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -2261,7 +2260,7 @@ struct SrcList {
Expr *pOn; /* The ON clause of a join */
IdList *pUsing; /* The USING clause of a join */
Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */
char *zIndex; /* Identifier from "INDEXED BY <zIndex>" clause */
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
Index *pIndex; /* Index structure corresponding to zIndex, if any */
} a[1]; /* One entry for each identifier on the list */
};
@@ -3067,7 +3066,9 @@ int sqlite3CantopenError(int);
# define sqlite3Isxdigit(x) isxdigit((unsigned char)(x))
# define sqlite3Tolower(x) tolower((unsigned char)(x))
#endif
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
int sqlite3IsIdChar(u8);
#endif
/*
** Internal function prototypes
@@ -3095,7 +3096,9 @@ void sqlite3ScratchFree(void*);
void *sqlite3PageMalloc(int);
void sqlite3PageFree(void*);
void sqlite3MemSetDefault(void);
#ifndef SQLITE_OMIT_BUILTIN_TEST
void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
#endif
int sqlite3HeapNearlyFull(void);
/*
@@ -3171,10 +3174,6 @@ char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
#endif
#if defined(SQLITE_DEBUG)
TreeView *sqlite3TreeViewPush(TreeView*,u8);
void sqlite3TreeViewPop(TreeView*);
void sqlite3TreeViewLine(TreeView*, const char*, ...);
void sqlite3TreeViewItem(TreeView*, const char*, u8);
void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
@@ -3243,7 +3242,9 @@ int sqlite3BitvecSet(Bitvec*, u32);
void sqlite3BitvecClear(Bitvec*, u32, void*);
void sqlite3BitvecDestroy(Bitvec*);
u32 sqlite3BitvecSize(Bitvec*);
#ifndef SQLITE_OMIT_BUILTIN_TEST
int sqlite3BitvecBuiltinTest(int,int*);
#endif
RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);
void sqlite3RowSetClear(RowSet*);
@@ -3331,6 +3332,7 @@ int sqlite3ExprCodeExprList(Parse*, ExprList*, int, u8);
#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int);
Table *sqlite3FindTable(sqlite3*,const char*, const char*);
Table *sqlite3LocateTable(Parse*,int isView,const char*, const char*);
Table *sqlite3LocateTableItem(Parse*,int isView,struct SrcList_item *);
@@ -3347,8 +3349,10 @@ void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
Vdbe *sqlite3GetVdbe(Parse*);
#ifndef SQLITE_OMIT_BUILTIN_TEST
void sqlite3PrngSaveState(void);
void sqlite3PrngRestoreState(void);
#endif
void sqlite3RollbackAll(sqlite3*,int);
void sqlite3CodeVerifySchema(Parse*, int);
void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
+4
View File
@@ -102,7 +102,11 @@ const char sqlite3IsEbcdicIdChar[] = {
};
#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40]))
#endif
/* Make the IdChar function accessible from ctime.c */
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
int sqlite3IsIdChar(u8 c){ return IdChar(c); }
#endif
/*
+425
View File
@@ -0,0 +1,425 @@
/*
** 2015-06-08
**
** 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 contains C code to implement the TreeView debugging routines.
** These routines print a parse tree to standard output for debugging and
** analysis.
**
** The interfaces in this file is only available when compiling
** with SQLITE_DEBUG.
*/
#include "sqliteInt.h"
#ifdef SQLITE_DEBUG
/*
** Add a new subitem to the tree. The moreToFollow flag indicates that this
** is not the last item in the tree.
*/
static TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
if( p==0 ){
p = sqlite3_malloc64( sizeof(*p) );
if( p==0 ) return 0;
memset(p, 0, sizeof(*p));
}else{
p->iLevel++;
}
assert( moreToFollow==0 || moreToFollow==1 );
if( p->iLevel<sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
return p;
}
/*
** Finished with one layer of the tree
*/
static void sqlite3TreeViewPop(TreeView *p){
if( p==0 ) return;
p->iLevel--;
if( p->iLevel<0 ) sqlite3_free(p);
}
/*
** Generate a single line of output for the tree, with a prefix that contains
** all the appropriate tree lines
*/
static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_list ap;
int i;
StrAccum acc;
char zBuf[500];
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
if( p ){
for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4);
}
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
}
va_start(ap, zFormat);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
va_end(ap);
if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1);
sqlite3StrAccumFinish(&acc);
fprintf(stdout,"%s", zBuf);
fflush(stdout);
}
/*
** Shorthand for starting a new tree item that consists of a single label
*/
static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
p = sqlite3TreeViewPush(p, moreFollows);
sqlite3TreeViewLine(p, "%s", zLabel);
}
/*
** Generate a human-readable description of a the Select object.
*/
void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0;
pView = sqlite3TreeViewPush(pView, moreToFollow);
sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p) selFlags=0x%x",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p, p->selFlags
);
if( p->pSrc && p->pSrc->nSrc ) n++;
if( p->pWhere ) n++;
if( p->pGroupBy ) n++;
if( p->pHaving ) n++;
if( p->pOrderBy ) n++;
if( p->pLimit ) n++;
if( p->pOffset ) n++;
if( p->pPrior ) n++;
sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
if( p->pSrc && p->pSrc->nSrc ){
int i;
pView = sqlite3TreeViewPush(pView, (n--)>0);
sqlite3TreeViewLine(pView, "FROM");
for(i=0; i<p->pSrc->nSrc; i++){
struct SrcList_item *pItem = &p->pSrc->a[i];
StrAccum x;
char zLine[100];
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor);
if( pItem->zDatabase ){
sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName);
}else if( pItem->zName ){
sqlite3XPrintf(&x, 0, " %s", pItem->zName);
}
if( pItem->pTab ){
sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName);
}
if( pItem->zAlias ){
sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias);
}
if( pItem->jointype & JT_LEFT ){
sqlite3XPrintf(&x, 0, " LEFT-JOIN");
}
sqlite3StrAccumFinish(&x);
sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1);
if( pItem->pSelect ){
sqlite3TreeViewSelect(pView, pItem->pSelect, 0);
}
sqlite3TreeViewPop(pView);
}
sqlite3TreeViewPop(pView);
}
if( p->pWhere ){
sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
sqlite3TreeViewExpr(pView, p->pWhere, 0);
sqlite3TreeViewPop(pView);
}
if( p->pGroupBy ){
sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
}
if( p->pHaving ){
sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
sqlite3TreeViewExpr(pView, p->pHaving, 0);
sqlite3TreeViewPop(pView);
}
if( p->pOrderBy ){
sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
}
if( p->pLimit ){
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
sqlite3TreeViewExpr(pView, p->pLimit, 0);
sqlite3TreeViewPop(pView);
}
if( p->pOffset ){
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
sqlite3TreeViewExpr(pView, p->pOffset, 0);
sqlite3TreeViewPop(pView);
}
if( p->pPrior ){
const char *zOp = "UNION";
switch( p->op ){
case TK_ALL: zOp = "UNION ALL"; break;
case TK_INTERSECT: zOp = "INTERSECT"; break;
case TK_EXCEPT: zOp = "EXCEPT"; break;
}
sqlite3TreeViewItem(pView, zOp, (n--)>0);
sqlite3TreeViewSelect(pView, p->pPrior, 0);
sqlite3TreeViewPop(pView);
}
sqlite3TreeViewPop(pView);
}
/*
** Generate a human-readable explanation of an expression tree.
*/
void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
const char *zBinOp = 0; /* Binary operator */
const char *zUniOp = 0; /* Unary operator */
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( pExpr==0 ){
sqlite3TreeViewLine(pView, "nil");
sqlite3TreeViewPop(pView);
return;
}
switch( pExpr->op ){
case TK_AGG_COLUMN: {
sqlite3TreeViewLine(pView, "AGG{%d:%d}",
pExpr->iTable, pExpr->iColumn);
break;
}
case TK_COLUMN: {
if( pExpr->iTable<0 ){
/* This only happens when coding check constraints */
sqlite3TreeViewLine(pView, "COLUMN(%d)", pExpr->iColumn);
}else{
sqlite3TreeViewLine(pView, "{%d:%d}",
pExpr->iTable, pExpr->iColumn);
}
break;
}
case TK_INTEGER: {
if( pExpr->flags & EP_IntValue ){
sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
}else{
sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
}
break;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
case TK_FLOAT: {
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_STRING: {
sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
break;
}
case TK_NULL: {
sqlite3TreeViewLine(pView,"NULL");
break;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
break;
}
#endif
case TK_VARIABLE: {
sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
pExpr->u.zToken, pExpr->iColumn);
break;
}
case TK_REGISTER: {
sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
break;
}
case TK_AS: {
sqlite3TreeViewLine(pView,"AS %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_ID: {
sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
break;
}
#ifndef SQLITE_OMIT_CAST
case TK_CAST: {
/* Expressions of the form: CAST(pLeft AS token) */
sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
#endif /* SQLITE_OMIT_CAST */
case TK_LT: zBinOp = "LT"; break;
case TK_LE: zBinOp = "LE"; break;
case TK_GT: zBinOp = "GT"; break;
case TK_GE: zBinOp = "GE"; break;
case TK_NE: zBinOp = "NE"; break;
case TK_EQ: zBinOp = "EQ"; break;
case TK_IS: zBinOp = "IS"; break;
case TK_ISNOT: zBinOp = "ISNOT"; break;
case TK_AND: zBinOp = "AND"; break;
case TK_OR: zBinOp = "OR"; break;
case TK_PLUS: zBinOp = "ADD"; break;
case TK_STAR: zBinOp = "MUL"; break;
case TK_MINUS: zBinOp = "SUB"; break;
case TK_REM: zBinOp = "REM"; break;
case TK_BITAND: zBinOp = "BITAND"; break;
case TK_BITOR: zBinOp = "BITOR"; break;
case TK_SLASH: zBinOp = "DIV"; break;
case TK_LSHIFT: zBinOp = "LSHIFT"; break;
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
case TK_CONCAT: zBinOp = "CONCAT"; break;
case TK_DOT: zBinOp = "DOT"; break;
case TK_UMINUS: zUniOp = "UMINUS"; break;
case TK_UPLUS: zUniOp = "UPLUS"; break;
case TK_BITNOT: zUniOp = "BITNOT"; break;
case TK_NOT: zUniOp = "NOT"; break;
case TK_ISNULL: zUniOp = "ISNULL"; break;
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
case TK_COLLATE: {
sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
break;
}
case TK_AGG_FUNCTION:
case TK_FUNCTION: {
ExprList *pFarg; /* List of function arguments */
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
pFarg = 0;
}else{
pFarg = pExpr->x.pList;
}
if( pExpr->op==TK_AGG_FUNCTION ){
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
pExpr->op2, pExpr->u.zToken);
}else{
sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
}
if( pFarg ){
sqlite3TreeViewExprList(pView, pFarg, 0, 0);
}
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_EXISTS: {
sqlite3TreeViewLine(pView, "EXISTS-expr");
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_SELECT: {
sqlite3TreeViewLine(pView, "SELECT-expr");
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
break;
}
case TK_IN: {
sqlite3TreeViewLine(pView, "IN");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
}else{
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
}
break;
}
#endif /* SQLITE_OMIT_SUBQUERY */
/*
** x BETWEEN y AND z
**
** This is equivalent to
**
** x>=y AND x<=z
**
** X is stored in pExpr->pLeft.
** Y is stored in pExpr->pList->a[0].pExpr.
** Z is stored in pExpr->pList->a[1].pExpr.
*/
case TK_BETWEEN: {
Expr *pX = pExpr->pLeft;
Expr *pY = pExpr->x.pList->a[0].pExpr;
Expr *pZ = pExpr->x.pList->a[1].pExpr;
sqlite3TreeViewLine(pView, "BETWEEN");
sqlite3TreeViewExpr(pView, pX, 1);
sqlite3TreeViewExpr(pView, pY, 1);
sqlite3TreeViewExpr(pView, pZ, 0);
break;
}
case TK_TRIGGER: {
/* If the opcode is TK_TRIGGER, then the expression is a reference
** to a column in the new.* or old.* pseudo-tables available to
** trigger programs. In this case Expr.iTable is set to 1 for the
** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
** is set to the column of the pseudo-table to read, or to -1 to
** read the rowid field.
*/
sqlite3TreeViewLine(pView, "%s(%d)",
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
break;
}
case TK_CASE: {
sqlite3TreeViewLine(pView, "CASE");
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
break;
}
#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
const char *zType = "unk";
switch( pExpr->affinity ){
case OE_Rollback: zType = "rollback"; break;
case OE_Abort: zType = "abort"; break;
case OE_Fail: zType = "fail"; break;
case OE_Ignore: zType = "ignore"; break;
}
sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
break;
}
#endif
default: {
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
break;
}
}
if( zBinOp ){
sqlite3TreeViewLine(pView, "%s", zBinOp);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
}else if( zUniOp ){
sqlite3TreeViewLine(pView, "%s", zUniOp);
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
}
sqlite3TreeViewPop(pView);
}
/*
** Generate a human-readable explanation of an expression list.
*/
void sqlite3TreeViewExprList(
TreeView *pView,
const ExprList *pList,
u8 moreToFollow,
const char *zLabel
){
int i;
pView = sqlite3TreeViewPush(pView, moreToFollow);
if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
if( pList==0 ){
sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
}else{
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; i<pList->nExpr; i++){
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1);
}
}
sqlite3TreeViewPop(pView);
}
#endif /* SQLITE_DEBUG */
+20
View File
@@ -3511,6 +3511,26 @@ case OP_Close: {
break;
}
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
/* Opcode: ColumnsUsed P1 * * P4 *
**
** This opcode (which only exists if SQLite was compiled with
** SQLITE_ENABLE_COLUMN_USED_MASK) identifies which columns of the
** table or index for cursor P1 are used. P4 is a 64-bit integer
** (P4_INT64) in which the first 63 bits are one for each of the
** first 63 columns of the table or index that are actually used
** by the cursor. The high-order bit is set if any column after
** the 64th is used.
*/
case OP_ColumnsUsed: {
VdbeCursor *pC;
pC = p->apCsr[pOp->p1];
assert( pC->pCursor );
pC->maskUsed = *(u64*)pOp->p4.pI64;
break;
}
#endif
/* Opcode: SeekGE P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
**
+1
View File
@@ -169,6 +169,7 @@ int sqlite3VdbeAddOp1(Vdbe*,int,int);
int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int);
int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
+3
View File
@@ -83,6 +83,9 @@ struct VdbeCursor {
i64 seqCount; /* Sequence counter */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
u64 maskUsed; /* Mask of columns used by this cursor */
#endif
/* Cached information about the header for the data record that the
** cursor is currently pointing to. Only valid if cacheStatus matches
+29 -3
View File
@@ -233,6 +233,23 @@ int sqlite3VdbeAddOp4(
return addr;
}
/*
** Add an opcode that includes the p4 value with a P4_INT64 type.
*/
int sqlite3VdbeAddOp4Dup8(
Vdbe *p, /* Add the opcode to this VM */
int op, /* The new opcode */
int p1, /* The P1 operand */
int p2, /* The P2 operand */
int p3, /* The P3 operand */
const u8 *zP4, /* The P4 operand */
int p4type /* P4 operand type */
){
char *p4copy = sqlite3DbMallocRaw(sqlite3VdbeDb(p), 8);
if( p4copy ) memcpy(p4copy, zP4, 8);
return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type);
}
/*
** Add an OP_ParseSchema opcode. This routine is broken out from
** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees
@@ -397,6 +414,7 @@ static Op *opIterNext(VdbeOpIter *p){
** * OP_VUpdate
** * OP_VRename
** * OP_FkCounter with P2==0 (immediate foreign key constraint)
** * OP_CreateTable and OP_InitCoroutine (for CREATE TABLE AS SELECT ...)
**
** Then check that the value of Parse.mayAbort is true if an
** ABORT may be thrown, or false otherwise. Return true if it does
@@ -408,6 +426,8 @@ static Op *opIterNext(VdbeOpIter *p){
int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
int hasAbort = 0;
int hasFkCounter = 0;
int hasCreateTable = 0;
int hasInitCoroutine = 0;
Op *pOp;
VdbeOpIter sIter;
memset(&sIter, 0, sizeof(sIter));
@@ -422,6 +442,8 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
hasAbort = 1;
break;
}
if( opcode==OP_CreateTable ) hasCreateTable = 1;
if( opcode==OP_InitCoroutine ) hasInitCoroutine = 1;
#ifndef SQLITE_OMIT_FOREIGN_KEY
if( opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1 ){
hasFkCounter = 1;
@@ -435,7 +457,8 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
** through all opcodes and hasAbort may be set incorrectly. Return
** true for this case to prevent the assert() in the callers frame
** from failing. */
return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter );
return ( v->db->mallocFailed || hasAbort==mayAbort || hasFkCounter
|| (hasCreateTable && hasInitCoroutine) );
}
#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
@@ -1218,12 +1241,11 @@ void sqlite3VdbeEnter(Vdbe *p){
/*
** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter().
*/
void sqlite3VdbeLeave(Vdbe *p){
static SQLITE_NOINLINE void vdbeLeave(Vdbe *p){
int i;
sqlite3 *db;
Db *aDb;
int nDb;
if( DbMaskAllZero(p->lockMask) ) return; /* The common case */
db = p->db;
aDb = db->aDb;
nDb = db->nDb;
@@ -1233,6 +1255,10 @@ void sqlite3VdbeLeave(Vdbe *p){
}
}
}
void sqlite3VdbeLeave(Vdbe *p){
if( DbMaskAllZero(p->lockMask) ) return; /* The common case */
vdbeLeave(p);
}
#endif
#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
+27 -16
View File
@@ -946,6 +946,32 @@ int sqlite3VdbeMemSetStr(
** If this routine fails for any reason (malloc returns NULL or unable
** to read from the disk) then the pMem is left in an inconsistent state.
*/
static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
u32 offset, /* Offset from the start of data to return bytes from. */
u32 amt, /* Number of bytes to return. */
int key, /* If true, retrieve from the btree key, not data. */
Mem *pMem /* OUT: Return data in this Mem structure. */
){
int rc;
pMem->flags = MEM_Null;
if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){
if( key ){
rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
}else{
rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
}
if( rc==SQLITE_OK ){
pMem->z[amt] = 0;
pMem->z[amt+1] = 0;
pMem->flags = MEM_Blob|MEM_Term;
pMem->n = (int)amt;
}else{
sqlite3VdbeMemRelease(pMem);
}
}
return rc;
}
int sqlite3VdbeMemFromBtree(
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
u32 offset, /* Offset from the start of data to return bytes from. */
@@ -975,22 +1001,7 @@ int sqlite3VdbeMemFromBtree(
pMem->flags = MEM_Blob|MEM_Ephem;
pMem->n = (int)amt;
}else{
pMem->flags = MEM_Null;
if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){
if( key ){
rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
}else{
rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
}
if( rc==SQLITE_OK ){
pMem->z[amt] = 0;
pMem->z[amt+1] = 0;
pMem->flags = MEM_Blob|MEM_Term;
pMem->n = (int)amt;
}else{
sqlite3VdbeMemRelease(pMem);
}
}
rc = vdbeMemFromBtreeResize(pCur, offset, amt, key, pMem);
}
return rc;
+115 -2755
View File
File diff suppressed because it is too large Load Diff
+62 -5
View File
@@ -19,7 +19,7 @@
** Trace output macros
*/
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
/***/ int sqlite3WhereTrace = 0;
/***/ int sqlite3WhereTrace;
#endif
#if defined(SQLITE_DEBUG) \
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
@@ -161,10 +161,6 @@ struct WhereOrSet {
WhereOrCost a[N_OR_COST]; /* Set of best costs */
};
/* Forward declaration of methods */
static int whereLoopResize(sqlite3*, WhereLoop*, int);
/*
** Each instance of this object holds a sequence of WhereLoop objects
** that implement some or all of a query plan.
@@ -372,6 +368,11 @@ struct WhereMaskSet {
int ix[BMS]; /* Cursor assigned to each bit */
};
/*
** Initialize a WhereMaskSet object
*/
#define initMaskSet(P) (P)->n=0
/*
** This object is a convenience wrapper holding all information needed
** to construct WhereLoop objects for a particular query.
@@ -423,6 +424,62 @@ struct WhereInfo {
WhereLevel a[1]; /* Information about each nest loop in WHERE */
};
/*
** Private interfaces - callable only by other where.c routines.
**
** where.c:
*/
Bitmask sqlite3WhereGetMask(WhereMaskSet*,int);
WhereTerm *sqlite3WhereFindTerm(
WhereClause *pWC, /* The WHERE clause to be searched */
int iCur, /* Cursor number of LHS */
int iColumn, /* Column number of LHS */
Bitmask notReady, /* RHS must not overlap with this mask */
u32 op, /* Mask of WO_xx values describing operator */
Index *pIdx /* Must be compatible with this index, if not NULL */
);
/* wherecode.c: */
#ifndef SQLITE_OMIT_EXPLAIN
int sqlite3WhereExplainOneScan(
Parse *pParse, /* Parse context */
SrcList *pTabList, /* Table list this loop refers to */
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
int iLevel, /* Value for "level" column of output */
int iFrom, /* Value for "from" column of output */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
);
#else
# define sqlite3WhereExplainOneScan(u,v,w,x,y,z) 0
#endif /* SQLITE_OMIT_EXPLAIN */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
void sqlite3WhereAddScanStatus(
Vdbe *v, /* Vdbe to add scanstatus entry to */
SrcList *pSrclist, /* FROM clause pLvl reads data from */
WhereLevel *pLvl, /* Level to add scanstatus() entry for */
int addrExplain /* Address of OP_Explain (or 0) */
);
#else
# define sqlite3WhereAddScanStatus(a, b, c, d) ((void)d)
#endif
Bitmask sqlite3WhereCodeOneLoopStart(
WhereInfo *pWInfo, /* Complete information about the WHERE clause */
int iLevel, /* Which level of pWInfo->a[] should be coded */
Bitmask notReady /* Which tables are currently available */
);
/* whereexpr.c: */
void sqlite3WhereClauseInit(WhereClause*,WhereInfo*);
void sqlite3WhereClauseClear(WhereClause*);
void sqlite3WhereSplit(WhereClause*,Expr*,u8);
Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*);
Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*);
void sqlite3WhereExprAnalyze(SrcList*, WhereClause*);
/*
** Bitmasks for the operators on WhereTerm objects. These are all
** operators that are of interest to the query planner. An
+1501
View File
File diff suppressed because it is too large Load Diff
+1249
View File
File diff suppressed because it is too large Load Diff
-88
View File
@@ -1,88 +0,0 @@
# 2015-06-02
#
# 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 type affinity and the affinity() built-in
# function.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix affinity1
do_execsql_test 100 {
CREATE TABLE t1(
c01 INT,
c02 INTEGER,
c03 TINYINT,
c04 SMALLINT,
c05 MEDIUMINT,
c06 BIGINT,
c07 UNSIGNED BIG INT,
c08 INT2,
c09 INT4,
c10 CHARACTER(20),
c11 VARCHAR(255),
c12 VARYING CHARACTER(255),
c13 NCHAR(55),
c14 NATIVE CHARACTER(70),
c15 NVARCHAR(100),
c16 TEXT,
c17 CLOB,
c20 BLOB,
c21,
c30 REAL,
c31 DOUBLE,
c32 DOUBLE PRECISION,
c33 FLOAT,
c40 NUMERIC,
c41 DECIMAL(10,5),
c42 BOOLEAN,
c43 DATE,
c44 DATETIME,
c50 FLOATING POINT,
c60 STRING
);
INSERT INTO t1 DEFAULT VALUES;
} {}
do_execsql_test 201 {
SELECT affinity(c01), affinity(c01+1), affinity(+c01) FROM t1;
} {INTEGER {} {}}
do_execsql_test 202 {SELECT affinity(c02) FROM t1} {INTEGER}
do_execsql_test 203 {SELECT affinity(c03) FROM t1} {INTEGER}
do_execsql_test 204 {SELECT affinity(c04) FROM t1} {INTEGER}
do_execsql_test 205 {SELECT affinity(c05) FROM t1} {INTEGER}
do_execsql_test 206 {SELECT affinity(c06) FROM t1} {INTEGER}
do_execsql_test 207 {SELECT affinity(c07) FROM t1} {INTEGER}
do_execsql_test 208 {SELECT affinity(c08) FROM t1} {INTEGER}
do_execsql_test 209 {SELECT affinity(c09) FROM t1} {INTEGER}
do_execsql_test 210 {SELECT affinity(c10) FROM t1} {TEXT}
do_execsql_test 211 {SELECT affinity(c11) FROM t1} {TEXT}
do_execsql_test 212 {SELECT affinity(c12) FROM t1} {TEXT}
do_execsql_test 213 {SELECT affinity(c13) FROM t1} {TEXT}
do_execsql_test 214 {SELECT affinity(c14) FROM t1} {TEXT}
do_execsql_test 215 {SELECT affinity(c15) FROM t1} {TEXT}
do_execsql_test 216 {SELECT affinity(c16) FROM t1} {TEXT}
do_execsql_test 220 {SELECT affinity(c20) FROM t1} {BLOB}
do_execsql_test 221 {SELECT affinity(c21) FROM t1} {BLOB}
do_execsql_test 230 {SELECT affinity(c30) FROM t1} {REAL}
do_execsql_test 231 {SELECT affinity(c31) FROM t1} {REAL}
do_execsql_test 232 {SELECT affinity(c32) FROM t1} {REAL}
do_execsql_test 233 {SELECT affinity(c33) FROM t1} {REAL}
do_execsql_test 240 {SELECT affinity(c40) FROM t1} {NUMERIC}
do_execsql_test 241 {SELECT affinity(c41) FROM t1} {NUMERIC}
do_execsql_test 242 {SELECT affinity(c42) FROM t1} {NUMERIC}
do_execsql_test 243 {SELECT affinity(c43) FROM t1} {NUMERIC}
do_execsql_test 244 {SELECT affinity(c44) FROM t1} {NUMERIC}
do_execsql_test 250 {SELECT affinity(c50) FROM t1} {INTEGER}
do_execsql_test 260 {SELECT affinity(c60) FROM t1} {NUMERIC}
finish_test
+61
View File
@@ -0,0 +1,61 @@
# 2015-06-02
#
# 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 type affinity in comparison operations.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_execsql_test affinity2-100 {
CREATE TABLE t1(
xi INTEGER,
xr REAL,
xb BLOB,
xn NUMERIC,
xt TEXT
);
INSERT INTO t1(rowid,xi,xr,xb,xn,xt) VALUES(1,1,1,1,1,1);
INSERT INTO t1(rowid,xi,xr,xb,xn,xt) VALUES(2,'2','2','2','2','2');
INSERT INTO t1(rowid,xi,xr,xb,xn,xt) VALUES(3,'03','03','03','03','03');
} {}
do_execsql_test affinity2-110 {
SELECT xi, typeof(xi) FROM t1 ORDER BY rowid;
} {1 integer 2 integer 3 integer}
do_execsql_test affinity2-120 {
SELECT xr, typeof(xr) FROM t1 ORDER BY rowid;
} {1.0 real 2.0 real 3.0 real}
do_execsql_test affinity2-130 {
SELECT xb, typeof(xb) FROM t1 ORDER BY rowid;
} {1 integer 2 text 03 text}
do_execsql_test affinity2-140 {
SELECT xn, typeof(xn) FROM t1 ORDER BY rowid;
} {1 integer 2 integer 3 integer}
do_execsql_test affinity2-150 {
SELECT xt, typeof(xt) FROM t1 ORDER BY rowid;
} {1 text 2 text 03 text}
do_execsql_test affinity2-200 {
SELECT rowid, xi==xt, xi==xb, xi==+xt FROM t1 ORDER BY rowid;
} {1 1 1 1 2 1 1 1 3 1 1 1}
do_execsql_test affinity2-210 {
SELECT rowid, xr==xt, xr==xb, xr==+xt FROM t1 ORDER BY rowid;
} {1 1 1 1 2 1 1 1 3 1 1 1}
do_execsql_test affinity2-220 {
SELECT rowid, xn==xt, xn==xb, xn==+xt FROM t1 ORDER BY rowid;
} {1 1 1 1 2 1 1 1 3 1 1 1}
do_execsql_test affinity2-300 {
SELECT rowid, xt==+xi, xt==xi, xt==xb FROM t1 ORDER BY rowid;
} {1 1 1 0 2 1 1 1 3 0 1 1}
finish_test
+5
View File
@@ -24,6 +24,11 @@ if {$tcl_platform(platform)=="windows"} {
} else {
set PROG "./sqlite3_analyzer"
}
if {![file exe $PROG]} {
puts "analyzer1 cannot run because $PROG is not available"
finish_test
return
}
db close
forcedelete test.db test.db-journal test.db-wal
sqlite3 db test.db
-1
View File
@@ -171,7 +171,6 @@ foreach {tn code} {
#
set ::busy_callback_count 0
proc busy_callback {args} {
puts Hello
incr ::busy_callback_count
return 0
}
+16
View File
@@ -0,0 +1,16 @@
#
# 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 runs most of the tests run by veryquick.test except for those
# that take a long time.
#
set testdir [file dirname $argv0]
source $testdir/permutations.test
run_test_suite extraquick
finish_test
-1
View File
@@ -39,7 +39,6 @@ do_test filectrl-1.5 {
do_test filectrl-1.6 {
sqlite3 db test.db
set fn [file_control_tempfilename db]
puts -nonewline \[$fn\]
set fn
} {/etilqs_/}
db close
+1 -1
View File
@@ -213,7 +213,7 @@ do_test fts3d-4.matches {
{0 1 0 4 0 2 5 3 0 3 9 1 0 5 11 4} \
{0 0 0 4 0 4 5 2 0 3 8 1 0 5 10 4}]
puts [db eval {SELECT c FROM t1 } ]
db eval {SELECT c FROM t1 }
check_terms_all fts3d-4.1 {a four is test that this was}
check_doclist_all fts3d-4.1.1 a {[1 0[2]] [2 0[2]] [3 0[2]]}
check_doclist_all fts3d-4.1.2 four {}
+3 -1
View File
@@ -47,7 +47,9 @@ foreach {tn q res} {
do_execsql_test 2.$tn.$s $q $res
set t($s) [lindex [time [list execsql $q] 100] 0]
}
puts "with optimization: $t(0) without: $t(1)"
if {0} {
puts "with optimization: $t(0) without: $t(1)"
}
}
do_test 2.1 {
+12 -2
View File
@@ -362,11 +362,17 @@ ifcapable icu { lappend tokenizers icu }
# Some tests to check that the tokenizers can both identify white-space
# codepoints. All codepoints tested below are of type "Zs" in the
# UnicodeData.txt file.
#
# Note that codepoint 6158 has changed from Zs to Cf in recent versions
# of UnicodeData.txt. So take that into account for the "icu" tests.
#
foreach T $tokenizers {
do_isspace_test 6.$T.1 $T 32
do_isspace_test 6.$T.2 $T 160
do_isspace_test 6.$T.3 $T 5760
do_isspace_test 6.$T.4 $T 6158
if {$T!="icu"} {
do_isspace_test 6.$T.4 $T 6158
}
do_isspace_test 6.$T.5 $T 8192
do_isspace_test 6.$T.6 $T 8193
do_isspace_test 6.$T.7 $T 8194
@@ -382,7 +388,11 @@ foreach T $tokenizers {
do_isspace_test 6.$T.17 $T 8287
do_isspace_test 6.$T.18 $T 12288
do_isspace_test 6.$T.19 $T {32 160 5760 6158}
if {$T!="icu"} {
do_isspace_test 6.$T.19 $T {32 160 5760 6158}
} else {
do_isspace_test 6.$T.19 $T {32 160 5760 8192}
}
do_isspace_test 6.$T.20 $T {8192 8193 8194 8195}
do_isspace_test 6.$T.21 $T {8196 8197 8198 8199}
do_isspace_test 6.$T.22 $T {8200 8201 8202 8239}
+36 -8
View File
@@ -10,8 +10,8 @@
**
*************************************************************************
**
** This is a utility program designed to aid running regressions tests
** on SQLite library using data from an external fuzzer, such as American
** This is a utility program designed to aid running regressions tests on
** the SQLite library using data from an external fuzzer, such as American
** Fuzzy Lop (AFL) (http://lcamtuf.coredump.cx/afl/).
**
** This program reads content from an SQLite database file with the following
@@ -25,16 +25,44 @@
** sqlid INTEGER PRIMARY KEY, -- SQL script id
** sqltext TEXT -- Text of SQL statements to run
** );
** CREATE TABLE IF NOT EXISTS readme(
** msg TEXT -- Human-readable description of this test collection
** );
**
** For each database file in the DB table, the SQL text in the XSQL table
** is run against that database. This program is looking for crashes,
** assertion faults, and/or memory leaks. No attempt is made to verify
** the output. The assumption is that either all of the database files
** or all of the SQL statements are malformed inputs, generated by a fuzzer,
** that need to be checked to make sure they do not present a security risk.
** is run against that database. All README.MSG values are printed prior
** to the start of the test (unless the --quiet option is used). If the
** DB table is empty, then all entries in XSQL are run against an empty
** in-memory database.
**
** This program is looking for crashes, assertion faults, and/or memory leaks.
** No attempt is made to verify the output. The assumption is that either all
** of the database files or all of the SQL statements are malformed inputs,
** generated by a fuzzer, that need to be checked to make sure they do not
** present a security risk.
**
** This program also includes some command-line options to help with
** creation and maintenance of the source content database.
** creation and maintenance of the source content database. The command
**
** ./fuzzcheck database.db --load-sql FILE...
**
** Loads all FILE... arguments into the XSQL table. The --load-db option
** works the same but loads the files into the DB table. The -m option can
** be used to initialize the README table. The "database.db" file is created
** if it does not previously exist. Example:
**
** ./fuzzcheck new.db --load-sql *.sql
** ./fuzzcheck new.db --load-db *.db
** ./fuzzcheck new.db -m 'New test cases'
**
** The three commands above will create the "new.db" file and initialize all
** tables. Then do "./fuzzcheck new.db" to run the tests.
**
** DEBUGGING HINTS:
**
** If fuzzcheck does crash, it can be run in the debugger and the content
** of the global variable g.zTextName[] will identify the specific XSQL and
** DB values that were running when the crash occurred.
*/
#include <stdio.h>
#include <stdlib.h>
BIN
View File
Binary file not shown.
+4 -2
View File
@@ -67,8 +67,10 @@ do_test 1.3 {
}
set iPrev $iNext
}
puts -nonewline \
" (forward=$nForward, back=$nBackward, noncontiguous=$nNoncont)"
if {0} {
puts -nonewline \
" (forward=$nForward, back=$nBackward, noncontiguous=$nNoncont)"
}
expr {$nForward > 2*($nBackward + $nNoncont)}
} {1}
+19
View File
@@ -327,4 +327,23 @@ do_execsql_test index6-8.2 {
3 three value 3
}
# 2015-06-11. Assertion fault found by AFL
#
do_execsql_test index6-9.1 {
CREATE TABLE t9(a int, b int, c int);
CREATE INDEX t9ca ON t9(c,a) WHERE a in (10,12,20);
INSERT INTO t9 VALUES(1,1,9),(10,2,35),(11,15,82),(20,19,5),(NULL,7,3);
UPDATE t9 SET b=c WHERE a in (10,12,20);
SELECT a,b,c,'|' FROM t9 ORDER BY a;
} {{} 7 3 | 1 1 9 | 10 35 35 | 11 15 82 | 20 5 5 |}
do_execsql_test index6-9.2 {
DROP TABLE t9;
CREATE TABLE t9(a int, b int, c int, PRIMARY KEY(a)) WITHOUT ROWID;
CREATE INDEX t9ca ON t9(c,a) WHERE a in (10,12,20);
INSERT INTO t9 VALUES(1,1,9),(10,2,35),(11,15,82),(20,19,5);
UPDATE t9 SET b=c WHERE a in (10,12,20);
SELECT a,b,c,'|' FROM t9 ORDER BY a;
} {1 1 9 | 10 35 35 | 11 15 82 | 20 5 5 |}
finish_test
+26
View File
@@ -687,4 +687,30 @@ ifcapable pragma&&compileoption_diags {
}
}
#-------------------------------------------------------------------------
# Test a problem with reordering tables following a LEFT JOIN.
#
do_execsql_test join-13.0 {
CREATE TABLE aa(a);
CREATE TABLE bb(b);
CREATE TABLE cc(c);
INSERT INTO aa VALUES(45);
INSERT INTO cc VALUES(45);
INSERT INTO cc VALUES(45);
}
do_execsql_test join-13.1 {
SELECT * FROM aa LEFT JOIN bb, cc WHERE cc.c=aa.a;
} {45 {} 45 45 {} 45}
# In the following, the order of [cc] and [bb] must not be exchanged, even
# though this would be helpful if the query used an inner join.
do_execsql_test join-13.2 {
CREATE INDEX ccc ON cc(c);
SELECT * FROM aa LEFT JOIN bb, cc WHERE cc.c=aa.a;
} {45 {} 45 45 {} 45}
finish_test
+14 -3
View File
@@ -96,7 +96,7 @@ if {$::tcl_platform(platform)!="unix"} {
set alltests [test_set $alltests -exclude {
all.test async.test quick.test veryquick.test
memleak.test permutations.test soak.test fts3.test
mallocAll.test rtree.test full.test
mallocAll.test rtree.test full.test extraquick.test
}]
set allquicktests [test_set $alltests -exclude {
@@ -146,11 +146,22 @@ if {[info exists ::env(TEST_FAILURE)]} {
lappend ::testsuitelist xxx
test_suite "veryquick" -prefix "" -description {
"Very" quick test suite. Runs in less than 5 minutes on a workstation.
"Very" quick test suite. Runs in minutes on a workstation.
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* *bigfile*
]
test_suite "extraquick" -prefix "" -description {
"Extra" quick test suite. Runs in a few minutes on a workstation.
This test suite is the same as the "veryquick" tests, except that
slower tests are omitted.
} -files [
test_set $allquicktests -exclude *malloc* *ioerr* *fault* *bigfile* \
wal3.test fts4merge* sort2.test mmap1.test walcrash* \
percentile.test where8m.test walcksum.test savepoint3.test \
fuzzer1.test fuzzer3.test fts3expr3.test
]
test_suite "mmap" -prefix "mm-" -description {
-1
View File
@@ -164,7 +164,6 @@ do_test progress-1.7 {
}
set ::res [list]
explain {SELECT a, b, c FROM abc}
db eval {SELECT a, b, c FROM abc} {
lappend ::res $a $b $c
db progress 5 "expr 1"
+5 -2
View File
@@ -547,7 +547,10 @@ proc process_options {argv} {
puts " --srcdir $::SRCDIR"
puts " --platform [list $platform]"
puts " --config [list $config]"
if {$::QUICK} {puts " --quick"}
if {$::QUICK} {
if {$::QUICK==1} {puts " --quick"}
if {$::QUICK==2} {puts " --veryquick"}
}
if {$::MSVC} {puts " --msvc"}
if {$::BUILDONLY} {puts " --buildonly"}
if {$::DRYRUN} {puts " --dryrun"}
@@ -645,7 +648,7 @@ proc main {argv} {
}
if {$target ne "checksymbols"} {
switch -- $::QUICK {
1 {set target test}
1 {set target quicktest}
2 {set target smoketest}
}
if {$::BUILDONLY} {
-1
View File
@@ -32,7 +32,6 @@ set result [execsql {
FROM songs
GROUP BY LOWER(artist)
}]
puts result=$result
do_test select8-1.1 {
execsql {
SELECT DISTINCT artist,sum(timesplayed) AS total
-1
View File
@@ -16,7 +16,6 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
db close
puts hello
# This script is only valid if we are running shared-cache mode in a
# threadsafe-capable database engine.
+5
View File
@@ -19,6 +19,11 @@ if {$tcl_platform(platform)=="windows"} {
} else {
set PROG "./sqldiff"
}
if {![file exe $PROG]} {
puts "sqldiff cannot run because $PROG is not available"
finish_test
return
}
db close
forcedelete test.db test2.db
sqlite3 db test.db
+16
View File
@@ -808,4 +808,20 @@ do_execsql_test table-17.1 {
SELECT p, q, '|' FROM t3 ORDER BY p;
} {1 1 | 2 2 |}
# 2015-06-16
# Ticket [https://www.sqlite.org/src/tktview/873cae2b6e25b1991ce5e9b782f9cd0409b96063]
# Make sure a CREATE TABLE AS statement correctly rolls back partial changes to the
# sqlite_master table when the SELECT on the right-hand side aborts.
#
do_catchsql_test table-18.1 {
DROP TABLE IF EXISTS t1;
BEGIN;
CREATE TABLE t1 AS SELECT zeroblob(2e20);
} {1 {string or blob too big}}
do_execsql_test table-18.2 {
COMMIT;
PRAGMA integrity_check;
} {ok}
finish_test
+160 -60
View File
@@ -81,6 +81,12 @@
# permutation
# presql
#
# Command to test whether or not --verbose=1 was specified on the command
# line (returns 0 for not-verbose, 1 for verbose and 2 for "verbose in the
# output file only").
#
# verbose
#
# Set the precision of FP arithmatic used by the interpreter. And
# configure SQLite to take database file locks on the page that begins
@@ -388,6 +394,9 @@ if {[info exists cmdlinearg]==0} {
# --file-retry-delay=N
# --start=[$permutation:]$testfile
# --match=$pattern
# --verbose=$val
# --output=$filename
# --help
#
set cmdlinearg(soft-heap-limit) 0
set cmdlinearg(maxerror) 1000
@@ -399,6 +408,8 @@ if {[info exists cmdlinearg]==0} {
set cmdlinearg(file-retry-delay) 0
set cmdlinearg(start) ""
set cmdlinearg(match) ""
set cmdlinearg(verbose) ""
set cmdlinearg(output) ""
set leftover [list]
foreach a $argv {
@@ -457,6 +468,22 @@ if {[info exists cmdlinearg]==0} {
set ::G(match) $cmdlinearg(match)
if {$::G(match) == ""} {unset ::G(match)}
}
{^-+output=.+$} {
foreach {dummy cmdlinearg(output)} [split $a =] break
if {$cmdlinearg(verbose)==""} {
set cmdlinearg(verbose) 2
}
}
{^-+verbose=.+$} {
foreach {dummy cmdlinearg(verbose)} [split $a =] break
if {$cmdlinearg(verbose)=="file"} {
set cmdlinearg(verbose) 2
} elseif {[string is boolean -strict $cmdlinearg(verbose)]==0} {
error "option --verbose= must be set to a boolean or to \"file\""
}
}
default {
lappend leftover $a
}
@@ -484,6 +511,16 @@ if {[info exists cmdlinearg]==0} {
if {$cmdlinearg(malloctrace)} {
sqlite3_memdebug_backtrace $cmdlinearg(backtrace)
}
if {$cmdlinearg(output)!=""} {
puts "Copying output to file $cmdlinearg(output)"
set ::G(output_fd) [open $cmdlinearg(output) w]
fconfigure $::G(output_fd) -buffering line
}
if {$cmdlinearg(verbose)==""} {
set cmdlinearg(verbose) 1
}
}
# Update the soft-heap-limit each time this script is run. In that
@@ -554,7 +591,7 @@ proc fail_test {name} {
set nFail [set_test_counter errors]
if {$nFail>=$::cmdlinearg(maxerror)} {
puts "*** Giving up..."
output2 "*** Giving up..."
finalize_testing
}
}
@@ -562,7 +599,7 @@ proc fail_test {name} {
# Remember a warning message to be displayed at the conclusion of all testing
#
proc warning {msg {append 1}} {
puts "Warning: $msg"
output2 "Warning: $msg"
set warnList [set_test_counter warn_list]
if {$append} {
lappend warnList $msg
@@ -577,6 +614,61 @@ proc incr_ntest {} {
set_test_counter count [expr [set_test_counter count] + 1]
}
# Return true if --verbose=1 was specified on the command line. Otherwise,
# return false.
#
proc verbose {} {
return $::cmdlinearg(verbose)
}
# Use the following commands instead of [puts] for test output within
# this file. Test scripts can still use regular [puts], which is directed
# to stdout and, if one is open, the --output file.
#
# output1: output that should be printed if --verbose=1 was specified.
# output2: output that should be printed unconditionally.
# output2_if_no_verbose: output that should be printed only if --verbose=0.
#
proc output1 {args} {
set v [verbose]
if {$v==1} {
uplevel output2 $args
} elseif {$v==2} {
uplevel puts [lrange $args 0 end-1] $::G(output_fd) [lrange $args end end]
}
}
proc output2 {args} {
set nArg [llength $args]
uplevel puts $args
}
proc output2_if_no_verbose {args} {
set v [verbose]
if {$v==0} {
uplevel output2 $args
} elseif {$v==2} {
uplevel puts [lrange $args 0 end-1] stdout [lrange $args end end]
}
}
# Override the [puts] command so that if no channel is explicitly
# specified the string is written to both stdout and to the file
# specified by "--output=", if any.
#
proc puts_override {args} {
set nArg [llength $args]
if {$nArg==1 || ($nArg==2 && [string first [lindex $args 0] -nonewline]==0)} {
uplevel puts_original $args
if {[info exists ::G(output_fd)]} {
uplevel puts [lrange $args 0 end-1] $::G(output_fd) [lrange $args end end]
}
} else {
# A channel was explicitly specified.
uplevel puts_original $args
}
}
rename puts puts_original
proc puts {args} { uplevel puts_override $args }
# Invoke the do_test procedure to run a single test
#
@@ -604,12 +696,13 @@ proc do_test {name cmd expected} {
}
incr_ntest
puts -nonewline $name...
output1 -nonewline $name...
flush stdout
if {![info exists ::G(match)] || [string match $::G(match) $name]} {
if {[catch {uplevel #0 "$cmd;\n"} result]} {
puts "\nError: $result"
output2_if_no_verbose -nonewline $name...
output2 "\nError: $result"
fail_test $name
} else {
if {[regexp {^~?/.*/$} $expected]} {
@@ -653,14 +746,15 @@ proc do_test {name cmd expected} {
# if {![info exists ::testprefix] || $::testprefix eq ""} {
# error "no test prefix"
# }
puts "\nExpected: \[$expected\]\n Got: \[$result\]"
output2_if_no_verbose -nonewline $name...
output2 "\nExpected: \[$expected\]\n Got: \[$result\]"
fail_test $name
} else {
puts " Ok"
output1 " Ok"
}
}
} else {
puts " Omitted"
output1 " Omitted"
omit_test $name "pattern mismatch" 0
}
flush stdout
@@ -837,7 +931,7 @@ proc delete_all_data {} {
# Return the number of microseconds per statement.
#
proc speed_trial {name numstmt units sql} {
puts -nonewline [format {%-21.21s } $name...]
output2 -nonewline [format {%-21.21s } $name...]
flush stdout
set speed [time {sqlite3_exec_nr db $sql}]
set tm [lindex $speed 0]
@@ -847,13 +941,13 @@ proc speed_trial {name numstmt units sql} {
set rate [format %20.5f [expr {1000000.0*$numstmt/$tm}]]
}
set u2 $units/s
puts [format {%12d uS %s %s} $tm $rate $u2]
output2 [format {%12d uS %s %s} $tm $rate $u2]
global total_time
set total_time [expr {$total_time+$tm}]
lappend ::speed_trial_times $name $tm
}
proc speed_trial_tcl {name numstmt units script} {
puts -nonewline [format {%-21.21s } $name...]
output2 -nonewline [format {%-21.21s } $name...]
flush stdout
set speed [time {eval $script}]
set tm [lindex $speed 0]
@@ -863,7 +957,7 @@ proc speed_trial_tcl {name numstmt units script} {
set rate [format %20.5f [expr {1000000.0*$numstmt/$tm}]]
}
set u2 $units/s
puts [format {%12d uS %s %s} $tm $rate $u2]
output2 [format {%12d uS %s %s} $tm $rate $u2]
global total_time
set total_time [expr {$total_time+$tm}]
lappend ::speed_trial_times $name $tm
@@ -875,19 +969,19 @@ proc speed_trial_init {name} {
sqlite3 versdb :memory:
set vers [versdb one {SELECT sqlite_source_id()}]
versdb close
puts "SQLite $vers"
output2 "SQLite $vers"
}
proc speed_trial_summary {name} {
global total_time
puts [format {%-21.21s %12d uS TOTAL} $name $total_time]
output2 [format {%-21.21s %12d uS TOTAL} $name $total_time]
if { 0 } {
sqlite3 versdb :memory:
set vers [lindex [versdb one {SELECT sqlite_source_id()}] 0]
versdb close
puts "CREATE TABLE IF NOT EXISTS time(version, script, test, us);"
output2 "CREATE TABLE IF NOT EXISTS time(version, script, test, us);"
foreach {test us} $::speed_trial_times {
puts "INSERT INTO time VALUES('$vers', '$name', '$test', $us);"
output2 "INSERT INTO time VALUES('$vers', '$name', '$test', $us);"
}
}
}
@@ -931,75 +1025,75 @@ proc finalize_testing {} {
}
}
if {$nKnown>0} {
puts "[expr {$nErr-$nKnown}] new errors and $nKnown known errors\
output2 "[expr {$nErr-$nKnown}] new errors and $nKnown known errors\
out of $nTest tests"
} else {
puts "$nErr errors out of $nTest tests"
output2 "$nErr errors out of $nTest tests"
}
if {$nErr>$nKnown} {
puts -nonewline "Failures on these tests:"
output2 -nonewline "Failures on these tests:"
foreach x [set_test_counter fail_list] {
if {![info exists known_error($x)]} {puts -nonewline " $x"}
if {![info exists known_error($x)]} {output2 -nonewline " $x"}
}
puts ""
output2 ""
}
foreach warning [set_test_counter warn_list] {
puts "Warning: $warning"
output2 "Warning: $warning"
}
run_thread_tests 1
if {[llength $omitList]>0} {
puts "Omitted test cases:"
output2 "Omitted test cases:"
set prec {}
foreach {rec} [lsort $omitList] {
if {$rec==$prec} continue
set prec $rec
puts [format { %-12s %s} [lindex $rec 0] [lindex $rec 1]]
output2 [format { %-12s %s} [lindex $rec 0] [lindex $rec 1]]
}
}
if {$nErr>0 && ![working_64bit_int]} {
puts "******************************************************************"
puts "N.B.: The version of TCL that you used to build this test harness"
puts "is defective in that it does not support 64-bit integers. Some or"
puts "all of the test failures above might be a result from this defect"
puts "in your TCL build."
puts "******************************************************************"
output2 "******************************************************************"
output2 "N.B.: The version of TCL that you used to build this test harness"
output2 "is defective in that it does not support 64-bit integers. Some or"
output2 "all of the test failures above might be a result from this defect"
output2 "in your TCL build."
output2 "******************************************************************"
}
if {$::cmdlinearg(binarylog)} {
vfslog finalize binarylog
}
if {$sqlite_open_file_count} {
puts "$sqlite_open_file_count files were left open"
output2 "$sqlite_open_file_count files were left open"
incr nErr
}
if {[lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1]>0 ||
[sqlite3_memory_used]>0} {
puts "Unfreed memory: [sqlite3_memory_used] bytes in\
output2 "Unfreed memory: [sqlite3_memory_used] bytes in\
[lindex [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0] 1] allocations"
incr nErr
ifcapable memdebug||mem5||(mem3&&debug) {
puts "Writing unfreed memory log to \"./memleak.txt\""
output2 "Writing unfreed memory log to \"./memleak.txt\""
sqlite3_memdebug_dump ./memleak.txt
}
} else {
puts "All memory allocations freed - no leaks"
output2 "All memory allocations freed - no leaks"
ifcapable memdebug||mem5 {
sqlite3_memdebug_dump ./memusage.txt
}
}
show_memstats
puts "Maximum memory usage: [sqlite3_memory_highwater 1] bytes"
puts "Current memory usage: [sqlite3_memory_highwater] bytes"
output2 "Maximum memory usage: [sqlite3_memory_highwater 1] bytes"
output2 "Current memory usage: [sqlite3_memory_highwater] bytes"
if {[info commands sqlite3_memdebug_malloc_count] ne ""} {
puts "Number of malloc() : [sqlite3_memdebug_malloc_count] calls"
output2 "Number of malloc() : [sqlite3_memdebug_malloc_count] calls"
}
if {$::cmdlinearg(malloctrace)} {
puts "Writing mallocs.sql..."
output2 "Writing mallocs.sql..."
memdebug_log_sql
sqlite3_memdebug_log stop
sqlite3_memdebug_log clear
if {[sqlite3_memory_used]>0} {
puts "Writing leaks.sql..."
output2 "Writing leaks.sql..."
sqlite3_memdebug_log sync
memdebug_log_sql leaks.sql
}
@@ -1020,30 +1114,30 @@ proc show_memstats {} {
set y [sqlite3_status SQLITE_STATUS_MALLOC_SIZE 0]
set val [format {now %10d max %10d max-size %10d} \
[lindex $x 1] [lindex $x 2] [lindex $y 2]]
puts "Memory used: $val"
output1 "Memory used: $val"
set x [sqlite3_status SQLITE_STATUS_MALLOC_COUNT 0]
set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]]
puts "Allocation count: $val"
output1 "Allocation count: $val"
set x [sqlite3_status SQLITE_STATUS_PAGECACHE_USED 0]
set y [sqlite3_status SQLITE_STATUS_PAGECACHE_SIZE 0]
set val [format {now %10d max %10d max-size %10d} \
[lindex $x 1] [lindex $x 2] [lindex $y 2]]
puts "Page-cache used: $val"
output1 "Page-cache used: $val"
set x [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0]
set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]]
puts "Page-cache overflow: $val"
output1 "Page-cache overflow: $val"
set x [sqlite3_status SQLITE_STATUS_SCRATCH_USED 0]
set val [format {now %10d max %10d} [lindex $x 1] [lindex $x 2]]
puts "Scratch memory used: $val"
output1 "Scratch memory used: $val"
set x [sqlite3_status SQLITE_STATUS_SCRATCH_OVERFLOW 0]
set y [sqlite3_status SQLITE_STATUS_SCRATCH_SIZE 0]
set val [format {now %10d max %10d max-size %10d} \
[lindex $x 1] [lindex $x 2] [lindex $y 2]]
puts "Scratch overflow: $val"
output1 "Scratch overflow: $val"
ifcapable yytrackmaxstackdepth {
set x [sqlite3_status SQLITE_STATUS_PARSER_STACK 0]
set val [format { max %10d} [lindex $x 2]]
puts "Parser stack depth: $val"
output2 "Parser stack depth: $val"
}
}
@@ -1058,7 +1152,7 @@ proc execsql_timed {sql {db db}} {
set x [uplevel [list $db eval $sql]]
} 1]
set tm [lindex $tm 0]
puts -nonewline " ([expr {$tm*0.001}]ms) "
output1 -nonewline " ([expr {$tm*0.001}]ms) "
set x
}
@@ -1074,20 +1168,20 @@ proc catchsql {sql {db db}} {
# Do an VDBE code dump on the SQL given
#
proc explain {sql {db db}} {
puts ""
puts "addr opcode p1 p2 p3 p4 p5 #"
puts "---- ------------ ------ ------ ------ --------------- -- -"
output2 ""
output2 "addr opcode p1 p2 p3 p4 p5 #"
output2 "---- ------------ ------ ------ ------ --------------- -- -"
$db eval "explain $sql" {} {
puts [format {%-4d %-12.12s %-6d %-6d %-6d % -17s %s %s} \
output2 [format {%-4d %-12.12s %-6d %-6d %-6d % -17s %s %s} \
$addr $opcode $p1 $p2 $p3 $p4 $p5 $comment
]
}
}
proc explain_i {sql {db db}} {
puts ""
puts "addr opcode p1 p2 p3 p4 p5 #"
puts "---- ------------ ------ ------ ------ ---------------- -- -"
output2 ""
output2 "addr opcode p1 p2 p3 p4 p5 #"
output2 "---- ------------ ------ ------ ------ ---------------- -- -"
# Set up colors for the different opcodes. Scheme is as follows:
@@ -1153,18 +1247,18 @@ proc explain_i {sql {db db}} {
$db eval "explain $sql" {} {
if {[info exists linebreak($addr)]} {
puts ""
output2 ""
}
set I [string repeat " " $x($addr)]
set col ""
catch { set col $color($opcode) }
puts [format {%-4d %s%s%-12.12s%s %-6d %-6d %-6d % -17s %s %s} \
output2 [format {%-4d %s%s%-12.12s%s %-6d %-6d %-6d % -17s %s %s} \
$addr $I $col $opcode $D $p1 $p2 $p3 $p4 $p5 $comment
]
}
puts "---- ------------ ------ ------ ------ ---------------- -- -"
output2 "---- ------------ ------ ------ ------ ---------------- -- -"
}
# Show the VDBE program for an SQL statement but omit the Trace
@@ -1595,9 +1689,9 @@ proc do_ioerr_test {testname args} {
set nowcksum [cksum]
set res [expr {$nowcksum==$::checksum || $nowcksum==$::goodcksum}]
if {$res==0} {
puts "now=$nowcksum"
puts "the=$::checksum"
puts "fwd=$::goodcksum"
output2 "now=$nowcksum"
output2 "the=$::checksum"
output2 "fwd=$::goodcksum"
}
set res
} 1
@@ -1821,6 +1915,12 @@ proc slave_test_script {script} {
interp eval tinterp [list set $var $value]
}
# If output is being copied into a file, share the file-descriptor with
# the interpreter.
if {[info exists ::G(output_fd)]} {
interp share {} $::G(output_fd) tinterp
}
# The alias used to access the global test counters.
tinterp alias set_test_counter set_test_counter
@@ -1889,7 +1989,7 @@ proc slave_test_file {zFile} {
# Add some info to the output.
#
puts "Time: $tail $ms ms"
output2 "Time: $tail $ms ms"
show_memstats
}
-3
View File
@@ -56,9 +56,6 @@ ifcapable !vtab||!schema_pragmas {
# We cannot create a virtual table if the module has not been registered.
#
do_test vtab1-1.1.1 {
explain {
CREATE VIRTUAL TABLE t1 USING echo;
}
catchsql {
CREATE VIRTUAL TABLE t1 USING echo;
}
+3
View File
@@ -289,6 +289,7 @@ foreach file {
mutex_w32.c
malloc.c
printf.c
treeview.c
random.c
threads.c
utf.c
@@ -343,6 +344,8 @@ foreach file {
update.c
vacuum.c
vtab.c
wherecode.c
whereexpr.c
where.c
parse.c
+22
View File
@@ -9,6 +9,28 @@ echo '********** No optimizations. Includes FTS4 and RTREE *********'
gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
-ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
sqlite3.c
echo '********** Android configuration ******************************'
gcc -c \
-DHAVE_USLEEP=1 \
-DSQLITE_HAVE_ISNAN \
-DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576 \
-DSQLITE_THREADSAFE=2 \
-DSQLITE_TEMP_STORE=3 \
-DSQLITE_POWERSAFE_OVERWRITE=1 \
-DSQLITE_DEFAULT_FILE_FORMAT=4 \
-DSQLITE_DEFAULT_AUTOVACUUM=1 \
-DSQLITE_ENABLE_MEMORY_MANAGEMENT=1 \
-DSQLITE_ENABLE_FTS3 \
-DSQLITE_ENABLE_FTS3_BACKWARDS \
-DSQLITE_ENABLE_FTS4 \
-DSQLITE_OMIT_BUILTIN_TEST \
-DSQLITE_OMIT_COMPILEOPTION_DIAGS \
-DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_DEFAULT_FILE_PERMISSIONS=0600 \
-DSQLITE_ENABLE_ICU \
-DUSE_PREAD64 \
-Wshadow -Wall -Wextra \
-Os sqlite3.c shell.c
echo '********** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******'
gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
-ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \