Compare commits

..

43 Commits

Author SHA1 Message Date
dan 95b54f8816 Various fixes and test case updates so that veryquick.test passes again.
FossilOrigin-Name: f352ef57e39a9443b4bdf47fc2c9b01006fe3c10
2014-02-12 15:05:05 +00:00
dan a52cbdb416 Merge latest trunk changes.
FossilOrigin-Name: 4d7057c4942464b4302031a1ee9f195700c5e66d
2014-02-12 14:43:01 +00:00
dan e5c544e0ab Test case updates to account for the fact that database files are not created until they are first written.
FossilOrigin-Name: 8ef97420b2614f50de6e6d7c758483b8b888f325
2014-02-11 19:35:42 +00:00
drh c5185cd845 Increase the version number to 3.8.4
FossilOrigin-Name: 0a8bcbbd4e11a60923736b2be9b1ce83ea2263fb
2014-02-11 16:24:34 +00:00
drh 39a3088dc4 Updates to the command-line shell. Simplify the banner message. Add the
".save" command as an alias for ".backup".  When starting with no arguments,
include a banner message warning that the database is transient and in-memory
and mention the ".open" command.

FossilOrigin-Name: f5ad1e1bf2828c5da70c1ff944d8212036142e6f
2014-02-11 16:22:18 +00:00
drh aaa21b41e8 Fixes to the "editline" support in the command-line shell.
FossilOrigin-Name: 7989ce5f105657060a39be295255da8eff9ed56e
2014-02-11 14:37:51 +00:00
dan 3612639a6f Merge latest trunk changes.
FossilOrigin-Name: 1f2e1b0c64934ec80f09d596d512f7c320e36f81
2014-02-11 05:26:22 +00:00
drh 7c3280649a Make sure that virtual WHERE-clause terms do not get transformed into real
terms when processing set of OR-connected terms.
Fix for ticket [4c86b126f22ad].

FossilOrigin-Name: c950d6c4117d076f871518e738cdf9e8c46a19fc
2014-02-11 01:50:29 +00:00
dan 35b85b4855 Fix a bug causing the POWERSAFE_OVERWRITE device-characteristic flag to be set incorrectly if file opening is deferred.
FossilOrigin-Name: 95d0c58d2791d81b432e7d263f3fc2f26858d395
2014-02-10 21:09:39 +00:00
drh a6e3a8c9d5 Fix a pointless conditional. Add a test case.
FossilOrigin-Name: 9367632dd7e4fec9197227e35b0627c2e81ebffc
2014-02-10 21:07:51 +00:00
drh 5c7976fe86 Add the ".save" command as an alias for ".backup". Improvements to the
way font changes are implemented on the in-memory database warning.

FossilOrigin-Name: fe284afe739c497e153ac2bc0275f7c9e862c824
2014-02-10 19:59:27 +00:00
dan c913126272 Experimental change to os_unix.c to delay creating a database file until it is first written.
FossilOrigin-Name: 538f7b25e436682adba10a158f082de24782cf00
2014-02-10 19:37:03 +00:00
drh ba47ba76a5 On unix, make the "transient in-memory database" text bold, but not red.
Leave the text read on windows.

FossilOrigin-Name: c9eba2f7be468ae7fc843ffd5b09bd062ee311c3
2014-02-10 19:36:06 +00:00
drh 1247aa4e4a In the command-line shell, on the banner, warn about the use of a
transient in-memory database in bold red text.

FossilOrigin-Name: 0fbc0fcec1b3a67065fa0ebb49375bf675789edc
2014-02-10 19:27:05 +00:00
drh 8af9ad951d Fix the compound-select-to-subquery converter so that it works with the
new compound-select object linkage introduced as part of the fix
for ticket [31a19d11b97088296].

FossilOrigin-Name: 572d4be4db03ce4afe9ae70f148703c74e0d8de0
2014-02-10 18:56:05 +00:00
drh b373591c5e Modify the command-line shell to print a warning when using an in-memory
database.

FossilOrigin-Name: 90e9deae4a2bf63308a212226314aa7838c161d9
2014-02-10 16:13:42 +00:00
drh 60830e3c53 Improvements to a "Synopsis:" comment in the VDBE engine.
FossilOrigin-Name: 0dfa7ee9157ea6b1c745732d6c3fcd066cf4f849
2014-02-10 15:56:34 +00:00
drh 53a6eb3f3c Faster implementation for sqlite3MulInt64().
FossilOrigin-Name: 010c48f671e909cb406f3716102a0032bc72a592
2014-02-10 12:59:15 +00:00
drh 1b27b8c0a0 Faster and smaller implementation of sqlite3_value_type().
FossilOrigin-Name: 5708bc24b8cab623b833121183042b43e5a7021b
2014-02-10 03:21:57 +00:00
drh 5574e3f456 Add a compound-query test to the speedtest1 test program.
FossilOrigin-Name: 532995759114ab7a7cba18cc9d8820d78eb1a96e
2014-02-09 23:59:28 +00:00
drh d227a291b2 Use the WITH clause to help resolve names for SELECT statements on the left
of a compound query.  Proposed fix for ticket [31a19d11b97088296a].

FossilOrigin-Name: 67bfd59d9087a987f15f6148efa1ff104983e1fb
2014-02-09 18:02:09 +00:00
drh fa46bfbbc5 Add the Mandelbrot Set testcase to the "cte" testset of speedtest1.
FossilOrigin-Name: 56febbeb575a298ae8839b3a59711150ceb9999d
2014-02-09 00:52:53 +00:00
drh c47548057d Add a new "testset" to the speedtest1 program: The sudoku solver.
FossilOrigin-Name: 4677ef2f8a726573c48ee2e532c00a68308dd7e1
2014-02-09 00:18:21 +00:00
drh 5f61229504 Do away with the "multi-register pseudo-table" abstration. Instead, just
use an OP_SCopy to load results directory from the result registers of
the co-routine.

FossilOrigin-Name: 1e64dd782a126f48d78c43a664844a41d0e6334e
2014-02-08 23:20:32 +00:00
drh 826af37865 Change the OP_Found opcode so that it expands zero-blobs prior to comparing
them.  Fix for ticket [fccbde530a6583b]

FossilOrigin-Name: e2303d1b0c17b6e7494fb7db8264f4c2ac193723
2014-02-08 19:12:21 +00:00
drh c0740cebeb Fix a harmless compiler warning in VS2013.
FossilOrigin-Name: 83116ee3e0f2b9110c70a4f73a9badc9c2a56f28
2014-02-08 13:24:04 +00:00
drh 04d0bcd533 Fix a harmless compiler warning in VS2013.
FossilOrigin-Name: 35f2793db5eb58484554477a23f8320843ebcd71
2014-02-08 13:22:36 +00:00
drh 725de29a2d Tweaks to the generated VDBE code to make it a little easier to follow.
FossilOrigin-Name: 129217ee91782ec77ff82661753ae5bee8ca99d0
2014-02-08 13:12:19 +00:00
drh e0e261a473 Enable constant expression factoring even if no tables are read and no
transaction is started.

FossilOrigin-Name: a45b87713c0afca2be2ace9500513620a024c0a2
2014-02-08 04:24:37 +00:00
drh aceb31b120 Change the OP_Trace opcode to OP_Init and give it the ability to jump to the
initialization code at the bottom of the program, thus avoiding the need for
an extra OP_Goto.

FossilOrigin-Name: 192dea97316144f15f6dd0eabff08a0bf9ef203e
2014-02-08 01:40:27 +00:00
drh 642364a48b Add opcodes OP_InitCoroutine and OP_EndCoroutine. Use these to remove the
need for separate boolean registers to record when a co-routine has finished.

FossilOrigin-Name: 5a88b6a7aef3a0d5380e19eee2ee38439cc9b08b
2014-02-07 22:21:07 +00:00
drh dddf6978d2 Fix redundant definitions of _LARGE_FILE and _LARGEFILE_SOURCE.
FossilOrigin-Name: 4043d879795bfad55af35e9cb48e0a42eb4087ae
2014-02-07 19:33:31 +00:00
drh a198f2b55d In the TCL bindings, make sure Tcl_AppendResult() is always terminated
by "(char*)0" and not just "0".

FossilOrigin-Name: ea4d23d1c0df4fde2e532daa081888712f465884
2014-02-07 19:26:13 +00:00
drh ed71a839fd Change the OP_InitCoroutine instruction to jump over the co-routine
implementation.

FossilOrigin-Name: a522f364a6b8ca6f69c353b30609a2166f6e94cf
2014-02-07 19:18:10 +00:00
drh 81cf13ec7b Get rid of the OP_Undef and OP_IsUndef opcodes in favor of higher-level
OP_InitCoroutine and OP_EndCoroutine.

FossilOrigin-Name: 1ec0e9dd4b26d9f597adc8e062317d4866c5a6a6
2014-02-07 18:27:53 +00:00
drh a5750cfe01 Add the OP_Undef and OP_IsUndef opcodes. With these, use the first register
in the result register range as the flag to indicate EOF on an INSERT from
a SELECT, rather than allocating a separate boolean register for that task.

FossilOrigin-Name: 6fb7448550f28a3c93053e125faeaf11de1011d0
2014-02-07 13:20:31 +00:00
mistachkin 21a919f630 More comment updates. No changes to code.
FossilOrigin-Name: be24fbc22106e508975e316abe0471edd3833291
2014-02-07 03:28:02 +00:00
drh 0fd613542c Update comments in vdbe.c. No changes to code.
FossilOrigin-Name: 1122b410de68a3c79b4c719a3a4cc4dc6a5bb39d
2014-02-07 02:29:45 +00:00
drh b22f7c831f Delete the OP_VerifySchema opcode. Enhance OP_Transaction to do the schema
version checks that OP_VerifySchema used to do.

FossilOrigin-Name: 2f3376ebf13df44e6acf27cb1f07172cd8b34033
2014-02-06 23:56:27 +00:00
drh 0211d8bca4 Change the spellfix1 virtual table to deterministically names its shadow
tables.

FossilOrigin-Name: 5219cdfc56ec3e1cd645ae6443ba72ce0df0339a
2014-02-06 13:18:51 +00:00
drh 4bbcf10617 Add additional error messages and a progress spinner to the ".clone" command.
FossilOrigin-Name: dd0db3f0cef1be46cea16d4e61ea3348b3b3bd3e
2014-02-06 02:46:08 +00:00
mistachkin e31ae90100 Rename the '.repair' shell command to '.clone'.
FossilOrigin-Name: 4f9d95624ae4e123f83c835b5940f64d4a47be0d
2014-02-06 01:15:29 +00:00
drh 3350ce95f7 Add the ".repair" command to the command-line shell.
FossilOrigin-Name: d1dfadea87ecf18eeb6d2f21769deaa97473ca0e
2014-02-06 00:49:12 +00:00
54 changed files with 1591 additions and 1053 deletions
+1 -1
View File
@@ -1 +1 @@
3.8.3
3.8.4
Vendored
+9 -9
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.62 for sqlite 3.8.3.
# Generated by GNU Autoconf 2.62 for sqlite 3.8.4.
#
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
@@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.8.3'
PACKAGE_STRING='sqlite 3.8.3'
PACKAGE_VERSION='3.8.4'
PACKAGE_STRING='sqlite 3.8.4'
PACKAGE_BUGREPORT=''
# Factoring default headers for most tests.
@@ -1483,7 +1483,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.8.3 to adapt to many kinds of systems.
\`configure' configures sqlite 3.8.4 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1548,7 +1548,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.8.3:";;
short | recursive ) echo "Configuration of sqlite 3.8.4:";;
esac
cat <<\_ACEOF
@@ -1664,7 +1664,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.8.3
sqlite configure 3.8.4
generated by GNU Autoconf 2.62
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1678,7 +1678,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.8.3, which was
It was created by sqlite $as_me 3.8.4, which was
generated by GNU Autoconf 2.62. Invocation command line was
$ $0 $@
@@ -14021,7 +14021,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.8.3, which was
This file was extended by sqlite $as_me 3.8.4, which was
generated by GNU Autoconf 2.62. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -14074,7 +14074,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_version="\\
sqlite config.status 3.8.3
sqlite config.status 3.8.4
configured by $0, generated by GNU Autoconf 2.62,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+2 -4
View File
@@ -1933,7 +1933,6 @@ static int spellfix1Init(
#define SPELLFIX_COL_COMMAND 11
}
if( rc==SQLITE_OK && isCreate ){
sqlite3_uint64 r;
spellfix1DbExec(&rc, db,
"CREATE TABLE IF NOT EXISTS \"%w\".\"%w_vocab\"(\n"
" id INTEGER PRIMARY KEY,\n"
@@ -1945,11 +1944,10 @@ static int spellfix1Init(
");\n",
zDbName, zTableName
);
sqlite3_randomness(sizeof(r), &r);
spellfix1DbExec(&rc, db,
"CREATE INDEX IF NOT EXISTS \"%w\".\"%w_index_%llx\" "
"CREATE INDEX IF NOT EXISTS \"%w\".\"%w_vocab_index_langid_k2\" "
"ON \"%w_vocab\"(langid,k2);",
zDbName, zModule, r, zTableName
zDbName, zModule, zTableName
);
}
for(i=3; rc==SQLITE_OK && i<argc; i++){
+58 -57
View File
@@ -1,12 +1,12 @@
C Change\smore\sOP_OpenEphemeral\soperations\sto\sOP_OpenHash.
D 2014-02-06T14:59:47.807
C Various\sfixes\sand\stest\scase\supdates\sso\sthat\sveryquick.test\spasses\sagain.
D 2014-02-12T15:05:05.674
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc 6ff3ff2eef45c7dd309a8626ff7947b20bd387e7
F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
F VERSION 8ed548d87d0a27fd7d7620476f9e25f9fa742d73
F VERSION 0dc30ad5cf90736d5fd9e540c9f05c542658abe7
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F addopcodes.awk 9eb448a552d5c0185cf62c463f9c173cedae3811
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
@@ -38,7 +38,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 0921066a13130082764ab4ab6456f7b5bebe56de
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure 1673bc402f8fc95015f72c279adc5a9a668ee237 x
F configure e12e1a4f031354f9af735bcb377941a72dc2cca5 x
F configure.ac 4cf9f60785143fa141b10962ccc885d973792e9a
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html 334dbf6621b8fb8790297ec1abf3cfa4621709d1
@@ -114,7 +114,7 @@ F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/spellfix.c adfc569fafef7a1eb8f21528e5277686b358c3ce
F ext/misc/spellfix.c 3548c433f473c2054e080b6382771636fcaa2c4c
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
@@ -159,23 +159,23 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
F src/alter.c d5348d0f86a5fc8fb3987727402f023953c021cf
F src/analyze.c 581d5c18ce89c6f45d4dca65914d0de5b4dad41f
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c ae408b77caf025df8c1baab52aad8a5a393bed35
F src/btree.h f1c65e0511d7a228fd1a7c7463ef842525364348
F src/btree.c 7b2c3cd16deedff7f4904f2e871e7b77328b9872
F src/btree.h a61ddebc78c66795a2b93181321a116746302cc9
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
F src/build.c 7e6c275ab1731510d6f793d0f88373ab3e858e69
F src/build.c 13b9d82181d95af7b00ec8a8e1304bac096432d4
F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c 3987ac3e32f6a447b1f3ca0268d67bdaf0a8b97f
F src/expr.c fa9cd9b4bdc8989efce99d49c7e46484e17f41f4
F src/delete.c 6765a421f08adbedc5d52d21760ec6dbe5123fd3
F src/expr.c 9bea427f95665c1aa8fdc87b7678546eef50c296
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5
F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5
@@ -183,7 +183,7 @@ F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c c6b4ba486e62d0b600632fdfce4bca76213158cb
F src/insert.c 89526b031cf8f0e2306f02099a73cee56110c580
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
@@ -205,11 +205,11 @@ F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace
F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_unix.c f3ed0e406cbf9c820565b2118232d0796346130f
F src/os_unix.c c53e2683d8cc23d08f28dbecf0e3c2bcf1d1acca
F src/os_win.c d4284f003445054a26689f1264b1b9bf7261bd1b
F src/pager.c efa923693e958696eee69b205a20bfbc402c8480
F src/pager.c 0ffa313a30ed6d061d9c6601b7b175cc50a1cab7
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
F src/parse.y bd51bc17cbfe7549adb4ca3747b1c3d384645065
F src/parse.y cce844ccb80b5f969b04c25100c8d94338488efb
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c
@@ -219,21 +219,21 @@ F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
F src/select.c d1acf45637f70d71a76cb8312507550e3aee6caa
F src/shell.c 24722d24d4ea8ca93db35e44db7308de786767ca
F src/select.c 50961f0d0ab8f2d45ff29ec5f91d8db221330ca7
F src/shell.c 3dd86bf73ccd079f0e32ef5069600586085e8239
F src/sqlite.h.in eed7f7d66a60daaa7b4a597dcd9bad87aad9611b
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h 29b97acb02309ad07de107a81c381512066fc2e4
F src/sqliteInt.h 5b1f4e30c8332270e4c14254ef1fbcbd92a4a4c7
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 21ca0043d7c48cde5dabed5c1116eee1be692f62
F src/tclsqlite.c 649d373f2a3cfbefe8e935a8dec83686616f9a85
F src/test1.c 2401eee14a4309a7cfe2aeb2f30ad517a1d9c299
F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35
F src/test2.c 0f8bd858c127fd5236dd965d534622422fbe0b2f
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
F src/test5.c a6d1ac55ac054d0b2b8f37b5e655b6c92645a013
F src/test5.c 41e6e732f14a54c7b47f753e364700760f6521b0
F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723
F src/test7.c 72b732baa5642f795655ba1126ea032af46ecfd2
F src/test8.c 54ccd7b1df5062f0ecbf50a8f7b618f8b1f13b20
@@ -275,25 +275,25 @@ F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9
F src/test_vfstrace.c 3a0ab304682fecbceb689e7d9b904211fde11d78
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7
F src/trigger.c 5c1c0b899ac0ce284763dcb8fdbaa38ecf15ef98
F src/update.c 3d2bdfe24d78303cf7fd3017aaa2d848d47a1020
F src/trigger.c a417d386e214f0abd2e0f756b834b4d9f4d3368a
F src/update.c a7df6fffce6bfedc578fda6136dd33e34a63f8ee
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
F src/util.c 15ac2627f548f5481d0d7e6c4eb67be673027695
F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
F src/vdbe.c 2e46c464e910cf0f11acf6690e8f72d7239a5f63
F src/vdbe.c e5c87476d717aebef5dafceab11417ebf2730554
F src/vdbe.h e6c4c610fcabad4fa80ebb1efc6822a9367e2b26
F src/vdbeInt.h 42db251e9f863401ff847b90d5fe1614c89a6a56
F src/vdbeapi.c ce4e68ea4842cc6081046f533d088dcf01d247ad
F src/vdbeaux.c a3327afa8cfcc5bb3d38f2b2a599bac5fb63c6be
F src/vdbeblob.c bc40f98f256f0b34116d6a44b114da4a81a15d33
F src/vdbemem.c 23cdc14ed43e0aafa57bd72b9bf3d5b1641afa91
F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8
F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820
F src/vdbeaux.c dac6e571262a322b2f889752a8dd36549bdacd2b
F src/vdbeblob.c 9542e116c1db5ed813977581d506c176e117c0ec
F src/vdbemem.c 06603e8e9d2f3247b68c6bbe4bd37fb6721b5bda
F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
F src/where.c 087307272e374c35c7eb1eb722f0ab7db09317f2
F src/where.c b0436385f40e86f0f4cc60355cd018bde2c89d4b
F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -336,9 +336,9 @@ F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
F test/backcompat.test 5f8ad58b3eaebc78cd2c66c65476a42e6f32b2ad
F test/backup.test c9cdd23a495864b9edf75a9fa66f5cb7e10fcf62
F test/backup.test 3b072335eadafa32ab940fceed5852fb48c30655
F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
F test/backup4.test 2a2e4a64388090b152de753fd9e123f28f6a3bd4
F test/backup4.test 139a465f76d43259123d6e09281d080fccc59f8a
F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
@@ -368,7 +368,7 @@ F test/capi3.test 6cdd49656bd62a296924f4d2fcfd05cd2a298369
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
F test/capi3c.test a21869e4d50d5dbb7e566e328fc0bc7c2efa6a32
F test/capi3d.test 6d0fc0a86d73f42dd19a7d8b7761ab9bc02277d0
F test/capi3e.test ad90088b18b0367125ff2d4b5400153fd2f99aab
F test/capi3e.test 1ecb23b79a6f2a50ba336142e795d6e677d1d2d4
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763
F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815
@@ -432,7 +432,7 @@ F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240
F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
F test/distinct.test b9f34f3827a67baf5b5bcb1cdf5185963d629d49
F test/distinct.test c7b194ef95dbddb32d77acbbab2e023c6eed0cb2
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
F test/e_createtable.test ee95d48664503d40f6cc9ef4a7d03216188e2ada
F test/e_delete.test d5186e2f5478b659f16a2c8b66c09892823e542a
@@ -447,7 +447,7 @@ F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
F test/e_select.test 52692ff3849541e828ad4661fe3773a9b8711763
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
F test/e_update.test 312cb8f5ccfe41515a6bb092f8ea562a9bd54d52
F test/e_uri.test a2c92d80093a7efdcfbb11093651cbea87097b6b
F test/e_uri.test bfa56d624d693a81bb29ac2a9a999e35c2c8d9bf
F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
@@ -457,7 +457,7 @@ F test/eqp.test 57c6c604c2807fb5531731c5323133453c24afac
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308
F test/exclusive2.test a3bfa5d21268d2d1f4dd1c094ad9cd583914ca73
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d
@@ -593,16 +593,16 @@ F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test dbf41c0c073c10a8c0fee280cba3e9dddbd4a9c6
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
F test/in4.test 64f3cc1acde1b9161ccdd8e5bde3daefdb5b2617
F test/in5.test 9d8c15bfc9a06da5b354d4d4ecfea9f928769641
F test/in5.test 99f9a40af01711b06d2d614ecfe96129f334fba3
F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328
F test/incrblob2.test bf4d549aa4a466d7fbe3e3a3693d3861263d5600
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
F test/incrblob4.test f26502a5697893e5acea268c910f16478c2f0fab
F test/incrblob_err.test d2562d2771ebffd4b3af89ef64c140dd44371597
F test/incrblobfault.test 280474078f6da9e732cd2a215d3d854969014b6e
F test/incrvacuum.test d2a6ddf5e429720b5fe502766af747915ccf6c32
F test/incrvacuum.test 0e0f03c3c4956de4f3b1d47fe03ea762bc9aaa83
F test/incrvacuum2.test 379eeb8740b0ef60c372c439ad4cbea20b34bb9b
F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
@@ -625,7 +625,7 @@ F test/instr.test 737bbf80685232033f3abedc6ae92f75860b5dd2
F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4
F test/interrupt.test dfe9a67a94b0b2d8f70545ba1a6cca10780d71cc
F test/intpkey.test 7506090fc08e028712a8bf47e5f54111947e3844
F test/io.test 3a7abcef18727cc0f2399e04b0e8903eccae50f8
F test/io.test 148556665d0f5181f510d072f434855bd40be1be
F test/ioerr.test 2a24bd6ed5a8b062e64bfe1f6cf94fb25e92210d
F test/ioerr2.test 9d71166f8466eda510f1af6137bdabaa82b5408d
F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
@@ -725,7 +725,7 @@ F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
F test/orderby5.test 0eb82d5890c3f3d0563966560cfdc984ea69e30c
F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
F test/pager1.test c609ea28a3692d8983e945a253ebae25ad385977
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
@@ -737,7 +737,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
F test/permutations.test 40add071ba71aefe1c04f5845308cf46f7de8d04
F test/permutations.test deb0e98ed7e2849fd896a39e3443b342b7feda2a
F test/pragma.test e882183ecd21d064cec5c7aaea174fbd36293429
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
@@ -786,7 +786,7 @@ F test/select6.test e76bd10a56988f15726c097a5d5a7966fe82d3b2
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
F test/selectA.test 99cf21df033b93033ea4f34aba14a500f48f04fe
F test/selectA.test 77adaffe9704cb80e301ebaeff4b107b58d435c5
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
F test/selectC.test 871fb55d884d3de5943c4057ebd22c2459e71977
F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394
@@ -803,7 +803,7 @@ F test/shared9.test 5f2a8f79b4d6c7d107a01ffa1ed05ae7e6333e21
F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
F test/shared_err.test 0079c05c97d88cfa03989b7c20a8b266983087aa
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test e7c0b9ebda25d5e78f0a3ea0dc4e31bb6d8098c0
F test/shell1.test f2a1d471e5cd2b42f7a65b166dc1ace2b8d11583
F test/shell2.test c57da3a381c099b02c813ba156298d5c2f5c93a3
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9
@@ -824,7 +824,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 7130d2cb6db45baa553a4ab2f715116c71c2d9f4
F test/speedtest1.c 1603da7b4897716f9df15bd71b0310f56ec3181e
F test/spellfix.test 61309f5efbec53603b3f86457d34a504f80abafe
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
@@ -835,7 +835,7 @@ F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
F test/syscall.test a653783d985108c4912cc64d341ffbbb55ad2806
F test/syscall.test 8e96912cf2e41b572d00c537ac71b9f5bb72477e
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
F test/table.test 580d23530187026d4502fae74a490f0408cf2cc7
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
@@ -844,7 +844,7 @@ F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
F test/tester.tcl 9bd04481b8b0ef1f2049ad01f28e175ee9a14f7b
F test/tester.tcl cc5fc5ecfbbd90f4c100d3aaea65eb5d3b3de988
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -869,6 +869,7 @@ F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
F test/tkt-3a77c9714e.test b08bca26de1140bdf004a37716582a43d7bd8be8
F test/tkt-3fe897352e.test 27e26eb0f1811aeba4d65aba43a4c52e99da5e70
F test/tkt-4a03edc4c8.test 91c0e135888cdc3d4eea82406a44b05c8c1648d0
F test/tkt-4c86b126f2.test cbcc611becd0396890169ab23102dd70048bbc9a
F test/tkt-4dd95f6943.test 3d0ce415d2ee15d3d564121960016b9c7be79407
F test/tkt-54844eea3f.test a12b851128f46a695e4e378cca67409b9b8f5894
F test/tkt-5d863f876e.test c9f36ca503fa154a3655f92a69d2c30da1747bfa
@@ -987,7 +988,7 @@ F test/tkt3929.test cdf67acf5aa936ec4ffead81db87f8a71fe40e59
F test/tkt3935.test e15261fedb9e30a4305a311da614a5d8e693c767
F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da
F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd
F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1
F test/tkt4018.test 04115ae33ee39988a076bd78decef7cec820ebe0
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
F test/tpch01.test 8f4ac52f62f3e9f6bce0889105aecdf0275e331b
F test/trace.test 4b36a41a3e9c7842151af6da5998f5080cdad9e5
@@ -1018,7 +1019,7 @@ F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
F test/unixexcl.test a9870e46cc6f8390a494513d4f2bf55b5a8b3e46
F test/unordered.test ef85ac8f2f3c93ed2b9e811b684de73175fc464c
F test/update.test 1b6c488a8f993d090b7ee9ad0e234faa161b3aeb
F test/uri.test 63e03df051620a18f794b4f4adcdefb3c23b6751
F test/uri.test 6aad91f02090012a03d0545a30c7cea02c70947a
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
F test/vacuum2.test af432e6e3bfc0ea20a80cb86a03c7d9876d38324
@@ -1048,7 +1049,7 @@ F test/vtab_shared.test 6acafaae7126c9f49be72c2f57eb8bef3024f1cb
F test/wal.test 40073e54359d43354925b2b700b7eebd5e207285
F test/wal2.test a8e3963abf6b232cf0b852b09b53665ef34007af
F test/wal3.test b22eb662bcbc148c5f6d956eaf94b047f7afe9c0
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
F test/wal4.test fc104ae9670221a5326c611789c205889aebe9fa
F test/wal5.test 8f888b50f66b78821e61ed0e233ded5de378224b
F test/wal6.test 527581f5527bf9c24394991e2be83000aace5f9e
F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd
@@ -1077,7 +1078,7 @@ F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
F test/where7.test 5a4b0abc207d71da4deecd734ad8579e8dd40aa8
F test/where8.test d2b4fd6d7b7c5d44f590182a05033d78a14c00a1
F test/where8.test 84033c4da466d90fe7ef0152661ff67fd218105f
F test/where8m.test da346596e19d54f0aba35ebade032a7c47d79739
F test/where9.test 4f3eab951353a3ae164befc521c777dfa903e46c
F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
@@ -1092,7 +1093,7 @@ F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/with1.test ce15d69d34a2576b0e47d78c244d1ba2a31679d1
F test/with1.test 268081a6b14817a262ced4d0ee34d4d2a1dd2068
F test/with2.test 2fe78fcd8deef2a0f9cfc49bfc755911d0b3fd64
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8
@@ -1152,7 +1153,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
P 715fac7749a6b1523fe9f7de8263f0c4d1571d07
R f507eae713e5b72113d4535fdf641347
U drh
Z 759564bb3627cf7a97644b4104ef33de
P 4d7057c4942464b4302031a1ee9f195700c5e66d 0a8bcbbd4e11a60923736b2be9b1ce83ea2263fb
R 4a7f56d4353f8f673e4fcc636c77fc4f
U dan
Z be45f6e8774a4940e329c99165e0e8a7
+1 -1
View File
@@ -1 +1 @@
881164cf6e5c987ae0e40804267715d878135198
f352ef57e39a9443b4bdf47fc2c9b01006fe3c10
+1 -1
View File
@@ -469,7 +469,7 @@ void sqlite3AlterRenameTable(
}
#endif
/* Begin a transaction and code the VerifyCookie for database iDb.
/* Begin a transaction for database iDb.
** Then modify the schema cookie (since the ALTER TABLE modifies the
** schema). Open a statement transaction if the table is a virtual
** table.
+4 -7
View File
@@ -1527,7 +1527,7 @@ static int btreeInitPage(MemPage *pPage){
** Set up a raw page so that it looks like a database page holding
** no entries.
*/
static void zeroPage(MemPage *pPage, u8 flags){
static void zeroPage(MemPage *pPage, int flags){
unsigned char *data = pPage->aData;
BtShared *pBt = pPage->pBt;
u8 hdr = pPage->hdrOffset;
@@ -2585,7 +2585,6 @@ static int newDatabase(BtShared *pBt){
MemPage *pP1;
unsigned char *data;
int rc;
u8 flags;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pBt->nPage>0 ){
@@ -2608,9 +2607,7 @@ static int newDatabase(BtShared *pBt){
data[22] = 32;
data[23] = 32;
memset(&data[24], 0, 100-24);
flags = (pBt->openFlags&BTREE_SINGLE_INDEX) ? PTF_ZERODATA|PTF_LEAF
: PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF;
zeroPage(pP1, flags);
zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA );
pBt->btsFlags |= BTS_PAGESIZE_FIXED;
#ifndef SQLITE_OMIT_AUTOVACUUM
assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 );
@@ -6112,7 +6109,7 @@ static int balance_nonroot(
u16 leafCorrection; /* 4 if pPage is a leaf. 0 if not */
int leafData; /* True if pPage is a leaf of a LEAFDATA tree */
int usableSpace; /* Bytes in pPage beyond the header */
u8 pageFlags; /* Value of pPage->aData[0] */
int pageFlags; /* Value of pPage->aData[0] */
int subtotal; /* Subtotal of bytes in cells on one page */
int iSpace1 = 0; /* First unused byte of aSpace1[] */
int iOvflSpace = 0; /* First unused byte of aOvflSpace[] */
@@ -7213,7 +7210,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
MemPage *pRoot;
Pgno pgnoRoot;
int rc;
u8 ptfFlags; /* Page-type flage for the root page of new table */
int ptfFlags; /* Page-type flage for the root page of new table */
assert( sqlite3BtreeHoldsMutex(p) );
assert( pBt->inTransaction==TRANS_WRITE );
+4 -5
View File
@@ -56,11 +56,10 @@ int sqlite3BtreeOpen(
** NOTE: These values must match the corresponding PAGER_ values in
** pager.h.
*/
#define BTREE_OMIT_JOURNAL 0x01 /* Do not create or use a rollback journal */
#define BTREE_MEMORY 0x02 /* This is an in-memory DB */
#define BTREE_SINGLE 0x04 /* The file contains at most 1 b-tree */
#define BTREE_UNORDERED 0x08 /* Use of a hash implementation is OK */
#define BTREE_SINGLE_INDEX 0x10 /* File contains one index btree */
#define BTREE_OMIT_JOURNAL 1 /* Do not create or use a rollback journal */
#define BTREE_MEMORY 2 /* This is an in-memory DB */
#define BTREE_SINGLE 4 /* The file contains at most 1 b-tree */
#define BTREE_UNORDERED 8 /* Use of a hash implementation is OK */
int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetCacheSize(Btree*,int);
+30 -63
View File
@@ -149,20 +149,22 @@ void sqlite3FinishCoding(Parse *pParse){
** transaction on each used database and to verify the schema cookie
** on each used database.
*/
if( pParse->cookieGoto>0 ){
if( db->mallocFailed==0 && (pParse->cookieMask || pParse->pConstExpr) ){
yDbMask mask;
int iDb, i, addr;
sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
int iDb, i;
assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
sqlite3VdbeJumpHere(v, 0);
for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
if( (mask & pParse->cookieMask)==0 ) continue;
sqlite3VdbeUsesBtree(v, iDb);
sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
if( db->init.busy==0 ){
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
sqlite3VdbeAddOp3(v, OP_VerifyCookie,
iDb, pParse->cookieValue[iDb],
db->aDb[iDb].pSchema->iGeneration);
}
sqlite3VdbeAddOp4Int(v,
OP_Transaction, /* Opcode */
iDb, /* P1 */
(mask & pParse->writeMask)!=0, /* P2 */
pParse->cookieValue[iDb], /* P3 */
db->aDb[iDb].pSchema->iGeneration /* P4 */
);
if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
for(i=0; i<pParse->nVtabLock; i++){
@@ -183,17 +185,16 @@ void sqlite3FinishCoding(Parse *pParse){
sqlite3AutoincrementBegin(pParse);
/* Code constant expressions that where factored out of inner loops */
addr = pParse->cookieGoto;
if( pParse->pConstExpr ){
ExprList *pEL = pParse->pConstExpr;
pParse->cookieGoto = 0;
pParse->okConstFactor = 0;
for(i=0; i<pEL->nExpr; i++){
sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg);
}
}
/* Finally, jump back to the beginning of the executable code. */
sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
sqlite3VdbeAddOp2(v, OP_Goto, 0, 1);
}
}
@@ -216,7 +217,6 @@ void sqlite3FinishCoding(Parse *pParse){
pParse->nSet = 0;
pParse->nVar = 0;
pParse->cookieMask = 0;
pParse->cookieGoto = 0;
}
/*
@@ -3825,59 +3825,26 @@ int sqlite3OpenTempDatabase(Parse *pParse){
}
/*
** Generate VDBE code that will verify the schema cookie and start
** a read-transaction for all named database files.
**
** It is important that all schema cookies be verified and all
** read transactions be started before anything else happens in
** the VDBE program. But this routine can be called after much other
** code has been generated. So here is what we do:
**
** The first time this routine is called, we code an OP_Goto that
** will jump to a subroutine at the end of the program. Then we
** record every database that needs its schema verified in the
** pParse->cookieMask field. Later, after all other code has been
** generated, the subroutine that does the cookie verifications and
** starts the transactions will be coded and the OP_Goto P2 value
** will be made to point to that subroutine. The generation of the
** cookie verification subroutine code happens in sqlite3FinishCoding().
**
** If iDb<0 then code the OP_Goto only - don't set flag to verify the
** schema on any databases. This can be used to position the OP_Goto
** early in the code, before we know if any database tables will be used.
** Record the fact that the schema cookie will need to be verified
** for database iDb. The code to actually verify the schema cookie
** will occur at the end of the top-level VDBE and will be generated
** later, by sqlite3FinishCoding().
*/
void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
sqlite3 *db = pToplevel->db;
yDbMask mask;
#ifndef SQLITE_OMIT_TRIGGER
if( pToplevel!=pParse ){
/* This branch is taken if a trigger is currently being coded. In this
** case, set cookieGoto to a non-zero value to show that this function
** has been called. This is used by the sqlite3ExprCodeConstants()
** function. */
pParse->cookieGoto = -1;
}
#endif
if( pToplevel->cookieGoto==0 ){
Vdbe *v = sqlite3GetVdbe(pToplevel);
if( v==0 ) return; /* This only happens if there was a prior error */
pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1;
}
if( iDb>=0 ){
sqlite3 *db = pToplevel->db;
yDbMask mask;
assert( iDb<db->nDb );
assert( db->aDb[iDb].pBt!=0 || iDb==1 );
assert( iDb<SQLITE_MAX_ATTACHED+2 );
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
mask = ((yDbMask)1)<<iDb;
if( (pToplevel->cookieMask & mask)==0 ){
pToplevel->cookieMask |= mask;
pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
if( !OMIT_TEMPDB && iDb==1 ){
sqlite3OpenTempDatabase(pToplevel);
}
assert( iDb>=0 && iDb<db->nDb );
assert( db->aDb[iDb].pBt!=0 || iDb==1 );
assert( iDb<SQLITE_MAX_ATTACHED+2 );
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
mask = ((yDbMask)1)<<iDb;
if( (pToplevel->cookieMask & mask)==0 ){
pToplevel->cookieMask |= mask;
pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
if( !OMIT_TEMPDB && iDb==1 ){
sqlite3OpenTempDatabase(pToplevel);
}
}
}
+1 -3
View File
@@ -383,9 +383,7 @@ void sqlite3DeleteFrom(
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
}else{
/* For a WITHOUT ROWID table, create an ephermeral table used to
** hold all primary keys for rows to be deleted. Use OP_OpenEphemeral
** rather than OP_OpenHash since for efficiency reasons it is good to
** process the primary keys in order. */
** hold all primary keys for rows to be deleted. */
pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk!=0 );
nPk = pPk->nKeyCol;
+213 -221
View File
@@ -1060,7 +1060,6 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
pNew->iLimit = 0;
pNew->iOffset = 0;
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
pNew->pRightmost = 0;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->addrOpenEphm[2] = -1;
@@ -1490,177 +1489,6 @@ int sqlite3CodeOnce(Parse *pParse){
return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++);
}
/*
** Generate code that constructs a transient table for the RHS of an IN
** operator:
**
** x IN (4,5,11) -- IN operator with list on right-hand side
** x IN (SELECT a FROM b) -- IN operator with subquery on the right
**
** The pExpr parameter is the IN expression.
**
** If parameter isRowid is non-zero, then expression pExpr is guaranteed
** to be of the form "<rowid> IN (?, ?, ?)", where <rowid> is a reference
** to some integer key column of a table B-Tree. In this case, use an
** intkey B-Tree to store the set of IN(...) values instead of the usual
** (slower) variable length keys B-Tree.
*/
#ifndef SQLITE_OMIT_SUBQUERY
static void sqlite3CreateInOperatorRhsTable(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* The IN, SELECT, or EXISTS operator */
int isRowid, /* If true, LHS of IN operator is a rowid */
int bOrdered /* If true, must use btree, not a hash */
){
int testAddr = -1; /* One-time test address */
Vdbe *v = sqlite3GetVdbe(pParse); /* prepared stmt under construction */
char affinity; /* Affinity of the LHS of the IN */
int addr; /* Address of OP_Open.. instruction */
Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
KeyInfo *pKeyInfo = 0; /* Key information */
assert( v!=0 );
assert( pExpr->op==TK_IN );
sqlite3ExprCachePush(pParse);
/* This code must be run in its entirety every time it is encountered
** if any of the following is true:
**
** * The right-hand side is a correlated subquery
** * We are inside a trigger
**
** If all of the above are false, then we can run this code just once
** save the results, and reuse the same result on subsequent invocations.
*/
if( !ExprHasProperty(pExpr, EP_VarSelect) ){
testAddr = sqlite3CodeOnce(pParse);
}
#ifndef SQLITE_OMIT_EXPLAIN
if( pParse->explain==2 ){
char *zMsg = sqlite3MPrintf(
pParse->db, "EXECUTE %sLIST SUBQUERY %d", testAddr>=0?"":"CORRELATED ",
pParse->iNextSelectId
);
sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
}
#endif
affinity = sqlite3ExprAffinity(pLeft);
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
** expression it is handled the same way. An ephemeral table is
** filled with single-field index keys representing the results
** from the SELECT or the <exprlist>.
**
** If the 'x' expression is a column value, or the SELECT...
** statement returns a column value, then the affinity of that
** column is used to build the index keys. If both 'x' and the
** SELECT... statement are columns, then numeric affinity is used
** if either column has NUMERIC or INTEGER affinity. If neither
** 'x' nor the SELECT... statement are columns, then numeric affinity
** is used.
*/
pExpr->iTable = pParse->nTab++;
addr = sqlite3VdbeAddOp2(v, bOrdered ? OP_OpenEphemeral : OP_OpenHash,
pExpr->iTable, !isRowid);
pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, 1, 1);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
/* Case 1: expr IN (SELECT ...)
**
** Generate code to write the results of the select into the temporary
** table allocated and opened above.
*/
SelectDest dest;
ExprList *pEList;
assert( !isRowid );
sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
dest.affSdst = (u8)affinity;
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
pExpr->x.pSelect->iLimit = 0;
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){
sqlite3KeyInfoUnref(pKeyInfo);
return;
}
pEList = pExpr->x.pSelect->pEList;
assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
assert( pEList!=0 );
assert( pEList->nExpr>0 );
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
pEList->a[0].pExpr);
}else if( ALWAYS(pExpr->x.pList!=0) ){
/* Case 2: expr IN (exprlist)
**
** For each expression, build an index key from the evaluation and
** store it in the temporary table. If <expr> is a column, then use
** that columns affinity when building index keys. If <expr> is not
** a column, use numeric affinity.
*/
int i;
ExprList *pList = pExpr->x.pList;
struct ExprList_item *pItem;
int r1, r2, r3;
if( !affinity ){
affinity = SQLITE_AFF_NONE;
}
if( pKeyInfo ){
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
}
/* Loop through each expression in <exprlist>. */
r1 = sqlite3GetTempReg(pParse);
r2 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Null, 0, r2);
for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
Expr *pE2 = pItem->pExpr;
int iValToIns;
/* If the expression is not constant then we will need to
** disable the test that was generated above that makes sure
** this code only executes once. Because for a non-constant
** expression we need to rerun this code each time.
*/
if( testAddr>=0 && !sqlite3ExprIsConstant(pE2) ){
sqlite3VdbeChangeToNoop(v, testAddr);
testAddr = -1;
}
/* Evaluate the expression and insert it into the temp table */
if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
}else{
r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
if( isRowid ){
sqlite3VdbeAddOp2(v, OP_MustBeInt, r3,
sqlite3VdbeCurrentAddr(v)+2);
sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
}else{
sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
sqlite3ExprCacheAffinityChange(pParse, r3, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
}
}
}
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempReg(pParse, r2);
}
if( pKeyInfo ){
sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
}
if( testAddr>=0 ){
sqlite3VdbeJumpHere(v, testAddr);
}
sqlite3ExprCachePop(pParse, 1);
}
#endif /* SQLITE_OMIT_SUBQUERY */
/*
** This function is used by the implementation of the IN (...) operator.
** The pX parameter is the expression on the RHS of the IN operator, which
@@ -1724,19 +1552,15 @@ static void sqlite3CreateInOperatorRhsTable(
**
** in order to avoid running the <test if data structure contains null>
** test more often than is necessary.
**
** IN_INDEX_EPH ephemeral tables must be in key order if the bOrdered flag
** is true. If bOrdered is false, the generated table can be a hash.
*/
#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound, int bOrdered){
int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
Select *p; /* SELECT to the right of IN operator */
int eType = 0; /* Type of RHS table. IN_INDEX_* */
int iTab = pParse->nTab++; /* Cursor of the RHS table */
int mustBeUnique = (prNotFound==0); /* True if RHS must be unique */
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
assert( v!=0 );
assert( pX->op==TK_IN );
/* Check to see if an existing table or index can be used to
@@ -1745,11 +1569,11 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound, int bOrdered){
*/
p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){
sqlite3 *db = pParse->db; /* Database connection */
Table *pTab; /* Table <table>. */
Expr *pExpr; /* Expression <column> */
i16 iCol; /* Index of column <column> */
i16 iDb; /* Database idx for pTab */
sqlite3 *db = pParse->db; /* Database connection */
Table *pTab; /* Table <table>. */
Expr *pExpr; /* Expression <column> */
i16 iCol; /* Index of column <column> */
i16 iDb; /* Database idx for pTab */
assert( p ); /* Because of isCandidateForInOpt(p) */
assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */
@@ -1759,15 +1583,24 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound, int bOrdered){
pExpr = p->pEList->a[0].pExpr;
iCol = (i16)pExpr->iColumn;
/* Code an OP_VerifyCookie and OP_TableLock for <table>. */
/* Code an OP_Transaction and OP_TableLock for <table>. */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
/* This function is only called from two places. In both cases the vdbe
** has already been allocated. So assume sqlite3GetVdbe() is always
** successful here.
*/
assert(v);
if( iCol<0 ){
int iAddr = sqlite3CodeOnce(pParse);
int iAddr;
iAddr = sqlite3CodeOnce(pParse);
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
eType = IN_INDEX_ROWID;
sqlite3VdbeJumpHere(v, iAddr);
}else{
Index *pIdx; /* Iterator variable */
@@ -1822,7 +1655,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound, int bOrdered){
eType = IN_INDEX_ROWID;
}
}
sqlite3CreateInOperatorRhsTable(pParse, pX, eType==IN_INDEX_ROWID,bOrdered);
sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
pParse->nQueryLoop = savedNQueryLoop;
}else{
pX->iTable = iTab;
@@ -1832,37 +1665,56 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound, int bOrdered){
#endif
/*
** Generate code for scalar subqueries used as a subquery expression:
** Generate code for scalar subqueries used as a subquery expression, EXISTS,
** or IN operators. Examples:
**
** (SELECT a FROM b) -- subquery
** EXISTS (SELECT a FROM b) -- EXISTS subquery
** x IN (4,5,11) -- IN operator with list on right-hand side
** x IN (SELECT a FROM b) -- IN operator with subquery on the right
**
** The pExpr parameter describes the expression that contains the subquery.
** The pExpr parameter describes the expression that contains the IN
** operator or subquery.
**
** Return the register that holds the result.
** If parameter isRowid is non-zero, then expression pExpr is guaranteed
** to be of the form "<rowid> IN (?, ?, ?)", where <rowid> is a reference
** to some integer key column of a table B-Tree. In this case, use an
** intkey B-Tree to store the set of IN(...) values instead of the usual
** (slower) variable length keys B-Tree.
**
** If rMayHaveNull is non-zero, that means that the operation is an IN
** (not a SELECT or EXISTS) and that the RHS might contains NULLs.
** Furthermore, the IN is in a WHERE clause and that we really want
** to iterate over the RHS of the IN operator in order to quickly locate
** all corresponding LHS elements. All this routine does is initialize
** the register given by rMayHaveNull to NULL. Calling routines will take
** care of changing this register value to non-NULL if the RHS is NULL-free.
**
** If rMayHaveNull is zero, that means that the subquery is being used
** for membership testing only. There is no need to initialize any
** registers to indicate the presence or absence of NULLs on the RHS.
**
** For a SELECT or EXISTS operator, return the register that holds the
** result. For IN operators or if an error occurs, the return value is 0.
*/
#ifndef SQLITE_OMIT_SUBQUERY
static int sqlite3CodeScalarSubquery(
int sqlite3CodeSubselect(
Parse *pParse, /* Parsing context */
Expr *pExpr /* The SELECT or EXISTS operator */
Expr *pExpr, /* The IN, SELECT, or EXISTS operator */
int rMayHaveNull, /* Register that records whether NULLs exist in RHS */
int isRowid /* If true, LHS of IN operator is a rowid */
){
int testAddr = -1; /* One-time test address */
int rReg = 0; /* Register storing resulting */
Vdbe *v = sqlite3GetVdbe(pParse);
Select *pSel; /* SELECT statement to encode */
SelectDest dest; /* How to deal with SELECt result */
if( NEVER(v==0) ) return 0;
testcase( pExpr->op==TK_EXISTS );
testcase( pExpr->op==TK_SELECT );
assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
assert( ExprHasProperty(pExpr, EP_xIsSelect) );
sqlite3ExprCachePush(pParse);
/* This code must be run in its entirety every time it is encountered
** if any of the following is true:
**
** * pExpr is a correlated subquery
** * The right-hand side is a correlated subquery
** * The right-hand side is an expression list containing variables
** * We are inside a trigger
**
** If all of the above are false, then we can run this code just once
@@ -1875,33 +1727,173 @@ static int sqlite3CodeScalarSubquery(
#ifndef SQLITE_OMIT_EXPLAIN
if( pParse->explain==2 ){
char *zMsg = sqlite3MPrintf(
pParse->db, "EXECUTE %sSCALAR SUBQUERY %d",
testAddr>=0?"":"CORRELATED ", pParse->iNextSelectId
pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr>=0?"":"CORRELATED ",
pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
);
sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
}
#endif
pSel = pExpr->x.pSelect;
sqlite3SelectDestInit(&dest, 0, ++pParse->nMem);
if( pExpr->op==TK_SELECT ){
dest.eDest = SRT_Mem;
sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iSDParm);
VdbeComment((v, "Init subquery result"));
}else{
dest.eDest = SRT_Exists;
sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
VdbeComment((v, "Init EXISTS result"));
switch( pExpr->op ){
case TK_IN: {
char affinity; /* Affinity of the LHS of the IN */
int addr; /* Address of OP_OpenEphemeral instruction */
Expr *pLeft = pExpr->pLeft; /* the LHS of the IN operator */
KeyInfo *pKeyInfo = 0; /* Key information */
if( rMayHaveNull ){
sqlite3VdbeAddOp2(v, OP_Null, 0, rMayHaveNull);
}
affinity = sqlite3ExprAffinity(pLeft);
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
** expression it is handled the same way. An ephemeral table is
** filled with single-field index keys representing the results
** from the SELECT or the <exprlist>.
**
** If the 'x' expression is a column value, or the SELECT...
** statement returns a column value, then the affinity of that
** column is used to build the index keys. If both 'x' and the
** SELECT... statement are columns, then numeric affinity is used
** if either column has NUMERIC or INTEGER affinity. If neither
** 'x' nor the SELECT... statement are columns, then numeric affinity
** is used.
*/
pExpr->iTable = pParse->nTab++;
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid);
pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, 1, 1);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
/* Case 1: expr IN (SELECT ...)
**
** Generate code to write the results of the select into the temporary
** table allocated and opened above.
*/
SelectDest dest;
ExprList *pEList;
assert( !isRowid );
sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
dest.affSdst = (u8)affinity;
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
pExpr->x.pSelect->iLimit = 0;
testcase( pKeyInfo==0 ); /* Caused by OOM in sqlite3KeyInfoAlloc() */
if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){
sqlite3KeyInfoUnref(pKeyInfo);
return 0;
}
pEList = pExpr->x.pSelect->pEList;
assert( pKeyInfo!=0 ); /* OOM will cause exit after sqlite3Select() */
assert( pEList!=0 );
assert( pEList->nExpr>0 );
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
pKeyInfo->aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
pEList->a[0].pExpr);
}else if( ALWAYS(pExpr->x.pList!=0) ){
/* Case 2: expr IN (exprlist)
**
** For each expression, build an index key from the evaluation and
** store it in the temporary table. If <expr> is a column, then use
** that columns affinity when building index keys. If <expr> is not
** a column, use numeric affinity.
*/
int i;
ExprList *pList = pExpr->x.pList;
struct ExprList_item *pItem;
int r1, r2, r3;
if( !affinity ){
affinity = SQLITE_AFF_NONE;
}
if( pKeyInfo ){
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
pKeyInfo->aColl[0] = sqlite3ExprCollSeq(pParse, pExpr->pLeft);
}
/* Loop through each expression in <exprlist>. */
r1 = sqlite3GetTempReg(pParse);
r2 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Null, 0, r2);
for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
Expr *pE2 = pItem->pExpr;
int iValToIns;
/* If the expression is not constant then we will need to
** disable the test that was generated above that makes sure
** this code only executes once. Because for a non-constant
** expression we need to rerun this code each time.
*/
if( testAddr>=0 && !sqlite3ExprIsConstant(pE2) ){
sqlite3VdbeChangeToNoop(v, testAddr);
testAddr = -1;
}
/* Evaluate the expression and insert it into the temp table */
if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){
sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns);
}else{
r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
if( isRowid ){
sqlite3VdbeAddOp2(v, OP_MustBeInt, r3,
sqlite3VdbeCurrentAddr(v)+2);
sqlite3VdbeAddOp3(v, OP_Insert, pExpr->iTable, r2, r3);
}else{
sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
sqlite3ExprCacheAffinityChange(pParse, r3, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
}
}
}
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempReg(pParse, r2);
}
if( pKeyInfo ){
sqlite3VdbeChangeP4(v, addr, (void *)pKeyInfo, P4_KEYINFO);
}
break;
}
case TK_EXISTS:
case TK_SELECT:
default: {
/* If this has to be a scalar SELECT. Generate code to put the
** value of this select in a memory cell and record the number
** of the memory cell in iColumn. If this is an EXISTS, write
** an integer 0 (not exists) or 1 (exists) into a memory cell
** and record that memory cell in iColumn.
*/
Select *pSel; /* SELECT statement to encode */
SelectDest dest; /* How to deal with SELECt result */
testcase( pExpr->op==TK_EXISTS );
testcase( pExpr->op==TK_SELECT );
assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
assert( ExprHasProperty(pExpr, EP_xIsSelect) );
pSel = pExpr->x.pSelect;
sqlite3SelectDestInit(&dest, 0, ++pParse->nMem);
if( pExpr->op==TK_SELECT ){
dest.eDest = SRT_Mem;
sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iSDParm);
VdbeComment((v, "Init subquery result"));
}else{
dest.eDest = SRT_Exists;
sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
VdbeComment((v, "Init EXISTS result"));
}
sqlite3ExprDelete(pParse->db, pSel->pLimit);
pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0,
&sqlite3IntTokens[1]);
pSel->iLimit = 0;
if( sqlite3Select(pParse, pSel, &dest) ){
return 0;
}
rReg = dest.iSDParm;
ExprSetVVAProperty(pExpr, EP_NoReduce);
break;
}
}
sqlite3ExprDelete(pParse->db, pSel->pLimit);
pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0,
&sqlite3IntTokens[1]);
pSel->iLimit = 0;
if( sqlite3Select(pParse, pSel, &dest) ){
return 0;
}
rReg = dest.iSDParm;
ExprSetVVAProperty(pExpr, EP_NoReduce);
if( testAddr>=0 ){
sqlite3VdbeJumpHere(v, testAddr);
@@ -1948,7 +1940,7 @@ static void sqlite3ExprCodeIN(
v = pParse->pVdbe;
assert( v!=0 ); /* OOM detected prior to this routine */
VdbeNoopComment((v, "begin IN expr"));
eType = sqlite3FindInIndex(pParse, pExpr, &rRhsHasNull, 0);
eType = sqlite3FindInIndex(pParse, pExpr, &rRhsHasNull);
/* Figure out the affinity to use to create a key from the results
** of the expression. affinityStr stores a static string suitable for
@@ -2820,7 +2812,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
case TK_SELECT: {
testcase( op==TK_EXISTS );
testcase( op==TK_SELECT );
inReg = sqlite3CodeScalarSubquery(pParse, pExpr);
inReg = sqlite3CodeSubselect(pParse, pExpr, 0, 0);
break;
}
case TK_IN: {
+19 -55
View File
@@ -349,17 +349,13 @@ void sqlite3AutoincrementEnd(Parse *pParse){
** co-routine. Run the co-routine to its next breakpoint
** by calling "OP_Yield $X" where $X is pDest->iSDParm.
**
** pDest->iSDParm+1 The register holding the "completed" flag for the
** co-routine. This register is 0 if the previous Yield
** generated a new result row, or 1 if the subquery
** has completed. If the Yield is called again
** after this register becomes 1, then the VDBE will
** halt with an SQLITE_INTERNAL error.
**
** pDest->iSdst First result register.
**
** pDest->nSdst Number of result registers.
**
** At EOF the first result register will be marked as "undefined" so that
** the caller can know when to stop reading results.
**
** This routine handles all of the register allocation and fills in the
** pDest structure appropriately.
**
@@ -370,7 +366,6 @@ void sqlite3AutoincrementEnd(Parse *pParse){
** reg[pDest->iSdst+pDest->nSdst-1]:
**
** X <- A
** EOF <- 0
** goto B
** A: setup for the SELECT
** loop rows in the SELECT
@@ -378,16 +373,13 @@ void sqlite3AutoincrementEnd(Parse *pParse){
** yield X
** end loop
** cleanup after the SELECT
** EOF <- 1
** yield X
** halt-error
** end co-routine R
** B:
**
** To use this subroutine, the caller generates code as follows:
**
** [ Co-routine generated by this subroutine, shown above ]
** S: yield X
** if EOF goto E
** S: yield X, at EOF goto E
** if skip this row, goto C
** if terminate loop, goto E
** deal with this row
@@ -396,31 +388,21 @@ void sqlite3AutoincrementEnd(Parse *pParse){
*/
int sqlite3CodeCoroutine(Parse *pParse, Select *pSelect, SelectDest *pDest){
int regYield; /* Register holding co-routine entry-point */
int regEof; /* Register holding co-routine completion flag */
int addrTop; /* Top of the co-routine */
int j1; /* Jump instruction */
int rc; /* Result code */
Vdbe *v; /* VDBE under construction */
regYield = ++pParse->nMem;
regEof = ++pParse->nMem;
v = sqlite3GetVdbe(pParse);
addrTop = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_Integer, addrTop+2, regYield); /* X <- A */
VdbeComment((v, "Co-routine entry point"));
sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof); /* EOF <- 0 */
VdbeComment((v, "Co-routine completion flag"));
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
sqlite3SelectDestInit(pDest, SRT_Coroutine, regYield);
j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
rc = sqlite3Select(pParse, pSelect, pDest);
assert( pParse->nErr==0 || rc );
if( pParse->db->mallocFailed && rc==SQLITE_OK ) rc = SQLITE_NOMEM;
if( rc ) return rc;
sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */
sqlite3VdbeAddOp1(v, OP_Yield, regYield); /* yield X */
sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort);
VdbeComment((v, "End of coroutine"));
sqlite3VdbeJumpHere(v, j1); /* label B: */
sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield);
sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
return rc;
}
@@ -488,7 +470,6 @@ static int xferOptimization(
** and the SELECT clause does not read from <table> at any time.
** The generated code follows this template:
**
** EOF <- 0
** X <- A
** goto B
** A: setup for the SELECT
@@ -497,12 +478,9 @@ static int xferOptimization(
** yield X
** end loop
** cleanup after the SELECT
** EOF <- 1
** yield X
** goto A
** end-coroutine X
** B: open write cursor to <table> and its indices
** C: yield X
** if EOF goto D
** C: yield X, at EOF goto D
** insert the select result into <table> from R..R+n
** goto C
** D: cleanup
@@ -513,7 +491,6 @@ static int xferOptimization(
** we have to use a intermediate table to store the results of
** the select. The template is like this:
**
** EOF <- 0
** X <- A
** goto B
** A: setup for the SELECT
@@ -522,12 +499,9 @@ static int xferOptimization(
** yield X
** end loop
** cleanup after the SELECT
** EOF <- 1
** yield X
** halt-error
** end co-routine R
** B: open temp table
** L: yield X
** if EOF goto M
** L: yield X, at EOF goto M
** insert row from R..R+n into temp table
** goto L
** M: open write cursor to <table> and its indices
@@ -576,7 +550,6 @@ void sqlite3Insert(
int regIns; /* Block of regs holding rowid+data being inserted */
int regRowid; /* registers holding insert rowid */
int regData; /* register holding first column to insert */
int regEof = 0; /* Register recording end of SELECT data */
int *aRegIdx = 0; /* One register allocated to each index */
#ifndef SQLITE_OMIT_TRIGGER
@@ -689,7 +662,6 @@ void sqlite3Insert(
int rc = sqlite3CodeCoroutine(pParse, pSelect, &dest);
if( rc ) goto insert_cleanup;
regEof = dest.iSDParm + 1;
regFromSelect = dest.iSdst;
assert( pSelect->pEList );
nColumn = pSelect->pEList->nExpr;
@@ -714,31 +686,25 @@ void sqlite3Insert(
** here is from the 4th template:
**
** B: open temp table
** L: yield X
** if EOF goto M
** L: yield X, goto M at EOF
** insert row from R..R+n into temp table
** goto L
** M: ...
**
** Use OP_OpenEphemeral, not OP_OpenHash, so that srcTab behaves as
** a FIFO.
*/
int regRec; /* Register to hold packed record */
int regTempRowid; /* Register to hold temp table ROWID */
int addrTop; /* Label "L" */
int addrIf; /* Address of jump to M */
srcTab = pParse->nTab++;
regRec = sqlite3GetTempReg(pParse);
regTempRowid = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);
addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);
sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regTempRowid);
sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regTempRowid);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);
sqlite3VdbeJumpHere(v, addrIf);
sqlite3VdbeJumpHere(v, addrTop);
sqlite3ReleaseTempReg(pParse, regRec);
sqlite3ReleaseTempReg(pParse, regTempRowid);
}
@@ -850,7 +816,7 @@ void sqlite3Insert(
/* This block codes the top of loop only. The complete loop is the
** following pseudocode (template 4):
**
** rewind temp table
** rewind temp table, if empty goto D
** C: loop over rows of intermediate table
** transfer values form intermediate table into <table>
** end loop
@@ -862,14 +828,12 @@ void sqlite3Insert(
/* This block codes the top of loop only. The complete loop is the
** following pseudocode (template 3):
**
** C: yield X
** if EOF goto D
** C: yield X, at EOF goto D
** insert the select result into <table> from R..R+n
** goto C
** D: ...
*/
addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
addrInsTop = sqlite3VdbeAddOp1(v, OP_If, regEof);
addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
}
/* Allocate registers for holding the rowid of the new row,
@@ -2074,7 +2038,7 @@ static int xferOptimization(
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
}
sqlite3VdbeJumpHere(v, emptySrcTest);
if( emptySrcTest ) sqlite3VdbeJumpHere(v, emptySrcTest);
sqlite3ReleaseTempReg(pParse, regRowid);
sqlite3ReleaseTempReg(pParse, regData);
if( emptyDestTest ){
+160 -56
View File
@@ -83,32 +83,6 @@
# endif
#endif
/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it. If the OS lacks
** large file support, these should be no-ops.
**
** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
** on the compiler command line. This is necessary if you are compiling
** on a recent machine (ex: RedHat 7.2) but you want your code to work
** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
** without this option, LFS is enable. But LFS does not exist in the kernel
** in RedHat 6.0, so the code won't work. Hence, for maximum binary
** portability you should omit LFS.
**
** The previous paragraph was written in 2005. (This paragraph is written
** on 2008-11-28.) These days, all Linux kernels support large files, so
** you should probably leave LFS enabled. But some embedded platforms might
** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
*/
#ifndef SQLITE_DISABLE_LFS
# define _LARGE_FILE 1
# ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 64
# endif
# define _LARGEFILE_SOURCE 1
#endif
/*
** standard include files.
*/
@@ -229,9 +203,7 @@ struct unixFile {
int sectorSize; /* Device sector size */
int deviceCharacteristics; /* Precomputed device characteristics */
#endif
#if SQLITE_ENABLE_LOCKING_STYLE
int openFlags; /* The flags specified at open() */
#endif
#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
unsigned fsFlags; /* cached details from statfs() */
#endif
@@ -281,7 +253,8 @@ static int randomnessPid = 0;
#define UNIXFILE_DELETE 0x20 /* Delete on close */
#define UNIXFILE_URI 0x40 /* Filename might have query parameters */
#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings have been issued */
#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() has issued warnings */
#define UNIXFILE_DEFERRED 0x0200 /* File has not yet been opened */
/*
** Include code that is common to all os_*.c files
@@ -1383,9 +1356,14 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
int reserved = 0;
unixFile *pFile = (unixFile*)id;
assert( pFile );
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
assert( pFile );
if( pFile->ctrlFlags & UNIXFILE_DEFERRED ){
*pResOut = 0;
return SQLITE_OK;
}
unixEnterMutex(); /* Because pFile->pInode is shared across threads */
/* Check if a thread in this process holds such a lock */
@@ -1465,6 +1443,21 @@ static int unixFileLock(unixFile *pFile, struct flock *pLock){
return rc;
}
static int unixOpen(sqlite3_vfs*, const char*, sqlite3_file*, int, int *);
static int unixOpenAndLock(unixFile *pFile){
sqlite3_file *id = (sqlite3_file*)pFile;
int eOrigLock = pFile->eFileLock;
int rc;
assert( pFile->ctrlFlags & UNIXFILE_DEFERRED );
rc = unixOpen(pFile->pVfs, pFile->zPath, id, pFile->openFlags, 0);
if( rc==SQLITE_OK && eOrigLock ){
rc = id->pMethods->xLock(id, eOrigLock);
}
return rc;
}
/*
** Lock the file with the lock specified by parameter eFileLock - one
** of the following:
@@ -1549,9 +1542,29 @@ static int unixLock(sqlite3_file *id, int eFileLock){
return SQLITE_OK;
}
if( pFile->ctrlFlags & UNIXFILE_DEFERRED ){
const char *zPath = pFile->zPath; /* Full-path to database file */
int eOrigLock; /* Current lock held on pFile */
assert( pFile->eFileLock==SHARED_LOCK || pFile->eFileLock==NO_LOCK );
/* If SQLite is requesting a SHARED lock and the database file does
** not exist, return early without opening the file. */
if( eFileLock==SHARED_LOCK && osAccess(zPath, F_OK) && errno==ENOENT ){
pFile->eFileLock = SHARED_LOCK;
return SQLITE_OK;
}
/* Or, if the database file has been created or a write lock is
** requested, open the database file now. */
rc = unixOpenAndLock(pFile);
if( rc!=SQLITE_OK ) return rc;
}
assert( (pFile->ctrlFlags & UNIXFILE_DEFERRED)==0 );
/* Make sure the locking sequence is correct.
** (1) We never move from unlocked to anything higher than shared lock.
** (2) SQLite never explicitly requests a pendig lock.
** (2) SQLite never explicitly requests a pending lock.
** (3) A shared lock is always held when a reserve lock is requested.
*/
assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
@@ -1752,6 +1765,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
return SQLITE_OK;
}
unixEnterMutex();
if( pFile->ctrlFlags & UNIXFILE_DEFERRED ) goto end_unlock;
pInode = pFile->pInode;
assert( pInode->nShared!=0 );
if( pFile->eFileLock>SHARED_LOCK ){
@@ -1958,19 +1972,23 @@ static int unixClose(sqlite3_file *id){
unixUnlock(id, NO_LOCK);
unixEnterMutex();
/* unixFile.pInode is always valid here. Otherwise, a different close
** routine (e.g. nolockClose()) would be called instead.
/* unixFile.pInode may be NULL here if the file was never opened.
*/
assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){
/* If there are outstanding locks, do not actually close the file just
** yet because that would clear those locks. Instead, add the file
** descriptor to pInode->pUnused list. It will be automatically closed
** when the last lock is cleared.
*/
setPendingFd(pFile);
assert( pFile->pInode==0
|| pFile->pInode->nLock>0
|| pFile->pInode->bProcessLock==0
);
if( pFile->pInode ){
if( pFile->pInode->nLock ){
/* If there are outstanding locks, do not actually close the file just
** yet because that would clear those locks. Instead, add the file
** descriptor to pInode->pUnused list. It will be automatically closed
** when the last lock is cleared.
*/
setPendingFd(pFile);
}
releaseInodeInfo(pFile);
}
releaseInodeInfo(pFile);
rc = closeUnixFile(id);
unixLeaveMutex();
return rc;
@@ -3199,6 +3217,20 @@ static int unixRead(
);
#endif
if( pFile->ctrlFlags & UNIXFILE_DEFERRED ){
int rc;
if( osAccess(pFile->zPath, F_OK) && errno==ENOENT ){
memset(pBuf, 0, amt);
rc = SQLITE_IOERR_SHORT_READ;
}else{
rc = unixOpen(pFile->pVfs, pFile->zPath, id, pFile->openFlags, 0);
}
if( rc!=SQLITE_OK ){
return rc;
}
}
assert( (pFile->ctrlFlags & UNIXFILE_DEFERRED)==0 );
#if SQLITE_MAX_MMAP_SIZE>0
/* Deal with as much of this read request as possible by transfering
** data from the memory mapping using memcpy(). */
@@ -3303,6 +3335,15 @@ static int unixWrite(
assert( id );
assert( amt>0 );
/* SQLite never actually calls xWrite on an empty file before obtaining
** a RESERVED lock on it. So the following condition is never true if
** the VFS is being used directly by SQLite. But it may be if this module
** is being used in some other way. By the multiplexor VFS, for example. */
if( pFile->ctrlFlags & UNIXFILE_DEFERRED ){
int rc = unixOpenAndLock(pFile);
if( rc!=SQLITE_OK ) return rc;
}
/* If this is a database file (not a journal, master-journal or temp
** file), the bytes in the locking range should never be read or written. */
#if 0
@@ -3651,10 +3692,19 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
** Determine the current size of a file in bytes
*/
static int unixFileSize(sqlite3_file *id, i64 *pSize){
unixFile *pFile = (unixFile*)id;
int rc;
struct stat buf;
assert( id );
rc = osFstat(((unixFile*)id)->h, &buf);
if( pFile->ctrlFlags & UNIXFILE_DEFERRED ){
rc = osStat(pFile->zPath, &buf);
if( rc && errno==ENOENT ){
rc = 0;
buf.st_size = 0;
}
}else{
rc = osFstat(pFile->h, &buf);
}
SimulateIOError( rc=1 );
if( rc!=0 ){
((unixFile*)id)->lastErrno = errno;
@@ -3670,7 +3720,6 @@ static int unixFileSize(sqlite3_file *id, i64 *pSize){
*/
if( *pSize==1 ) *pSize = 0;
return SQLITE_OK;
}
@@ -5202,14 +5251,7 @@ static int fillInUnixFile(
pNew->h = h;
pNew->pVfs = pVfs;
pNew->zPath = zFilename;
pNew->ctrlFlags = (u8)ctrlFlags;
#if SQLITE_MAX_MMAP_SIZE>0
pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
#endif
if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
"psow", SQLITE_POWERSAFE_OVERWRITE) ){
pNew->ctrlFlags |= UNIXFILE_PSOW;
}
pNew->ctrlFlags = (unsigned short)ctrlFlags;
if( strcmp(pVfs->zName,"unix-excl")==0 ){
pNew->ctrlFlags |= UNIXFILE_EXCL;
}
@@ -5348,7 +5390,6 @@ static int fillInUnixFile(
if( h>=0 ) robust_close(pNew, h, __LINE__);
}else{
pNew->pMethod = pLockingStyle;
OpenCounter(+1);
verifyDbFile(pNew);
}
return rc;
@@ -5605,7 +5646,7 @@ static int unixOpen(
int eType = flags&0xFFFFFF00; /* Type of file to open */
int noLock; /* True to omit locking primitives */
int rc = SQLITE_OK; /* Function Return Code */
int ctrlFlags = 0; /* UNIXFILE_* flags */
int ctrlFlags; /* UNIXFILE_* flags */
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
@@ -5635,6 +5676,11 @@ static int unixOpen(
char zTmpname[MAX_PATHNAME+2];
const char *zName = zPath;
assert( p->pInode==0 && (p->h==-1 || p->h==0) );
p->ctrlFlags &= ~UNIXFILE_DEFERRED;
p->eFileLock = NO_LOCK;
ctrlFlags = p->ctrlFlags;
/* Check the following statements are true:
**
** (a) Exactly one of the READWRITE and READONLY flags must be set, and
@@ -5671,7 +5717,6 @@ static int unixOpen(
sqlite3_randomness(0,0);
}
memset(p, 0, sizeof(unixFile));
if( eType==SQLITE_OPEN_MAIN_DB ){
UnixUnusedFd *pUnused;
@@ -5844,10 +5889,69 @@ static int unixOpen(
open_finished:
if( rc!=SQLITE_OK ){
sqlite3_free(p->pUnused);
p->pUnused = 0;
}
return rc;
}
static int unixOpenDeferred(
sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */
const char *zPath, /* Pathname of file to be opened */
sqlite3_file *pFile, /* The file descriptor to be filled in */
int flags, /* Input flags to control the opening */
int *pOutFlags /* Output flags returned to SQLite core */
){
const int mask1 = SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_READWRITE
| SQLITE_OPEN_CREATE;
const int mask2 = SQLITE_OPEN_READONLY | SQLITE_OPEN_DELETEONCLOSE
| SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_AUTOPROXY;
int rc; /* Return code */
unixFile *p = (unixFile*)pFile; /* File object to populate */
const char *zUri = (flags & UNIXFILE_URI) ? zPath : 0;
/* Zero the file object */
memset(p, 0, sizeof(unixFile));
if( sqlite3_uri_boolean(zUri, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
p->ctrlFlags |= UNIXFILE_PSOW;
}
#if SQLITE_MAX_MMAP_SIZE>0
p->mmapSizeMax = sqlite3GlobalConfig.szMmap;
#endif
/* If all the flags in mask1 are set, and all the flags in mask2 are
** clear, the file does not exist but the directory does and is
** writable, then this is a deferred open. */
if( zPath && (flags & (mask1 | mask2))==mask1 ){
int posixrc;
posixrc = osAccess(zPath, F_OK);
if( posixrc && errno==ENOENT ){
char zDirname[MAX_PATHNAME+1];
int i;
for(i=(int)strlen(zPath); i>1 && zPath[i]!='/'; i--);
memcpy(zDirname, zPath, i);
zDirname[i] = '\0';
posixrc = osAccess(zDirname, W_OK);
if( posixrc==0 ){
p->pMethod = (**(finder_type*)pVfs->pAppData)(0, 0);
if( p->pMethod->xLock==unixLock ){
p->pVfs = pVfs;
p->h = -1;
p->ctrlFlags |= UNIXFILE_DEFERRED;
p->openFlags = flags;
p->zPath = zPath;
if( pOutFlags ) *pOutFlags = flags;
OpenCounter(+1);
return SQLITE_OK;
}
}
}
}
rc = unixOpen(pVfs, zPath, pFile, flags, pOutFlags);
OpenCounter( rc==SQLITE_OK );
return rc;
}
/*
** Delete the file at zPath. If the dirSync argument is true, fsync()
@@ -7402,7 +7506,7 @@ int sqlite3_os_init(void){
0, /* pNext */ \
VFSNAME, /* zName */ \
(void*)&FINDER, /* pAppData */ \
unixOpen, /* xOpen */ \
unixOpenDeferred, /* xOpen */ \
unixDelete, /* xDelete */ \
unixAccess, /* xAccess */ \
unixFullPathname, /* xFullPathname */ \
+1 -1
View File
@@ -1683,7 +1683,7 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
** already in memory.
*/
static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
PgHdr *p; /* Return value */
PgHdr *p = 0; /* Return value */
/* It is not possible for a call to PcacheFetch() with createFlag==0 to
** fail, since no attempt to allocate dynamic memory will be made.
+17 -4
View File
@@ -412,13 +412,26 @@ cmd ::= select(X). {
%type oneselect {Select*}
%destructor oneselect {sqlite3SelectDelete(pParse->db, $$);}
select(A) ::= with(W) selectnowith(X). {
if( X ){
X->pWith = W;
select(A) ::= with(W) selectnowith(X). {
Select *p = X, *pNext, *pLoop;
if( p ){
int cnt = 0, mxSelect;
p->pWith = W;
if( p->pPrior ){
pNext = 0;
for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){
pLoop->pNext = pNext;
pLoop->selFlags |= SF_Compound;
}
mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
if( mxSelect && cnt>mxSelect ){
sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
}
}
}else{
sqlite3WithDelete(pParse->db, W);
}
A = X;
A = p;
}
selectnowith(A) ::= oneselect(X). {A = X;}
+77 -121
View File
@@ -109,6 +109,14 @@ void sqlite3SelectDelete(sqlite3 *db, Select *p){
}
}
/*
** Return a pointer to the right-most SELECT statement in a compound.
*/
static Select *findRightmost(Select *p){
while( p->pNext ) p = p->pNext;
return p;
}
/*
** Given 1 to 3 identifiers preceding the JOIN keyword, determine the
** type of join. Return an integer constant that expresses that type
@@ -535,8 +543,8 @@ typedef struct DistinctCtx DistinctCtx;
struct DistinctCtx {
u8 isTnct; /* True if the DISTINCT keyword is present */
u8 eTnctType; /* One of the WHERE_DISTINCT_* operators */
int tabTnct; /* Table containing previously seen values */
int addrTnct; /* Address of OpenEphemeral/OpenHash opcode for tabTnct */
int tabTnct; /* Ephemeral table used for DISTINCT processing */
int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */
};
/*
@@ -765,12 +773,8 @@ static void selectInnerLoop(
}
#endif /* #ifndef SQLITE_OMIT_SUBQUERY */
/* Send the data to the callback function or to a subroutine. In the
** case of a subroutine, the subroutine itself is responsible for
** popping the data from the stack.
*/
case SRT_Coroutine:
case SRT_Output: {
case SRT_Coroutine: /* Send data to a co-routine */
case SRT_Output: { /* Return the results */
testcase( eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
if( pOrderBy ){
@@ -1619,11 +1623,13 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
Vdbe *v = pParse->pVdbe;
if( v==0 ){
v = pParse->pVdbe = sqlite3VdbeCreate(pParse);
#ifndef SQLITE_OMIT_TRACE
if( v ){
sqlite3VdbeAddOp0(v, OP_Trace);
if( v ) sqlite3VdbeAddOp0(v, OP_Init);
if( pParse->pToplevel==0
&& OptimizationEnabled(pParse->db,SQLITE_FactorOutConst)
){
pParse->okConstFactor = 1;
}
#endif
}
return v;
}
@@ -1871,7 +1877,7 @@ static void generateWithRecursiveQuery(
}
VdbeComment((v, "Queue table"));
if( iDistinct ){
p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenHash, iDistinct, 0);
p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
p->selFlags |= SF_UsesEphemeral;
}
@@ -1879,7 +1885,9 @@ static void generateWithRecursiveQuery(
p->pOrderBy = 0;
/* Store the results of the setup-query in Queue. */
pSetup->pNext = 0;
rc = sqlite3Select(pParse, pSetup, &destQueue);
pSetup->pNext = p;
if( rc ) goto end_of_recursive_query;
/* Find the next row in the Queue and output that row */
@@ -1984,8 +1992,6 @@ static int multiSelect(
assert( (p->selFlags & SF_Recursive)==0 || p->op==TK_ALL || p->op==TK_UNION );
db = pParse->db;
pPrior = p->pPrior;
assert( pPrior->pRightmost!=pPrior );
assert( pPrior->pRightmost==p->pRightmost );
dest = *pDest;
if( pPrior->pOrderBy ){
sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before",
@@ -2007,7 +2013,8 @@ static int multiSelect(
*/
if( dest.eDest==SRT_EphemTab ){
assert( p->pEList );
sqlite3VdbeAddOp2(v, OP_OpenHash, dest.iSDParm, p->pEList->nExpr);
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iSDParm, p->pEList->nExpr);
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
dest.eDest = SRT_Table;
}
@@ -2092,12 +2099,10 @@ static int multiSelect(
testcase( p->op==TK_EXCEPT );
testcase( p->op==TK_UNION );
priorOp = SRT_Union;
if( dest.eDest==priorOp && ALWAYS(!p->pLimit &&!p->pOffset) ){
if( dest.eDest==priorOp ){
/* We can reuse a temporary table generated by a SELECT to our
** right.
*/
assert( p->pRightmost!=p ); /* Can only happen for leftward elements
** of a 3-way or more compound */
assert( p->pLimit==0 ); /* Not allowed on leftward elements */
assert( p->pOffset==0 ); /* Not allowed on leftward elements */
unionTab = dest.iSDParm;
@@ -2107,10 +2112,10 @@ static int multiSelect(
*/
unionTab = pParse->nTab++;
assert( p->pOrderBy==0 );
addr = sqlite3VdbeAddOp2(v, OP_OpenHash, unionTab, 0);
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
assert( p->addrOpenEphm[0] == -1 );
p->addrOpenEphm[0] = addr;
p->pRightmost->selFlags |= SF_UsesEphemeral;
findRightmost(p)->selFlags |= SF_UsesEphemeral;
assert( p->pEList );
}
@@ -2190,8 +2195,7 @@ static int multiSelect(
/* INTERSECT is different from the others since it requires
** two temporary tables. Hence it has its own case. Begin
** by allocating the tables we will need. The tables must be
** ordered: Use OP_OpenEphermeral, not OP_OpenHash.
** by allocating the tables we will need.
*/
tab1 = pParse->nTab++;
tab2 = pParse->nTab++;
@@ -2200,7 +2204,7 @@ static int multiSelect(
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);
assert( p->addrOpenEphm[0] == -1 );
p->addrOpenEphm[0] = addr;
p->pRightmost->selFlags |= SF_UsesEphemeral;
findRightmost(p)->selFlags |= SF_UsesEphemeral;
assert( p->pEList );
/* Code the SELECTs to our left into temporary table "tab1".
@@ -2279,7 +2283,7 @@ static int multiSelect(
CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */
int nCol; /* Number of columns in result set */
assert( p->pRightmost==p );
assert( p->pNext==0 );
nCol = p->pEList->nExpr;
pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1);
if( !pKeyInfo ){
@@ -2572,9 +2576,7 @@ static int multiSelectOrderBy(
SelectDest destA; /* Destination for coroutine A */
SelectDest destB; /* Destination for coroutine B */
int regAddrA; /* Address register for select-A coroutine */
int regEofA; /* Flag to indicate when select-A is complete */
int regAddrB; /* Address register for select-B coroutine */
int regEofB; /* Flag to indicate when select-B is complete */
int addrSelectA; /* Address of the select-A coroutine */
int addrSelectB; /* Address of the select-B coroutine */
int regOutA; /* Address register for the output-A subroutine */
@@ -2582,6 +2584,7 @@ static int multiSelectOrderBy(
int addrOutA; /* Address of the output-A subroutine */
int addrOutB = 0; /* Address of the output-B subroutine */
int addrEofA; /* Address of the select-A-exhausted subroutine */
int addrEofA_noB; /* Alternate addrEofA if B is uninitialized */
int addrEofB; /* Address of the select-B-exhausted subroutine */
int addrAltB; /* Address of the A<B subroutine */
int addrAeqB; /* Address of the A==B subroutine */
@@ -2696,6 +2699,7 @@ static int multiSelectOrderBy(
/* Separate the left and the right query from one another
*/
p->pPrior = 0;
pPrior->pNext = 0;
sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
if( pPrior->pPrior==0 ){
sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
@@ -2718,37 +2722,30 @@ static int multiSelectOrderBy(
p->pOffset = 0;
regAddrA = ++pParse->nMem;
regEofA = ++pParse->nMem;
regAddrB = ++pParse->nMem;
regEofB = ++pParse->nMem;
regOutA = ++pParse->nMem;
regOutB = ++pParse->nMem;
sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA);
sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB);
/* Jump past the various subroutines and coroutines to the main
** merge loop
*/
j1 = sqlite3VdbeAddOp0(v, OP_Goto);
addrSelectA = sqlite3VdbeCurrentAddr(v);
/* Generate a coroutine to evaluate the SELECT statement to the
** left of the compound operator - the "A" select.
*/
VdbeNoopComment((v, "Begin coroutine for left SELECT"));
addrSelectA = sqlite3VdbeCurrentAddr(v) + 1;
j1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA);
VdbeComment((v, "left SELECT"));
pPrior->iLimit = regLimitA;
explainSetInteger(iSub1, pParse->iNextSelectId);
sqlite3Select(pParse, pPrior, &destA);
sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
VdbeNoopComment((v, "End coroutine for left SELECT"));
sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrA);
sqlite3VdbeJumpHere(v, j1);
/* Generate a coroutine to evaluate the SELECT statement on
** the right - the "B" select
*/
addrSelectB = sqlite3VdbeCurrentAddr(v);
VdbeNoopComment((v, "Begin coroutine for right SELECT"));
addrSelectB = sqlite3VdbeCurrentAddr(v) + 1;
j1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB);
VdbeComment((v, "right SELECT"));
savedLimit = p->iLimit;
savedOffset = p->iOffset;
p->iLimit = regLimitB;
@@ -2757,9 +2754,7 @@ static int multiSelectOrderBy(
sqlite3Select(pParse, p, &destB);
p->iLimit = savedLimit;
p->iOffset = savedOffset;
sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
VdbeNoopComment((v, "End coroutine for right SELECT"));
sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrB);
/* Generate a subroutine that outputs the current row of the A
** select as the next output row of the compound select.
@@ -2783,13 +2778,12 @@ static int multiSelectOrderBy(
/* Generate a subroutine to run when the results from select A
** are exhausted and only data in select B remains.
*/
VdbeNoopComment((v, "eof-A subroutine"));
if( op==TK_EXCEPT || op==TK_INTERSECT ){
addrEofA = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelEnd);
addrEofA_noB = addrEofA = labelEnd;
}else{
addrEofA = sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd);
sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
VdbeNoopComment((v, "eof-A subroutine"));
addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA);
p->nSelectRow += pPrior->nSelectRow;
}
@@ -2802,9 +2796,8 @@ static int multiSelectOrderBy(
if( p->nSelectRow > pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
}else{
VdbeNoopComment((v, "eof-B subroutine"));
addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB);
}
@@ -2812,8 +2805,7 @@ static int multiSelectOrderBy(
*/
VdbeNoopComment((v, "A-lt-B subroutine"));
addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA);
sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
/* Generate code to handle the case of A==B
@@ -2826,8 +2818,7 @@ static int multiSelectOrderBy(
}else{
VdbeNoopComment((v, "A-eq-B subroutine"));
addrAeqB =
sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA);
sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
}
@@ -2838,19 +2829,14 @@ static int multiSelectOrderBy(
if( op==TK_ALL || op==TK_UNION ){
sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
}
sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB);
sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
/* This code runs once to initialize everything.
*/
sqlite3VdbeJumpHere(v, j1);
sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofA);
sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofB);
sqlite3VdbeAddOp2(v, OP_Gosub, regAddrA, addrSelectA);
sqlite3VdbeAddOp2(v, OP_Gosub, regAddrB, addrSelectB);
sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB);
sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB);
/* Implement the main merge loop
*/
@@ -2879,6 +2865,7 @@ static int multiSelectOrderBy(
sqlite3SelectDelete(db, p->pPrior);
}
p->pPrior = pPrior;
pPrior->pNext = p;
/*** TBD: Insert subroutine calls to close cursors on incomplete
**** subqueries ****/
@@ -3144,7 +3131,7 @@ static int flattenSubquery(
** and (14). */
if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */
if( pSub->pOffset ) return 0; /* Restriction (14) */
if( p->pRightmost && pSub->pLimit ){
if( (p->selFlags & SF_Compound)!=0 && pSub->pLimit ){
return 0; /* Restriction (15) */
}
if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
@@ -3295,14 +3282,14 @@ static int flattenSubquery(
p->pOrderBy = pOrderBy;
p->pSrc = pSrc;
p->op = TK_ALL;
p->pRightmost = 0;
if( pNew==0 ){
pNew = pPrior;
p->pPrior = pPrior;
}else{
pNew->pPrior = pPrior;
pNew->pRightmost = 0;
if( pPrior ) pPrior->pNext = pNew;
pNew->pNext = p;
p->pPrior = pNew;
}
p->pPrior = pNew;
if( db->mallocFailed ) return 1;
}
@@ -3641,6 +3628,10 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
pNew->pHaving = 0;
pNew->pOrderBy = 0;
p->pPrior = 0;
p->pNext = 0;
p->selFlags &= ~SF_Compound;
assert( pNew->pPrior!=0 );
pNew->pPrior->pNext = pNew;
pNew->pLimit = 0;
pNew->pOffset = 0;
return WRC_Continue;
@@ -3828,9 +3819,10 @@ static int withExpand(
*/
static void selectPopWith(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
if( p->pWith ){
assert( pParse->pWith==p->pWith );
pParse->pWith = p->pWith->pOuter;
With *pWith = findRightmost(p)->pWith;
if( pWith!=0 ){
assert( pParse->pWith==pWith );
pParse->pWith = pWith->pOuter;
}
}
#else
@@ -3880,7 +3872,7 @@ static int selectExpander(Walker *pWalker, Select *p){
}
pTabList = p->pSrc;
pEList = p->pEList;
sqlite3WithPush(pParse, p->pWith, 0);
sqlite3WithPush(pParse, findRightmost(p)->pWith, 0);
/* Make sure cursor numbers have been assigned to all entries in
** the FROM clause of the SELECT statement.
@@ -4302,7 +4294,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
pFunc->iDistinct = -1;
}else{
KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0);
sqlite3VdbeAddOp4(v, OP_OpenHash, pFunc->iDistinct, 0, 0,
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
(char*)pKeyInfo, P4_KEYINFO);
}
}
@@ -4558,36 +4550,18 @@ int sqlite3Select(
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
*/
int addrTop;
int addrEof;
int addrTop = sqlite3VdbeCurrentAddr(v)+1;
pItem->regReturn = ++pParse->nMem;
addrEof = ++pParse->nMem;
/* Before coding the OP_Goto to jump to the start of the main routine,
** ensure that the jump to the verify-schema routine has already
** been coded. Otherwise, the verify-schema would likely be coded as
** part of the co-routine. If the main routine then accessed the
** database before invoking the co-routine for the first time (for
** example to initialize a LIMIT register from a sub-select), it would
** be doing so without having verified the schema version and obtained
** the required db locks. See ticket d6b36be38. */
sqlite3CodeVerifySchema(pParse, -1);
sqlite3VdbeAddOp0(v, OP_Goto);
addrTop = sqlite3VdbeAddOp1(v, OP_OpenPseudo, pItem->iCursor);
sqlite3VdbeChangeP5(v, 1);
VdbeComment((v, "coroutine for %s", pItem->pTab->zName));
sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
VdbeComment((v, "%s", pItem->pTab->zName));
pItem->addrFillSub = addrTop;
sqlite3VdbeAddOp2(v, OP_Integer, 0, addrEof);
sqlite3VdbeChangeP5(v, 1);
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
pItem->viaCoroutine = 1;
sqlite3VdbeChangeP2(v, addrTop, dest.iSdst);
sqlite3VdbeChangeP3(v, addrTop, dest.nSdst);
sqlite3VdbeAddOp2(v, OP_Integer, 1, addrEof);
sqlite3VdbeAddOp1(v, OP_Yield, pItem->regReturn);
VdbeComment((v, "end %s", pItem->pTab->zName));
pItem->regResult = dest.iSdst;
sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
sqlite3VdbeJumpHere(v, addrTop-1);
sqlite3ClearTempRegCache(pParse);
}else{
@@ -4603,12 +4577,14 @@ int sqlite3Select(
pItem->regReturn = ++pParse->nMem;
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
pItem->addrFillSub = topAddr+1;
VdbeNoopComment((v, "materialize %s", pItem->pTab->zName));
if( pItem->isCorrelated==0 ){
/* If the subquery is not correlated and if we are not inside of
** a trigger, then we only need to compute the value of the subquery
** once. */
onceAddr = sqlite3CodeOnce(pParse);
VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
}else{
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
}
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
@@ -4640,21 +4616,6 @@ int sqlite3Select(
/* If there is are a sequence of queries, do the earlier ones first.
*/
if( p->pPrior ){
if( p->pRightmost==0 ){
Select *pLoop, *pRight = 0;
int cnt = 0;
int mxSelect;
for(pLoop=p; pLoop; pLoop=pLoop->pPrior, cnt++){
pLoop->pRightmost = p;
pLoop->pNext = pRight;
pRight = pLoop;
}
mxSelect = db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
if( mxSelect && cnt>mxSelect ){
sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
goto select_end;
}
}
rc = multiSelect(pParse, p, pDest);
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
return rc;
@@ -4721,8 +4682,6 @@ int sqlite3Select(
}
/* If the output is destined for a temporary table, open that table.
** Use OP_OpenEphemeral rather than OP_OpenHash to keep the rows in
** their original order.
*/
if( pDest->eDest==SRT_EphemTab ){
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest->iSDParm, pEList->nExpr);
@@ -4742,10 +4701,11 @@ int sqlite3Select(
*/
if( p->selFlags & SF_Distinct ){
sDistinct.tabTnct = pParse->nTab++;
sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenHash,
sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
sDistinct.tabTnct, 0, 0,
(char*)keyInfoFromExprList(pParse, p->pEList, 0),
P4_KEYINFO);
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED;
}else{
sDistinct.eTnctType = WHERE_DISTINCT_NOOP;
@@ -5317,10 +5277,6 @@ void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
sqlite3ExplainPrintf(pVdbe, "(null-select)");
return;
}
while( p->pPrior ){
p->pPrior->pNext = p;
p = p->pPrior;
}
sqlite3ExplainPush(pVdbe);
while( p ){
explainOneSelect(pVdbe, p);
+261 -10
View File
@@ -45,14 +45,17 @@
# include <sys/types.h>
#endif
#ifdef HAVE_EDITLINE
# include <editline/editline.h>
#endif
#if defined(HAVE_READLINE) && HAVE_READLINE==1
#if defined(HAVE_READLINE) && HAVE_READLINE!=0
# include <readline/readline.h>
# include <readline/history.h>
#else
# undef HAVE_READLINE
#endif
#if !defined(HAVE_EDITLINE) && (!defined(HAVE_READLINE) || HAVE_READLINE!=1)
#if defined(HAVE_EDITLINE) && !defined(HAVE_READLINE)
# define HAVE_READLINE 1
# include <editline/readline.h>
#endif
#if !defined(HAVE_READLINE)
# define add_history(X)
# define read_history(X)
# define write_history(X)
@@ -413,7 +416,7 @@ static char *one_input_line(FILE *in, char *zPrior, int isContinuation){
zResult = local_getline(zPrior, in);
}else{
zPrompt = isContinuation ? continuePrompt : mainPrompt;
#if defined(HAVE_READLINE) && HAVE_READLINE==1
#if defined(HAVE_READLINE)
free(zPrior);
zResult = readline(zPrompt);
if( zResult && *zResult ) add_history(zResult);
@@ -1543,6 +1546,7 @@ static int run_schema_dump_query(
static char zHelp[] =
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
".bail ON|OFF Stop after hitting an error. Default OFF\n"
".clone NEWDB Clone data into NEWDB from the existing database\n"
".databases List names and files of attached databases\n"
".dump ?TABLE? ... Dump the database in an SQL text format\n"
" If TABLE specified, only dump tables matching\n"
@@ -1582,6 +1586,7 @@ static char zHelp[] =
".quit Exit this program\n"
".read FILENAME Execute SQL in FILENAME\n"
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
".save FILE Write in-memory database into FILE\n"
".schema ?TABLE? Show the CREATE statements\n"
" If TABLE specified, only show tables matching\n"
" LIKE pattern TABLE.\n"
@@ -1896,6 +1901,219 @@ static char *csv_read_one_field(CSVReader *p){
return p->z;
}
/*
** Try to transfer data for table zTable. If an error is seen while
** moving forward, try to go backwards. The backwards movement won't
** work for WITHOUT ROWID tables.
*/
static void tryToCloneData(
struct callback_data *p,
sqlite3 *newDb,
const char *zTable
){
sqlite3_stmt *pQuery = 0;
sqlite3_stmt *pInsert = 0;
char *zQuery = 0;
char *zInsert = 0;
int rc;
int i, j, n;
int nTable = (int)strlen(zTable);
int k = 0;
int cnt = 0;
const int spinRate = 10000;
zQuery = sqlite3_mprintf("SELECT * FROM \"%w\"", zTable);
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
if( rc ){
fprintf(stderr, "Error %d: %s on [%s]\n",
sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
zQuery);
goto end_data_xfer;
}
n = sqlite3_column_count(pQuery);
zInsert = sqlite3_malloc(200 + nTable + n*3);
if( zInsert==0 ){
fprintf(stderr, "out of memory\n");
goto end_data_xfer;
}
sqlite3_snprintf(200+nTable,zInsert,
"INSERT OR IGNORE INTO \"%s\" VALUES(?", zTable);
i = (int)strlen(zInsert);
for(j=1; j<n; j++){
memcpy(zInsert+i, ",?", 2);
i += 2;
}
memcpy(zInsert+i, ");", 3);
rc = sqlite3_prepare_v2(newDb, zInsert, -1, &pInsert, 0);
if( rc ){
fprintf(stderr, "Error %d: %s on [%s]\n",
sqlite3_extended_errcode(newDb), sqlite3_errmsg(newDb),
zQuery);
goto end_data_xfer;
}
for(k=0; k<2; k++){
while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
for(i=0; i<n; i++){
switch( sqlite3_column_type(pQuery, i) ){
case SQLITE_NULL: {
sqlite3_bind_null(pInsert, i+1);
break;
}
case SQLITE_INTEGER: {
sqlite3_bind_int64(pInsert, i+1, sqlite3_column_int64(pQuery,i));
break;
}
case SQLITE_FLOAT: {
sqlite3_bind_double(pInsert, i+1, sqlite3_column_double(pQuery,i));
break;
}
case SQLITE_TEXT: {
sqlite3_bind_text(pInsert, i+1,
(const char*)sqlite3_column_text(pQuery,i),
-1, SQLITE_STATIC);
break;
}
case SQLITE_BLOB: {
sqlite3_bind_blob(pInsert, i+1, sqlite3_column_blob(pQuery,i),
sqlite3_column_bytes(pQuery,i),
SQLITE_STATIC);
break;
}
}
} /* End for */
rc = sqlite3_step(pInsert);
if( rc!=SQLITE_OK && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
fprintf(stderr, "Error %d: %s\n", sqlite3_extended_errcode(newDb),
sqlite3_errmsg(newDb));
}
sqlite3_reset(pInsert);
cnt++;
if( (cnt%spinRate)==0 ){
printf("%c\b", "|/-\\"[(cnt/spinRate)%4]);
fflush(stdout);
}
} /* End while */
if( rc==SQLITE_DONE ) break;
sqlite3_finalize(pQuery);
sqlite3_free(zQuery);
zQuery = sqlite3_mprintf("SELECT * FROM \"%w\" ORDER BY rowid DESC;",
zTable);
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
if( rc ){
fprintf(stderr, "Warning: cannot step \"%s\" backwards", zTable);
break;
}
} /* End for(k=0...) */
end_data_xfer:
sqlite3_finalize(pQuery);
sqlite3_finalize(pInsert);
sqlite3_free(zQuery);
sqlite3_free(zInsert);
}
/*
** Try to transfer all rows of the schema that match zWhere. For
** each row, invoke xForEach() on the object defined by that row.
** If an error is encountered while moving forward through the
** sqlite_master table, try again moving backwards.
*/
static void tryToCloneSchema(
struct callback_data *p,
sqlite3 *newDb,
const char *zWhere,
void (*xForEach)(struct callback_data*,sqlite3*,const char*)
){
sqlite3_stmt *pQuery = 0;
char *zQuery = 0;
int rc;
const unsigned char *zName;
const unsigned char *zSql;
char *zErrMsg = 0;
zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
" WHERE %s", zWhere);
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
if( rc ){
fprintf(stderr, "Error: (%d) %s on [%s]\n",
sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
zQuery);
goto end_schema_xfer;
}
while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
zName = sqlite3_column_text(pQuery, 0);
zSql = sqlite3_column_text(pQuery, 1);
printf("%s... ", zName); fflush(stdout);
sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
if( zErrMsg ){
fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
sqlite3_free(zErrMsg);
zErrMsg = 0;
}
if( xForEach ){
xForEach(p, newDb, (const char*)zName);
}
printf("done\n");
}
if( rc!=SQLITE_DONE ){
sqlite3_finalize(pQuery);
sqlite3_free(zQuery);
zQuery = sqlite3_mprintf("SELECT name, sql FROM sqlite_master"
" WHERE %s ORDER BY rowid DESC", zWhere);
rc = sqlite3_prepare_v2(p->db, zQuery, -1, &pQuery, 0);
if( rc ){
fprintf(stderr, "Error: (%d) %s on [%s]\n",
sqlite3_extended_errcode(p->db), sqlite3_errmsg(p->db),
zQuery);
goto end_schema_xfer;
}
while( (rc = sqlite3_step(pQuery))==SQLITE_ROW ){
zName = sqlite3_column_text(pQuery, 0);
zSql = sqlite3_column_text(pQuery, 1);
printf("%s... ", zName); fflush(stdout);
sqlite3_exec(newDb, (const char*)zSql, 0, 0, &zErrMsg);
if( zErrMsg ){
fprintf(stderr, "Error: %s\nSQL: [%s]\n", zErrMsg, zSql);
sqlite3_free(zErrMsg);
zErrMsg = 0;
}
if( xForEach ){
xForEach(p, newDb, (const char*)zName);
}
printf("done\n");
}
}
end_schema_xfer:
sqlite3_finalize(pQuery);
sqlite3_free(zQuery);
}
/*
** Open a new database file named "zNewDb". Try to recover as much information
** as possible out of the main database (which might be corrupt) and write it
** into zNewDb.
*/
static void tryToClone(struct callback_data *p, const char *zNewDb){
int rc;
sqlite3 *newDb = 0;
if( access(zNewDb,0)==0 ){
fprintf(stderr, "File \"%s\" already exists.\n", zNewDb);
return;
}
rc = sqlite3_open(zNewDb, &newDb);
if( rc ){
fprintf(stderr, "Cannot create output database: %s\n",
sqlite3_errmsg(newDb));
}else{
sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
tryToCloneSchema(p, newDb, "type!='table'", 0);
sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
}
sqlite3_close(newDb);
}
/*
** If an input line begins with "." then invoke this routine to
** process that line.
@@ -1938,7 +2156,9 @@ static int do_meta_command(char *zLine, struct callback_data *p){
if( nArg==0 ) return 0; /* no tokens, no error */
n = strlen30(azArg[0]);
c = azArg[0][0];
if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 ){
if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
|| (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
){
const char *zDestFile = 0;
const char *zDb = 0;
sqlite3 *pDest;
@@ -2003,6 +2223,10 @@ static int do_meta_command(char *zLine, struct callback_data *p){
test_breakpoint();
}else
if( c=='c' && strncmp(azArg[0], "clone", n)==0 && nArg>1 && nArg<3 ){
tryToClone(p, azArg[1]);
}else
if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 && nArg==1 ){
struct callback_data data;
char *zErrMsg = 0;
@@ -3282,6 +3506,26 @@ static void main_init(struct callback_data *data) {
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
}
/*
** Output text to the console in a font that attracts extra attention.
*/
#ifdef _WIN32
static void printBold(const char *zText){
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
SetConsoleTextAttribute(out,
FOREGROUND_RED|FOREGROUND_INTENSITY
);
printf("%s", zText);
SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
}
#else
static void printBold(const char *zText){
printf("\033[1m%s\033[0m", zText);
}
#endif
/*
** Get the argument to an --option. Throw an error and die if no argument
** is available.
@@ -3302,6 +3546,7 @@ int main(int argc, char **argv){
char *zFirstCmd = 0;
int i;
int rc = 0;
int warnInmemoryDb = 0;
if( strcmp(sqlite3_sourceid(),SQLITE_SOURCE_ID)!=0 ){
fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
@@ -3396,6 +3641,7 @@ int main(int argc, char **argv){
if( data.zDbFilename==0 ){
#ifndef SQLITE_OMIT_MEMORYDB
data.zDbFilename = ":memory:";
warnInmemoryDb = argc==1;
#else
fprintf(stderr,"%s: Error: no database filename specified\n", Argv0);
return 1;
@@ -3532,10 +3778,15 @@ int main(int argc, char **argv){
int nHistory;
printf(
"SQLite version %s %.19s\n" /*extra-version-info*/
"Enter \".help\" for instructions\n"
"Enter SQL statements terminated with a \";\"\n",
"Enter \".help\" for usage hints.\n",
sqlite3_libversion(), sqlite3_sourceid()
);
if( warnInmemoryDb ){
printf("Connected to a ");
printBold("transient in-memory database.");
printf("\nUse \".open FILENAME\" to reopen on a "
"persistent database.\n");
}
zHome = find_home_dir();
if( zHome ){
nHistory = strlen30(zHome) + 20;
@@ -3543,7 +3794,7 @@ int main(int argc, char **argv){
sqlite3_snprintf(nHistory, zHistory,"%s/.sqlite_history", zHome);
}
}
#if defined(HAVE_READLINE) && HAVE_READLINE==1
#if defined(HAVE_READLINE)
if( zHistory ) read_history(zHistory);
#endif
rc = process_input(&data, 0);
+11 -5
View File
@@ -33,6 +33,11 @@
** in Red Hat 6.0, so the code won't work. Hence, for maximum binary
** portability you should omit LFS.
**
** The previous paragraph was written in 2005. (This paragraph is written
** on 2008-11-28.) These days, all Linux kernels support large files, so
** you should probably leave LFS enabled. But some embedded platforms might
** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
**
** Similar is true for Mac OS X. LFS is only supported on Mac OS X 9 and later.
*/
#ifndef SQLITE_DISABLE_LFS
@@ -1083,8 +1088,7 @@ struct sqlite3 {
** Return true if it OK to factor constant expressions into the initialization
** code. The argument is a Parse object for the code generator.
*/
#define ConstFactorOk(P) \
((P)->cookieGoto>0 && OptimizationEnabled((P)->db,SQLITE_FactorOutConst))
#define ConstFactorOk(P) ((P)->okConstFactor)
/*
** Possible values for the sqlite.magic field.
@@ -2015,6 +2019,7 @@ struct SrcList {
Select *pSelect; /* A SELECT statement used in place of a table name */
int addrFillSub; /* Address of subroutine to manifest a subquery */
int regReturn; /* Register holding return address of addrFillSub */
int regResult; /* Registers holding results of a co-routine */
u8 jointype; /* Type of join between this able and the previous */
unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
unsigned isCorrelated :1; /* True if sub-query is correlated */
@@ -2143,7 +2148,6 @@ struct Select {
ExprList *pOrderBy; /* The ORDER BY clause */
Select *pPrior; /* Prior select in a compound select statement */
Select *pNext; /* Next select to the left in a compound */
Select *pRightmost; /* Right-most select in a compound select statement */
Expr *pLimit; /* LIMIT expression. NULL means not used. */
Expr *pOffset; /* OFFSET expression. NULL means not used. */
With *pWith; /* WITH clause attached to this select. Or NULL. */
@@ -2165,6 +2169,7 @@ struct Select {
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */
#define SF_Compound 0x1000 /* Part of a compound query */
/*
@@ -2349,6 +2354,7 @@ struct Parse {
u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
u8 mayAbort; /* True if statement may throw an ABORT exception */
u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
u8 okConstFactor; /* OK to factor out constants */
int aTempReg[8]; /* Holding area for temporary registers */
int nRangeReg; /* Size of the temporary register block */
int iRangeReg; /* First register in temporary register block */
@@ -2377,7 +2383,6 @@ struct Parse {
Token constraintName;/* Name of the constraint currently being parsed */
yDbMask writeMask; /* Start a write transaction on these databases */
yDbMask cookieMask; /* Bitmask of schema verified databases */
int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */
int regRowid; /* Register holding rowid of CREATE TABLE entry */
int regRoot; /* Register holding root page number for new objects */
@@ -3283,6 +3288,7 @@ void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
int sqlite3GetToken(const unsigned char *, int *);
void sqlite3NestedParse(Parse*, const char*, ...);
void sqlite3ExpirePreparedStatements(sqlite3*);
int sqlite3CodeSubselect(Parse *, Expr *, int, int);
void sqlite3SelectPrep(Parse*, Select*, NameContext*);
int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
int sqlite3ResolveExprNames(NameContext*, Expr*);
@@ -3478,7 +3484,7 @@ const char *sqlite3JournalModename(int);
#define IN_INDEX_EPH 2
#define IN_INDEX_INDEX_ASC 3
#define IN_INDEX_INDEX_DESC 4
int sqlite3FindInIndex(Parse *, Expr *, int*, int);
int sqlite3FindInIndex(Parse *, Expr *, int*);
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
+37 -32
View File
@@ -1025,7 +1025,7 @@ static int DbTransPostCmd(
** this method's logic. Not clear how this would be best handled.
*/
if( rc!=TCL_ERROR ){
Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0);
Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
rc = TCL_ERROR;
}
sqlite3_exec(pDb->db, "ROLLBACK", 0, 0, 0);
@@ -1675,7 +1675,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
*/
case DB_AUTHORIZER: {
#ifdef SQLITE_OMIT_AUTHORIZATION
Tcl_AppendResult(interp, "authorization not available in this build", 0);
Tcl_AppendResult(interp, "authorization not available in this build",
(char*)0);
return TCL_ERROR;
#else
if( objc>3 ){
@@ -1683,7 +1684,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
return TCL_ERROR;
}else if( objc==2 ){
if( pDb->zAuth ){
Tcl_AppendResult(interp, pDb->zAuth, 0);
Tcl_AppendResult(interp, pDb->zAuth, (char*)0);
}
}else{
char *zAuth;
@@ -1769,7 +1770,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
return TCL_ERROR;
}else if( objc==2 ){
if( pDb->zBusy ){
Tcl_AppendResult(interp, pDb->zBusy, 0);
Tcl_AppendResult(interp, pDb->zBusy, (char*)0);
}
}else{
char *zBusy;
@@ -1823,7 +1824,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
}else{
if( TCL_ERROR==Tcl_GetIntFromObj(interp, objv[3], &n) ){
Tcl_AppendResult( interp, "cannot convert \"",
Tcl_GetStringFromObj(objv[3],0), "\" to integer", 0);
Tcl_GetStringFromObj(objv[3],0), "\" to integer", (char*)0);
return TCL_ERROR;
}else{
if( n<0 ){
@@ -1837,7 +1838,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
}
}else{
Tcl_AppendResult( interp, "bad option \"",
Tcl_GetStringFromObj(objv[2],0), "\": must be flush or size", 0);
Tcl_GetStringFromObj(objv[2],0), "\": must be flush or size",
(char*)0);
return TCL_ERROR;
}
break;
@@ -1934,7 +1936,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
return TCL_ERROR;
}else if( objc==2 ){
if( pDb->zCommit ){
Tcl_AppendResult(interp, pDb->zCommit, 0);
Tcl_AppendResult(interp, pDb->zCommit, (char*)0);
}
}else{
const char *zCommit;
@@ -2039,7 +2041,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
nSep = strlen30(zSep);
nNull = strlen30(zNull);
if( nSep==0 ){
Tcl_AppendResult(interp,"Error: non-null separator required for copy",0);
Tcl_AppendResult(interp,"Error: non-null separator required for copy",
(char*)0);
return TCL_ERROR;
}
if(strcmp(zConflict, "rollback") != 0 &&
@@ -2049,19 +2052,19 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
strcmp(zConflict, "replace" ) != 0 ) {
Tcl_AppendResult(interp, "Error: \"", zConflict,
"\", conflict-algorithm must be one of: rollback, "
"abort, fail, ignore, or replace", 0);
"abort, fail, ignore, or replace", (char*)0);
return TCL_ERROR;
}
zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
if( zSql==0 ){
Tcl_AppendResult(interp, "Error: no such table: ", zTable, 0);
Tcl_AppendResult(interp, "Error: no such table: ", zTable, (char*)0);
return TCL_ERROR;
}
nByte = strlen30(zSql);
rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( rc ){
Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);
Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0);
nCol = 0;
}else{
nCol = sqlite3_column_count(pStmt);
@@ -2072,7 +2075,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
}
zSql = malloc( nByte + 50 + nCol*2 );
if( zSql==0 ) {
Tcl_AppendResult(interp, "Error: can't malloc()", 0);
Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0);
return TCL_ERROR;
}
sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?",
@@ -2087,7 +2090,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
free(zSql);
if( rc ){
Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);
Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0);
sqlite3_finalize(pStmt);
return TCL_ERROR;
}
@@ -2099,7 +2102,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
}
azCol = malloc( sizeof(azCol[0])*(nCol+1) );
if( azCol==0 ) {
Tcl_AppendResult(interp, "Error: can't malloc()", 0);
Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0);
fclose(in);
return TCL_ERROR;
}
@@ -2127,7 +2130,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
sqlite3_snprintf(nErr, zErr,
"Error: %s line %d: expected %d columns of data but found %d",
zFile, lineno, nCol, i+1);
Tcl_AppendResult(interp, zErr, 0);
Tcl_AppendResult(interp, zErr, (char*)0);
free(zErr);
}
zCommit = "ROLLBACK";
@@ -2147,7 +2150,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
rc = sqlite3_reset(pStmt);
free(zLine);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), 0);
Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), (char*)0);
zCommit = "ROLLBACK";
break;
}
@@ -2165,7 +2168,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
}else{
/* failure, append lineno where failed */
sqlite3_snprintf(sizeof(zLineNum), zLineNum,"%d",lineno);
Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,0);
Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,
(char*)0);
rc = TCL_ERROR;
}
break;
@@ -2191,7 +2195,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
break;
#else
Tcl_AppendResult(interp, "extension loading is turned off at compile-time",
0);
(char*)0);
return TCL_ERROR;
#endif
}
@@ -2349,7 +2353,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
*/
case DB_INCRBLOB: {
#ifdef SQLITE_OMIT_INCRBLOB
Tcl_AppendResult(interp, "incrblob not available in this build", 0);
Tcl_AppendResult(interp, "incrblob not available in this build", (char*)0);
return TCL_ERROR;
#else
int isReadonly = 0;
@@ -2456,7 +2460,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
case DB_PROGRESS: {
if( objc==2 ){
if( pDb->zProgress ){
Tcl_AppendResult(interp, pDb->zProgress, 0);
Tcl_AppendResult(interp, pDb->zProgress, (char*)0);
}
}else if( objc==4 ){
char *zProgress;
@@ -2502,7 +2506,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
return TCL_ERROR;
}else if( objc==2 ){
if( pDb->zProfile ){
Tcl_AppendResult(interp, pDb->zProfile, 0);
Tcl_AppendResult(interp, pDb->zProfile, (char*)0);
}
}else{
char *zProfile;
@@ -2547,7 +2551,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
rc = sqlite3_rekey(pDb->db, pKey, nKey);
if( rc ){
Tcl_AppendResult(interp, sqlite3_errstr(rc), 0);
Tcl_AppendResult(interp, sqlite3_errstr(rc), (char*)0);
rc = TCL_ERROR;
}
#endif
@@ -2688,7 +2692,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
return TCL_ERROR;
}else if( objc==2 ){
if( pDb->zTrace ){
Tcl_AppendResult(interp, pDb->zTrace, 0);
Tcl_AppendResult(interp, pDb->zTrace, (char*)0);
}
}else{
char *zTrace;
@@ -2759,7 +2763,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
rc = sqlite3_exec(pDb->db, zBegin, 0, 0, 0);
pDb->disableAuth--;
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0);
Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
return TCL_ERROR;
}
pDb->nTransaction++;
@@ -2783,7 +2787,8 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
*/
case DB_UNLOCK_NOTIFY: {
#ifndef SQLITE_ENABLE_UNLOCK_NOTIFY
Tcl_AppendResult(interp, "unlock_notify not available in this build", 0);
Tcl_AppendResult(interp, "unlock_notify not available in this build",
(char*)0);
rc = TCL_ERROR;
#else
if( objc!=2 && objc!=3 ){
@@ -2806,7 +2811,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
}
if( sqlite3_unlock_notify(pDb->db, xNotify, pNotifyArg) ){
Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), 0);
Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
rc = TCL_ERROR;
}
}
@@ -2935,14 +2940,14 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
if( objc==2 ){
zArg = Tcl_GetStringFromObj(objv[1], 0);
if( strcmp(zArg,"-version")==0 ){
Tcl_AppendResult(interp,sqlite3_libversion(),0);
Tcl_AppendResult(interp,sqlite3_libversion(), (char*)0);
return TCL_OK;
}
if( strcmp(zArg,"-has-codec")==0 ){
#ifdef SQLITE_HAS_CODEC
Tcl_AppendResult(interp,"1",0);
Tcl_AppendResult(interp,"1",(char*)0);
#else
Tcl_AppendResult(interp,"0",0);
Tcl_AppendResult(interp,"0",(char*)0);
#endif
return TCL_OK;
}
@@ -3424,7 +3429,7 @@ static int md5_cmd(void*cd, Tcl_Interp *interp, int argc, const char **argv){
if( argc!=2 ){
Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
" TEXT\"", 0);
" TEXT\"", (char*)0);
return TCL_ERROR;
}
MD5Init(&ctx);
@@ -3449,13 +3454,13 @@ static int md5file_cmd(void*cd, Tcl_Interp*interp, int argc, const char **argv){
if( argc!=2 ){
Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
" FILENAME\"", 0);
" FILENAME\"", (char*)0);
return TCL_ERROR;
}
in = fopen(argv[1],"rb");
if( in==0 ){
Tcl_AppendResult(interp,"unable to open file \"", argv[1],
"\" for reading", 0);
"\" for reading", (char*)0);
return TCL_ERROR;
}
MD5Init(&ctx);
+3
View File
@@ -534,7 +534,10 @@ static int fake_big_file(
}
offset = n;
offset *= 1024*1024;
sqlite3OsLock(fd, SHARED_LOCK);
sqlite3OsLock(fd, EXCLUSIVE_LOCK);
rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset);
sqlite3OsUnlock(fd, NO_LOCK);
sqlite3OsCloseFree(fd);
sqlite3_free(zFile);
if( rc ){
+1 -1
View File
@@ -76,7 +76,7 @@ static int test_value_overhead(
val.flags = MEM_Str|MEM_Term|MEM_Static;
val.z = "hello world";
val.type = SQLITE_TEXT;
val.memType = MEM_Str;
val.enc = SQLITE_UTF8;
for(i=0; i<repeat_count; i++){
+1 -9
View File
@@ -726,15 +726,7 @@ static int codeTriggerProgram(
** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy
*/
pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf;
/* Clear the cookieGoto flag. When coding triggers, the cookieGoto
** variable is used as a flag to indicate to sqlite3ExprCodeConstants()
** that it is not safe to refactor constants (this happens after the
** start of the first loop in the SQL statement is coded - at that
** point code may be conditionally executed, so it is no longer safe to
** initialize constant register values). */
assert( pParse->cookieGoto==0 || pParse->cookieGoto==-1 );
pParse->cookieGoto = 0;
assert( pParse->okConstFactor==0 );
switch( pStep->op ){
case TK_UPDATE: {
+2 -1
View File
@@ -735,7 +735,8 @@ static void updateVirtualTable(
*/
assert( v );
ephemTab = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_OpenHash, ephemTab, pTab->nCol+1+(pRowid!=0));
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
/* fill the ephemeral table
*/
+13 -5
View File
@@ -1123,13 +1123,12 @@ int sqlite3AddInt64(i64 *pA, i64 iB){
testcase( iA>0 && LARGEST_INT64 - iA == iB );
testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 );
if( iA>0 && LARGEST_INT64 - iA < iB ) return 1;
*pA += iB;
}else{
testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 );
testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 );
if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
*pA += iB;
}
*pA += iB;
return 0;
}
int sqlite3SubInt64(i64 *pA, i64 iB){
@@ -1153,9 +1152,18 @@ int sqlite3MulInt64(i64 *pA, i64 iB){
iA0 = iA % TWOPOWER32;
iB1 = iB/TWOPOWER32;
iB0 = iB % TWOPOWER32;
if( iA1*iB1 != 0 ) return 1;
assert( iA1*iB0==0 || iA0*iB1==0 );
r = iA1*iB0 + iA0*iB1;
if( iA1==0 ){
if( iB1==0 ){
*pA *= iB;
return 0;
}
r = iA0*iB1;
}else if( iB1==0 ){
r = iA1*iB0;
}else{
/* If both iA1 and iB1 are non-zero, overflow will result */
return 1;
}
testcase( r==(-TWOPOWER31)-1 );
testcase( r==(-TWOPOWER31) );
testcase( r==TWOPOWER31 );
+197 -244
View File
@@ -9,33 +9,8 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** The code in this file implements execution method of the
** Virtual Database Engine (VDBE). A separate file ("vdbeaux.c")
** handles housekeeping details such as creating and deleting
** VDBE instances. This file is solely interested in executing
** the VDBE program.
**
** In the external interface, an "sqlite3_stmt*" is an opaque pointer
** to a VDBE.
**
** The SQL parser generates a program which is then executed by
** the VDBE to do the work of the SQL statement. VDBE programs are
** similar in form to assembly language. The program consists of
** a linear sequence of operations. Each operation has an opcode
** and 5 operands. Operands P1, P2, and P3 are integers. Operand P4
** is a null-terminated string. Operand P5 is an unsigned character.
** Few opcodes use all 5 operands.
**
** Computation results are stored on a set of registers numbered beginning
** with 1 and going up to Vdbe.nMem. Each register can store
** either an integer, a null-terminated string, a floating point
** number, or the SQL "NULL" value. An implicit conversion from one
** type to the other occurs as necessary.
**
** Most of the code in this file is taken up by the sqlite3VdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
** The code in this file implements the function that runs the
** bytecode of a prepared statement.
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files. The formatting
@@ -49,7 +24,11 @@
/*
** Invoke this macro on memory cells just prior to changing the
** value of the cell. This macro verifies that shallow copies are
** not misused.
** not misused. A shallow copy of a string or blob just copies a
** pointer to the string or blob, not the content. If the original
** is changed while the copy is still in use, the string or blob might
** be changed out from under the copy. This macro verifies that nothing
** like that every happens.
*/
#ifdef SQLITE_DEBUG
# define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M)
@@ -108,7 +87,7 @@ static void updateMaxBlobsize(Mem *p){
#endif
/*
** The next global variable is incremented each type the OP_Found opcode
** The next global variable is incremented each time the OP_Found opcode
** is executed. This is used to test whether or not the foreign key
** operation implemented using OP_FkIsZero is working. This variable
** has no function other than to help verify the correct operation of the
@@ -152,31 +131,7 @@ int sqlite3_found_count = 0;
&& sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
/* Return true if the cursor was opened using the OP_OpenSorter opcode. */
# define isSorter(x) ((x)->pSorter!=0)
/*
** Argument pMem points at a register that will be passed to a
** user-defined function or returned to the user as the result of a query.
** This routine sets the pMem->type variable used by the sqlite3_value_*()
** routines.
*/
void sqlite3VdbeMemStoreType(Mem *pMem){
int flags = pMem->flags;
if( flags & MEM_Null ){
pMem->type = SQLITE_NULL;
}
else if( flags & MEM_Int ){
pMem->type = SQLITE_INTEGER;
}
else if( flags & MEM_Real ){
pMem->type = SQLITE_FLOAT;
}
else if( flags & MEM_Str ){
pMem->type = SQLITE_TEXT;
}else{
pMem->type = SQLITE_BLOB;
}
}
#define isSorter(x) ((x)->pSorter!=0)
/*
** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL
@@ -306,12 +261,14 @@ static void applyAffinity(
** loss of information and return the revised type of the argument.
*/
int sqlite3_value_numeric_type(sqlite3_value *pVal){
Mem *pMem = (Mem*)pVal;
if( pMem->type==SQLITE_TEXT ){
int eType = sqlite3_value_type(pVal);
if( eType==SQLITE_TEXT ){
Mem *pMem = (Mem*)pVal;
applyNumericAffinity(pMem);
sqlite3VdbeMemStoreType(pMem);
eType = sqlite3_value_type(pVal);
}
return pMem->type;
return eType;
}
/*
@@ -414,7 +371,7 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
** Print the value of a register for tracing purposes:
*/
static void memTracePrint(Mem *p){
if( p->flags & MEM_Invalid ){
if( p->flags & MEM_Undefined ){
printf(" undefined");
}else if( p->flags & MEM_Null ){
printf(" NULL");
@@ -458,20 +415,6 @@ static void registerTrace(int iReg, Mem *p){
#endif
/*
** The CHECK_FOR_INTERRUPT macro defined here looks to see if the
** sqlite3_interrupt() routine has been called. If it has been, then
** processing of the VDBE program is interrupted.
**
** This macro added to every instruction that does a jump in order to
** implement a loop. This test used to be on every single instruction,
** but that meant we more testing than we needed. By only testing the
** flag on jump instructions, we get a (small) speed improvement.
*/
#define CHECK_FOR_INTERRUPT \
if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
#ifndef NDEBUG
/*
** This function is only called from within an assert() expression. It
@@ -494,35 +437,8 @@ static int checkSavepointCount(sqlite3 *db){
/*
** Execute as much of a VDBE program as we can then return.
**
** sqlite3VdbeMakeReady() must be called before this routine in order to
** close the program with a final OP_Halt and to set up the callbacks
** and the error message pointer.
**
** Whenever a row or result data is available, this routine will either
** invoke the result callback (if there is one) or return with
** SQLITE_ROW.
**
** If an attempt is made to open a locked database, then this routine
** will either invoke the busy callback (if there is one) or it will
** return SQLITE_BUSY.
**
** If an error occurs, an error message is written to memory obtained
** from sqlite3_malloc() and p->zErrMsg is made to point to that memory.
** The error code is stored in p->rc and this routine returns SQLITE_ERROR.
**
** If the callback ever returns non-zero, then the program exits
** immediately. There will be no error message but the p->rc field is
** set to SQLITE_ABORT and this routine will return SQLITE_ERROR.
**
** A memory allocation error causes p->rc to be set to SQLITE_NOMEM and this
** routine to return SQLITE_ERROR.
**
** Other fatal errors return SQLITE_ERROR.
**
** After this routine has finished, sqlite3VdbeFinalize() should be
** used to clean up the mess that was left behind.
** Execute as much of a VDBE program as we can.
** This is the core of sqlite3_step().
*/
int sqlite3VdbeExec(
Vdbe *p /* The VDBE */
@@ -566,7 +482,7 @@ int sqlite3VdbeExec(
assert( p->explain==0 );
p->pResultSet = 0;
db->busyHandler.nBusy = 0;
CHECK_FOR_INTERRUPT;
if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
sqlite3VdbeIOTraceSql(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
if( db->xProgress ){
@@ -742,7 +658,7 @@ case OP_Goto: { /* jump */
** checks on every opcode. This helps sqlite3_step() to run about 1.5%
** faster according to "valgrind --tool=cachegrind" */
check_for_interrupt:
CHECK_FOR_INTERRUPT;
if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/* Call the progress callback if it is configured and the required number
** of VDBE ops have been executed (either since this invocation of
@@ -782,20 +698,66 @@ case OP_Gosub: { /* jump */
/* Opcode: Return P1 * * * *
**
** Jump to the next instruction after the address in register P1.
** Jump to the next instruction after the address in register P1. After
** the jump, register P1 becomes undefined.
*/
case OP_Return: { /* in1 */
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags & MEM_Int );
assert( pIn1->flags==MEM_Int );
pc = (int)pIn1->u.i;
pIn1->flags = MEM_Undefined;
break;
}
/* Opcode: Yield P1 * * * *
/* Opcode: InitCoroutine P1 P2 P3 * *
**
** Set up register P1 so that it will OP_Yield to the co-routine
** located at address P3.
**
** If P2!=0 then the co-routine implementation immediately follows
** this opcode. So jump over the co-routine implementation to
** address P2.
*/
case OP_InitCoroutine: { /* jump */
assert( pOp->p1>0 && pOp->p1<=(p->nMem-p->nCursor) );
assert( pOp->p2>=0 && pOp->p2<p->nOp );
assert( pOp->p3>=0 && pOp->p3<p->nOp );
pOut = &aMem[pOp->p1];
assert( !VdbeMemDynamic(pOut) );
pOut->u.i = pOp->p3 - 1;
pOut->flags = MEM_Int;
if( pOp->p2 ) pc = pOp->p2 - 1;
break;
}
/* Opcode: EndCoroutine P1 * * * *
**
** The instruction at the address in register P1 is an OP_Yield.
** Jump to the P2 parameter of that OP_Yield.
** After the jump, register P1 becomes undefined.
*/
case OP_EndCoroutine: { /* in1 */
VdbeOp *pCaller;
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags==MEM_Int );
assert( pIn1->u.i>=0 && pIn1->u.i<p->nOp );
pCaller = &aOp[pIn1->u.i];
assert( pCaller->opcode==OP_Yield );
assert( pCaller->p2>=0 && pCaller->p2<p->nOp );
pc = pCaller->p2 - 1;
pIn1->flags = MEM_Undefined;
break;
}
/* Opcode: Yield P1 P2 * * *
**
** Swap the program counter with the value in register P1.
**
** If the co-routine ends with OP_Yield or OP_Return then continue
** to the next instruction. But if the co-routine ends with
** OP_EndCoroutine, jump immediately to P2.
*/
case OP_Yield: { /* in1 */
case OP_Yield: { /* in1, jump */
int pcDest;
pIn1 = &aMem[pOp->p1];
assert( (pIn1->flags & MEM_Dyn)==0 );
@@ -808,7 +770,7 @@ case OP_Yield: { /* in1 */
}
/* Opcode: HaltIfNull P1 P2 P3 P4 P5
** Synopsis: if r[P3] null then halt
** Synopsis: if r[P3]=null halt
**
** Check the value in register P3. If it is NULL then Halt using
** parameter P1, P2, and P4 as if this were a Halt instruction. If the
@@ -956,7 +918,9 @@ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
** Synopsis: r[P2]='P4'
**
** P4 points to a nul terminated UTF-8 string. This opcode is transformed
** into an OP_String before it is executed for the first time.
** into an OP_String before it is executed for the first time. During
** this transformation, the length of string P4 is computed and stored
** as the P1 parameter.
*/
case OP_String8: { /* same as TK_STRING, out2-prerelease */
assert( pOp->p4.z!=0 );
@@ -1031,7 +995,7 @@ case OP_Null: { /* out2-prerelease */
}
/* Opcode: Blob P1 P2 * P4
/* Opcode: Blob P1 P2 * P4 *
** Synopsis: r[P2]=P4 (len=P1)
**
** P4 points to a blob of data P1 bytes long. Store this
@@ -1050,7 +1014,7 @@ case OP_Blob: { /* out2-prerelease */
**
** Transfer the values of bound parameter P1 into register P2
**
** If the parameter is named, then its name appears in P4 and P3==1.
** If the parameter is named, then its name appears in P4.
** The P4 value is used by sqlite3_bind_parameter_name().
*/
case OP_Variable: { /* out2-prerelease */
@@ -1169,8 +1133,8 @@ case OP_SCopy: { /* out2 */
** The registers P1 through P1+P2-1 contain a single row of
** results. This opcode causes the sqlite3_step() call to terminate
** with an SQLITE_ROW return code and it sets up the sqlite3_stmt
** structure to provide access to the top P1 values as the result
** row.
** structure to provide access to the r[P1]..r[P1+P2-1] values as
** the result row.
*/
case OP_ResultRow: {
Mem *pMem;
@@ -1698,7 +1662,7 @@ case OP_RealAffinity: { /* in1 */
**
** Force the value in register P1 to be text.
** If the value is numeric, convert it to a string using the
** equivalent of printf(). Blob values are unchanged and
** equivalent of sprintf(). Blob values are unchanged and
** are afterwards simply interpreted as text.
**
** A NULL value is not changed by this routine. It remains NULL.
@@ -2153,7 +2117,9 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
/* Opcode: Once P1 P2 * * *
**
** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
** set the flag and fall through to the next instruction.
** set the flag and fall through to the next instruction. In other words,
** this opcode causes all following up codes up through P2 (but not including
** P2) to run just once and skipped on subsequent times through the loop.
*/
case OP_Once: { /* jump */
assert( pOp->p1<p->nOnceFlag );
@@ -2293,11 +2259,6 @@ case OP_Column: {
if( pCrsr==0 ){
assert( pC->pseudoTableReg>0 );
pReg = &aMem[pC->pseudoTableReg];
if( pC->multiPseudo ){
sqlite3VdbeMemShallowCopy(pDest, pReg+p2, MEM_Ephem);
Deephemeralize(pDest);
goto op_column_out;
}
assert( pReg->flags & MEM_Blob );
assert( memIsValid(pReg) );
pC->payloadSize = pC->szRow = avail = pReg->n;
@@ -2946,7 +2907,7 @@ case OP_AutoCommit: {
break;
}
/* Opcode: Transaction P1 P2 * * *
/* Opcode: Transaction P1 P2 P3 P4 P5
**
** Begin a transaction. The transaction ends when a Commit or Rollback
** opcode is encountered. Depending on the ON CONFLICT setting, the
@@ -2976,9 +2937,17 @@ case OP_AutoCommit: {
** will automatically commit when the VDBE halts.
**
** If P2 is zero, then a read-lock is obtained on the database file.
**
** If P5!=0 then this opcode also checks the schema cookie against P3
** and the schema generation counter against P4.
** The cookie changes its value whenever the database schema changes.
** This operation is used to detect when that the cookie has changed
** and that the current process needs to reread the schema.
*/
case OP_Transaction: {
Btree *pBt;
int iMeta;
int iGen;
assert( p->bIsReader );
assert( p->readOnly==0 || pOp->p2==0 );
@@ -3022,6 +2991,35 @@ case OP_Transaction: {
p->nStmtDefCons = db->nDeferredCons;
p->nStmtDefImmCons = db->nDeferredImmCons;
}
/* Gather the schema version number for checking */
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
iGen = db->aDb[pOp->p1].pSchema->iGeneration;
}else{
iGen = iMeta = 0;
}
assert( pOp->p5==0 || pOp->p4type==P4_INT32 );
if( pOp->p5 && (iMeta!=pOp->p3 || iGen!=pOp->p4.i) ){
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
/* If the schema-cookie from the database file matches the cookie
** stored with the in-memory representation of the schema, do
** not reload the schema from the database file.
**
** If virtual-tables are in use, this is not just an optimization.
** Often, v-tables store their data in other SQLite tables, which
** are queried from within xNext() and other v-table methods using
** prepared queries. If such a query is out-of-date, we do not want to
** discard the database schema, as the user code implementing the
** v-table would have to be ready for the sqlite3_vtab structure itself
** to be invalidated whenever sqlite3_step() is called from within
** a v-table method.
*/
if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
sqlite3ResetOneSchema(db, pOp->p1);
}
p->expired = 1;
rc = SQLITE_SCHEMA;
}
break;
}
@@ -3096,66 +3094,6 @@ case OP_SetCookie: { /* in3 */
break;
}
/* Opcode: VerifyCookie P1 P2 P3 * *
**
** Check the value of global database parameter number 0 (the
** schema version) and make sure it is equal to P2 and that the
** generation counter on the local schema parse equals P3.
**
** P1 is the database number which is 0 for the main database file
** and 1 for the file holding temporary tables and some higher number
** for auxiliary databases.
**
** The cookie changes its value whenever the database schema changes.
** This operation is used to detect when that the cookie has changed
** and that the current process needs to reread the schema.
**
** Either a transaction needs to have been started or an OP_Open needs
** to be executed (to establish a read lock) before this opcode is
** invoked.
*/
case OP_VerifyCookie: {
int iMeta;
int iGen;
Btree *pBt;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (((yDbMask)1)<<pOp->p1))!=0 );
assert( sqlite3SchemaMutexHeld(db, pOp->p1, 0) );
assert( p->bIsReader );
pBt = db->aDb[pOp->p1].pBt;
if( pBt ){
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
iGen = db->aDb[pOp->p1].pSchema->iGeneration;
}else{
iGen = iMeta = 0;
}
if( iMeta!=pOp->p2 || iGen!=pOp->p3 ){
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
/* If the schema-cookie from the database file matches the cookie
** stored with the in-memory representation of the schema, do
** not reload the schema from the database file.
**
** If virtual-tables are in use, this is not just an optimization.
** Often, v-tables store their data in other SQLite tables, which
** are queried from within xNext() and other v-table methods using
** prepared queries. If such a query is out-of-date, we do not want to
** discard the database schema, as the user code implementing the
** v-table would have to be ready for the sqlite3_vtab structure itself
** to be invalidated whenever sqlite3_step() is called from within
** a v-table method.
*/
if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
sqlite3ResetOneSchema(db, pOp->p1);
}
p->expired = 1;
rc = SQLITE_SCHEMA;
}
break;
}
/* Opcode: OpenRead P1 P2 P3 P4 P5
** Synopsis: root=P2 iDb=P3
**
@@ -3295,7 +3233,7 @@ case OP_OpenWrite: {
break;
}
/* Opcode: OpenEphemeral P1 P2 * P4 *
/* Opcode: OpenEphemeral P1 P2 * P4 P5
** Synopsis: nColumn=P2
**
** Open a new cursor P1 to a transient table.
@@ -3307,18 +3245,11 @@ case OP_OpenWrite: {
** The cursor points to a BTree table if P4==0 and to a BTree index
** if P4 is not 0. If P4 is not NULL, it points to a KeyInfo structure
** that defines the format of keys in the index.
*/
/* Opcode: OpenHash P1 P2 * P4 *
** Synopsis: nColumn=P2
**
** Open a new cursor P1 to a transient table.
** P2 is the number of columns in the ephemeral table.
** The cursor points to a BTree table if P4==0 and to a BTree index
** if P4 is a KeyInfo structure.
**
** This opcode is identical to OP_OpenEphemeral except that it
** adds the BTREE_UNORDERED parameter to the sqlite3BtreeOpen() call,
** thus causing the underlying table to unordered.
** The P5 parameter can be a mask of the BTREE_* flags defined
** in btree.h. These flags control aspects of the operation of
** the btree. The BTREE_OMIT_JOURNAL and BTREE_SINGLE flags are
** added automatically.
*/
/* Opcode: OpenAutoindex P1 P2 * P4 *
** Synopsis: nColumn=P2
@@ -3329,10 +3260,9 @@ case OP_OpenWrite: {
** indices in joins.
*/
case OP_OpenAutoindex:
case OP_OpenHash:
case OP_OpenEphemeral: {
VdbeCursor *pCx;
int btreeFlags;
KeyInfo *pKeyInfo;
static const int vfsFlags =
SQLITE_OPEN_READWRITE |
@@ -3342,39 +3272,42 @@ case OP_OpenEphemeral: {
SQLITE_OPEN_TRANSIENT_DB;
assert( pOp->p1>=0 );
assert( pOp->p2>=0 );
assert( pOp->p5==0 );
pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
if( pCx==0 ) goto no_mem;
pCx->nullRow = 1;
btreeFlags = BTREE_OMIT_JOURNAL | BTREE_SINGLE;
if( pOp->opcode==OP_OpenHash ){
btreeFlags |= BTREE_UNORDERED;
pCx->isOrdered = 0;
}else{
pCx->isOrdered = 1;
}
if( pOp->p4.pKeyInfo ){
assert( pOp->p4type==P4_KEYINFO );
assert( pOp->p4.pKeyInfo->db==db );
assert( pOp->p4.pKeyInfo->enc==ENC(db) );
btreeFlags |= BTREE_SINGLE_INDEX;
pCx->isTable = 0;
}else{
pCx->isTable = 1;
}
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt, btreeFlags, vfsFlags);
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt,
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
}
if( rc==SQLITE_OK ){
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, pOp->p4.pKeyInfo,
pCx->pCursor);
/* If a transient index is required, create it by calling
** sqlite3BtreeCreateTable() with the BTREE_BLOBKEY flag before
** opening it. If a transient table is required, just use the
** automatically created table with root-page 1 (an BLOB_INTKEY table).
*/
if( (pKeyInfo = pOp->p4.pKeyInfo)!=0 ){
int pgno;
assert( pOp->p4type==P4_KEYINFO );
rc = sqlite3BtreeCreateTable(pCx->pBt, &pgno, BTREE_BLOBKEY | pOp->p5);
if( rc==SQLITE_OK ){
assert( pgno==MASTER_ROOT+1 );
assert( pKeyInfo->db==db );
assert( pKeyInfo->enc==ENC(db) );
pCx->pKeyInfo = pKeyInfo;
rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, pKeyInfo, pCx->pCursor);
}
pCx->isTable = 0;
}else{
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor);
pCx->isTable = 1;
}
}
pCx->pKeyInfo = pOp->p4.pKeyInfo;
pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
break;
}
/* Opcode: SorterOpen P1 * * P4 *
/* Opcode: SorterOpen P1 P2 * P4 *
**
** This opcode works like OP_OpenEphemeral except that it opens
** a transient index that is specifically designed to sort large
@@ -3394,14 +3327,13 @@ case OP_SorterOpen: {
break;
}
/* Opcode: OpenPseudo P1 P2 P3 * P5
** Synopsis: content in r[P2@P3]
/* Opcode: OpenPseudo P1 P2 P3 * *
** Synopsis: P3 columns in r[P2]
**
** Open a new cursor that points to a fake table that contains a single
** row of data. The content of that one row in the content of memory
** register P2 when P5==0. In other words, cursor P1 becomes an alias for the
** MEM_Blob content contained in register P2. When P5==1, then the
** row is represented by P3 consecutive registers beginning with P2.
** row of data. The content of that one row is the content of memory
** register P2. In other words, cursor P1 becomes an alias for the
** MEM_Blob content contained in register P2.
**
** A pseudo-table created by this opcode is used to hold a single
** row output from the sorter so that the row can be decomposed into
@@ -3421,7 +3353,7 @@ case OP_OpenPseudo: {
pCx->nullRow = 1;
pCx->pseudoTableReg = pOp->p2;
pCx->isTable = 1;
pCx->multiPseudo = pOp->p5;
assert( pOp->p5==0 );
break;
}
@@ -3734,15 +3666,13 @@ case OP_Found: { /* jump, in3 */
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp->p4.i;
r.aMem = pIn3;
for(ii=0; ii<r.nField; ii++){
assert( memIsValid(&r.aMem[ii]) );
ExpandBlob(&r.aMem[ii]);
#ifdef SQLITE_DEBUG
{
int i;
for(i=0; i<r.nField; i++){
assert( memIsValid(&r.aMem[i]) );
if( i ) REGISTER_TRACE(pOp->p3+i, &r.aMem[i]);
}
}
if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
#endif
}
r.flags = UNPACKED_PREFIX_MATCH;
pIdxKey = &r;
}else{
@@ -4241,7 +4171,7 @@ case OP_SorterData: {
**
** Write into register P2 the complete row key for cursor P1.
** There is no interpretation of the data.
** The key is copied onto the P3 register exactly as
** The key is copied onto the P2 register exactly as
** it is found in the database file.
**
** If the P1 cursor must be pointing to a valid row (not a NULL row)
@@ -4467,7 +4397,7 @@ case OP_Rewind: { /* jump */
break;
}
/* Opcode: Next P1 P2 P3 * P5
/* Opcode: Next P1 P2 P3 P4 P5
**
** Advance cursor P1 so that it points to the next key/data pair in its
** table or index. If there are no more key/value pairs then fall through
@@ -4490,12 +4420,12 @@ case OP_Rewind: { /* jump */
**
** See also: Prev, NextIfOpen
*/
/* Opcode: NextIfOpen P1 P2 P3 * P5
/* Opcode: NextIfOpen P1 P2 P3 P4 P5
**
** This opcode works just like OP_Next except that if cursor P1 is not
** open it behaves a no-op.
*/
/* Opcode: Prev P1 P2 P3 * P5
/* Opcode: Prev P1 P2 P3 P4 P5
**
** Back up cursor P1 so that it points to the previous key/data pair in its
** table or index. If there is no previous key/value pairs then fall through
@@ -4516,7 +4446,7 @@ case OP_Rewind: { /* jump */
** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented.
*/
/* Opcode: PrevIfOpen P1 P2 P3 * P5
/* Opcode: PrevIfOpen P1 P2 P3 P4 P5
**
** This opcode works just like OP_Prev except that if cursor P1 is not
** open it behaves a no-op.
@@ -4575,6 +4505,14 @@ next_tail:
** P3 is a flag that provides a hint to the b-tree layer that this
** insert is likely to be an append.
**
** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is
** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear,
** then the change counter is unchanged.
**
** If P5 has the OPFLAG_USESEEKRESULT bit set, then the cursor must have
** just done a seek to the spot where the new entry is to be inserted.
** This flag avoids doing an extra seek.
**
** This instruction only works for indices. The equivalent instruction
** for tables is OP_Insert.
*/
@@ -5175,7 +5113,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */
#ifndef SQLITE_OMIT_TRIGGER
/* Opcode: Program P1 P2 P3 P4 *
/* Opcode: Program P1 P2 P3 P4 P5
**
** Execute the trigger program passed as P4 (type P4_SUBPROGRAM).
**
@@ -5187,6 +5125,8 @@ case OP_RowSetTest: { /* jump, in1, in3 */
** memory required by the sub-vdbe at runtime.
**
** P4 is a pointer to the VM containing the trigger program.
**
** If P5 is non-zero, then recursive program invocation is enabled.
*/
case OP_Program: { /* jump */
int nMem; /* Number of memory registers for sub-program */
@@ -5264,7 +5204,7 @@ case OP_Program: { /* jump */
pEnd = &VdbeFrameMem(pFrame)[pFrame->nChildMem];
for(pMem=VdbeFrameMem(pFrame); pMem!=pEnd; pMem++){
pMem->flags = MEM_Invalid;
pMem->flags = MEM_Undefined;
pMem->db = db;
}
}else{
@@ -5574,7 +5514,7 @@ case OP_Checkpoint: {
#endif
#ifndef SQLITE_OMIT_PRAGMA
/* Opcode: JournalMode P1 P2 P3 * P5
/* Opcode: JournalMode P1 P2 P3 * *
**
** Change the journal mode of database P1 to P3. P3 must be one of the
** PAGER_JOURNALMODE_XXX values. If changing between the various rollback
@@ -6060,7 +6000,7 @@ case OP_VRename: {
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VUpdate P1 P2 P3 P4 *
/* Opcode: VUpdate P1 P2 P3 P4 P5
** Synopsis: data=r[P3@P2]
**
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
@@ -6083,6 +6023,9 @@ case OP_VRename: {
** P1 is a boolean flag. If it is set to true and the xUpdate call
** is successful, then the value returned by sqlite3_last_insert_rowid()
** is set to the value of the rowid for the row just inserted.
**
** P5 is the error actions (OE_Replace, OE_Fail, OE_Ignore, etc) to
** apply in the case of a constraint failure on an insert or update.
*/
case OP_VUpdate: {
sqlite3_vtab *pVtab;
@@ -6171,16 +6114,26 @@ case OP_MaxPgcnt: { /* out2-prerelease */
#endif
#ifndef SQLITE_OMIT_TRACE
/* Opcode: Trace * * * P4 *
/* Opcode: Init * P2 * P4 *
** Synopsis: Start at P2
**
** Programs contain a single instance of this opcode as the very first
** opcode.
**
** If tracing is enabled (by the sqlite3_trace()) interface, then
** the UTF-8 string contained in P4 is emitted on the trace callback.
** Or if P4 is blank, use the string returned by sqlite3_sql().
**
** If P2 is not zero, jump to instruction P2.
*/
case OP_Trace: {
case OP_Init: { /* jump */
char *zTrace;
char *z;
if( pOp->p2 ){
pc = pOp->p2 - 1;
}
#ifndef SQLITE_OMIT_TRACE
if( db->xTrace
&& !p->doingRerun
&& (zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql))!=0
@@ -6206,9 +6159,9 @@ case OP_Trace: {
sqlite3DebugPrintf("SQL-trace: %s\n", zTrace);
}
#endif /* SQLITE_DEBUG */
#endif /* SQLITE_OMIT_TRACE */
break;
}
#endif
/* Opcode: Noop * * * * *
+8 -7
View File
@@ -75,7 +75,6 @@ struct VdbeCursor {
Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
Bool isTable:1; /* True if a table requiring integer keys */
Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */
Bool multiPseudo:1; /* Multi-register pseudo-cursor */
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
i64 seqCount; /* Sequence counter */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
@@ -169,7 +168,7 @@ struct Mem {
} u;
int n; /* Number of characters in string value, excluding '\0' */
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 type; /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */
u8 memType; /* Lower 5 bits of flags */
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
#ifdef SQLITE_DEBUG
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
@@ -198,7 +197,7 @@ struct Mem {
#define MEM_Blob 0x0010 /* Value is a BLOB */
#define MEM_RowSet 0x0020 /* Value is a RowSet object */
#define MEM_Frame 0x0040 /* Value is a VdbeFrame object */
#define MEM_Invalid 0x0080 /* Value is undefined */
#define MEM_Undefined 0x0080 /* Value is undefined */
#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
#define MEM_TypeMask 0x01ff /* Mask of type bits */
@@ -230,7 +229,7 @@ struct Mem {
** is for use inside assert() statements only.
*/
#ifdef SQLITE_DEBUG
#define memIsValid(M) ((M)->flags & MEM_Invalid)==0
#define memIsValid(M) ((M)->flags & MEM_Undefined)==0
#endif
/*
@@ -425,16 +424,18 @@ int sqlite3VdbeMemNumerify(Mem*);
int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*);
void sqlite3VdbeMemRelease(Mem *p);
void sqlite3VdbeMemReleaseExternal(Mem *p);
#define VdbeMemDynamic(X) \
(((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))!=0)
#define VdbeMemRelease(X) \
if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
sqlite3VdbeMemReleaseExternal(X);
if( VdbeMemDynamic(X) ) sqlite3VdbeMemReleaseExternal(X);
int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
const char *sqlite3OpcodeName(int);
int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
int sqlite3VdbeCloseStatement(Vdbe *, int);
void sqlite3VdbeFrameDelete(VdbeFrame*);
int sqlite3VdbeFrameRestore(VdbeFrame *);
void sqlite3VdbeMemStoreType(Mem *pMem);
#define sqlite3VdbeMemStoreType(X) (X)->memType = (u8)((X)->flags&0x1f)
/* void sqlite3VdbeMemStoreType(Mem *pMem); */
int sqlite3VdbeTransferError(Vdbe *p);
int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
+36 -2
View File
@@ -172,7 +172,41 @@ const void *sqlite3_value_text16le(sqlite3_value *pVal){
}
#endif /* SQLITE_OMIT_UTF16 */
int sqlite3_value_type(sqlite3_value* pVal){
return pVal->type;
static const u8 aType[] = {
SQLITE_BLOB, /* 0x00 */
SQLITE_NULL, /* 0x01 */
SQLITE_TEXT, /* 0x02 */
SQLITE_NULL, /* 0x03 */
SQLITE_INTEGER, /* 0x04 */
SQLITE_NULL, /* 0x05 */
SQLITE_INTEGER, /* 0x06 */
SQLITE_NULL, /* 0x07 */
SQLITE_FLOAT, /* 0x08 */
SQLITE_NULL, /* 0x09 */
SQLITE_FLOAT, /* 0x0a */
SQLITE_NULL, /* 0x0b */
SQLITE_INTEGER, /* 0x0c */
SQLITE_NULL, /* 0x0d */
SQLITE_INTEGER, /* 0x0e */
SQLITE_NULL, /* 0x0f */
SQLITE_BLOB, /* 0x10 */
SQLITE_NULL, /* 0x11 */
SQLITE_TEXT, /* 0x12 */
SQLITE_NULL, /* 0x13 */
SQLITE_INTEGER, /* 0x14 */
SQLITE_NULL, /* 0x15 */
SQLITE_INTEGER, /* 0x16 */
SQLITE_NULL, /* 0x17 */
SQLITE_FLOAT, /* 0x18 */
SQLITE_NULL, /* 0x19 */
SQLITE_FLOAT, /* 0x1a */
SQLITE_NULL, /* 0x1b */
SQLITE_INTEGER, /* 0x1c */
SQLITE_NULL, /* 0x1d */
SQLITE_INTEGER, /* 0x1e */
SQLITE_NULL, /* 0x1f */
};
return aType[pVal->memType&0x1f];
}
/**************************** sqlite3_result_ *******************************
@@ -1131,7 +1165,7 @@ int sqlite3_bind_text16(
#endif /* SQLITE_OMIT_UTF16 */
int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
int rc;
switch( pValue->type ){
switch( sqlite3_value_type((sqlite3_value*)pValue) ){
case SQLITE_INTEGER: {
rc = sqlite3_bind_int64(pStmt, i, pValue->u.i);
break;
+14 -25
View File
@@ -863,14 +863,6 @@ void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
** this routine is a valid pointer. But because the dummy.opcode is 0,
** dummy will never be written to. This is verified by code inspection and
** by running with Valgrind.
**
** About the #ifdef SQLITE_OMIT_TRACE: Normally, this routine is never called
** unless p->nOp>0. This is because in the absense of SQLITE_OMIT_TRACE,
** an OP_Trace instruction is always inserted by sqlite3VdbeGet() as soon as
** a new VDBE is created. So we are free to set addr to p->nOp-1 without
** having to double-check to make sure that the result is non-negative. But
** if SQLITE_OMIT_TRACE is defined, the OP_Trace is omitted and we do need to
** check the value of p->nOp-1 before continuing.
*/
VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
/* C89 specifies that the constant "dummy" will be initialized to all
@@ -878,9 +870,6 @@ VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
static VdbeOp dummy; /* Ignore the MSVC warning about no initializer */
assert( p->magic==VDBE_MAGIC_INIT );
if( addr<0 ){
#ifdef SQLITE_OMIT_TRACE
if( p->nOp==0 ) return (VdbeOp*)&dummy;
#endif
addr = p->nOp - 1;
}
assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed );
@@ -1234,7 +1223,7 @@ static void releaseMemArray(Mem *p, int N){
p->zMalloc = 0;
}
p->flags = MEM_Invalid;
p->flags = MEM_Undefined;
}
db->mallocFailed = malloc_failed;
}
@@ -1356,7 +1345,7 @@ int sqlite3VdbeList(
}
if( p->explain==1 ){
pMem->flags = MEM_Int;
pMem->type = SQLITE_INTEGER;
pMem->memType = MEM_Int;
pMem->u.i = i; /* Program counter */
pMem++;
@@ -1364,7 +1353,7 @@ int sqlite3VdbeList(
pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
assert( pMem->z!=0 );
pMem->n = sqlite3Strlen30(pMem->z);
pMem->type = SQLITE_TEXT;
pMem->memType = MEM_Str;
pMem->enc = SQLITE_UTF8;
pMem++;
@@ -1390,17 +1379,17 @@ int sqlite3VdbeList(
pMem->flags = MEM_Int;
pMem->u.i = pOp->p1; /* P1 */
pMem->type = SQLITE_INTEGER;
pMem->memType = MEM_Int;
pMem++;
pMem->flags = MEM_Int;
pMem->u.i = pOp->p2; /* P2 */
pMem->type = SQLITE_INTEGER;
pMem->memType = MEM_Int;
pMem++;
pMem->flags = MEM_Int;
pMem->u.i = pOp->p3; /* P3 */
pMem->type = SQLITE_INTEGER;
pMem->memType = MEM_Int;
pMem++;
if( sqlite3VdbeMemGrow(pMem, 32, 0) ){ /* P4 */
@@ -1416,7 +1405,7 @@ int sqlite3VdbeList(
pMem->n = sqlite3Strlen30(pMem->z);
pMem->enc = SQLITE_UTF8;
}
pMem->type = SQLITE_TEXT;
pMem->memType = MEM_Str;
pMem++;
if( p->explain==1 ){
@@ -1427,7 +1416,7 @@ int sqlite3VdbeList(
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
pMem->n = 2;
sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
pMem->type = SQLITE_TEXT;
pMem->memType = MEM_Str;
pMem->enc = SQLITE_UTF8;
pMem++;
@@ -1438,11 +1427,11 @@ int sqlite3VdbeList(
}
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
pMem->n = displayComment(pOp, zP4, pMem->z, 500);
pMem->type = SQLITE_TEXT;
pMem->memType = MEM_Str;
pMem->enc = SQLITE_UTF8;
#else
pMem->flags = MEM_Null; /* Comment */
pMem->type = SQLITE_NULL;
pMem->memType = MEM_Null;
#endif
}
@@ -1465,7 +1454,7 @@ void sqlite3VdbePrintSql(Vdbe *p){
z = p->zSql;
}else if( p->nOp>=1 ){
const VdbeOp *pOp = &p->aOp[0];
if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){
z = pOp->p4.z;
while( sqlite3Isspace(*z) ) z++;
}
@@ -1484,7 +1473,7 @@ void sqlite3VdbeIOTraceSql(Vdbe *p){
if( sqlite3IoTrace==0 ) return;
if( nOp<1 ) return;
pOp = &p->aOp[0];
if( pOp->opcode==OP_Trace && pOp->p4.z!=0 ){
if( pOp->opcode==OP_Init && pOp->p4.z!=0 ){
int i, j;
char z[1000];
sqlite3_snprintf(sizeof(z), z, "%s", pOp->p4.z);
@@ -1702,7 +1691,7 @@ void sqlite3VdbeMakeReady(
p->aMem--; /* aMem[] goes from 1..nMem */
p->nMem = nMem; /* not from 0..nMem-1 */
for(n=1; n<=nMem; n++){
p->aMem[n].flags = MEM_Invalid;
p->aMem[n].flags = MEM_Undefined;
p->aMem[n].db = db;
}
}
@@ -1814,7 +1803,7 @@ static void Cleanup(Vdbe *p){
int i;
if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
if( p->aMem ){
for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Invalid );
for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
}
#endif
+26 -32
View File
@@ -134,21 +134,20 @@ int sqlite3_blob_open(
** transaction.
*/
static const VdbeOpList openBlob[] = {
{OP_Transaction, 0, 0, 0}, /* 0: Start a transaction */
{OP_VerifyCookie, 0, 0, 0}, /* 1: Check the schema cookie */
{OP_TableLock, 0, 0, 0}, /* 2: Acquire a read or write lock */
/* {OP_Transaction, 0, 0, 0}, // 0: Inserted separately */
{OP_TableLock, 0, 0, 0}, /* 1: Acquire a read or write lock */
/* One of the following two instructions is replaced by an OP_Noop. */
{OP_OpenRead, 0, 0, 0}, /* 3: Open cursor 0 for reading */
{OP_OpenWrite, 0, 0, 0}, /* 4: Open cursor 0 for read/write */
{OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */
{OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */
{OP_Variable, 1, 1, 1}, /* 5: Push the rowid to the stack */
{OP_NotExists, 0, 10, 1}, /* 6: Seek the cursor */
{OP_Column, 0, 0, 1}, /* 7 */
{OP_ResultRow, 1, 0, 0}, /* 8 */
{OP_Goto, 0, 5, 0}, /* 9 */
{OP_Close, 0, 0, 0}, /* 10 */
{OP_Halt, 0, 0, 0}, /* 11 */
{OP_Variable, 1, 1, 1}, /* 4: Push the rowid to the stack */
{OP_NotExists, 0, 10, 1}, /* 5: Seek the cursor */
{OP_Column, 0, 0, 1}, /* 6 */
{OP_ResultRow, 1, 0, 0}, /* 7 */
{OP_Goto, 0, 4, 0}, /* 8 */
{OP_Close, 0, 0, 0}, /* 9 */
{OP_Halt, 0, 0, 0}, /* 10 */
};
int rc = SQLITE_OK;
@@ -261,36 +260,31 @@ int sqlite3_blob_open(
Vdbe *v = (Vdbe *)pBlob->pStmt;
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags,
pTab->pSchema->schema_cookie,
pTab->pSchema->iGeneration);
sqlite3VdbeChangeP5(v, 1);
sqlite3VdbeAddOpList(v, sizeof(openBlob)/sizeof(VdbeOpList), openBlob);
/* Configure the OP_Transaction */
sqlite3VdbeChangeP1(v, 0, iDb);
sqlite3VdbeChangeP2(v, 0, flags);
/* Configure the OP_VerifyCookie */
sqlite3VdbeChangeP1(v, 1, iDb);
sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie);
sqlite3VdbeChangeP3(v, 1, pTab->pSchema->iGeneration);
/* Make sure a mutex is held on the table to be accessed */
sqlite3VdbeUsesBtree(v, iDb);
/* Configure the OP_TableLock instruction */
#ifdef SQLITE_OMIT_SHARED_CACHE
sqlite3VdbeChangeToNoop(v, 2);
sqlite3VdbeChangeToNoop(v, 1);
#else
sqlite3VdbeChangeP1(v, 2, iDb);
sqlite3VdbeChangeP2(v, 2, pTab->tnum);
sqlite3VdbeChangeP3(v, 2, flags);
sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT);
sqlite3VdbeChangeP1(v, 1, iDb);
sqlite3VdbeChangeP2(v, 1, pTab->tnum);
sqlite3VdbeChangeP3(v, 1, flags);
sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT);
#endif
/* Remove either the OP_OpenWrite or OpenRead. Set the P2
** parameter of the other to pTab->tnum. */
sqlite3VdbeChangeToNoop(v, 4 - flags);
sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum);
sqlite3VdbeChangeP3(v, 3 + flags, iDb);
sqlite3VdbeChangeToNoop(v, 3 - flags);
sqlite3VdbeChangeP2(v, 2 + flags, pTab->tnum);
sqlite3VdbeChangeP3(v, 2 + flags, iDb);
/* Configure the number of columns. Configure the cursor to
** think that the table has one more column than it really
@@ -299,8 +293,8 @@ int sqlite3_blob_open(
** we can invoke OP_Column to fill in the vdbe cursors type
** and offset cache without causing any IO.
*/
sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
sqlite3VdbeChangeP2(v, 7, pTab->nCol);
sqlite3VdbeChangeP4(v, 2+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
sqlite3VdbeChangeP2(v, 6, pTab->nCol);
if( !db->mallocFailed ){
pParse->nVar = 1;
pParse->nMem = 1;
+11 -11
View File
@@ -289,7 +289,7 @@ void sqlite3VdbeMemReleaseExternal(Mem *p){
/*
** Release any memory held by the Mem. This may leave the Mem in an
** inconsistent state, for example with (Mem.z==0) and
** (Mem.type==SQLITE_TEXT).
** (Mem.memType==MEM_Str).
*/
void sqlite3VdbeMemRelease(Mem *p){
VdbeMemRelease(p);
@@ -480,7 +480,7 @@ void sqlite3VdbeMemSetNull(Mem *pMem){
sqlite3RowSetClear(pMem->u.pRowSet);
}
MemSetTypeFlag(pMem, MEM_Null);
pMem->type = SQLITE_NULL;
pMem->memType = MEM_Null;
}
void sqlite3ValueSetNull(sqlite3_value *p){
sqlite3VdbeMemSetNull((Mem*)p);
@@ -493,7 +493,7 @@ void sqlite3ValueSetNull(sqlite3_value *p){
void sqlite3VdbeMemSetZeroBlob(Mem *pMem, int n){
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Blob|MEM_Zero;
pMem->type = SQLITE_BLOB;
pMem->memType = MEM_Blob;
pMem->n = 0;
if( n<0 ) n = 0;
pMem->u.nZero = n;
@@ -516,7 +516,7 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
sqlite3VdbeMemRelease(pMem);
pMem->u.i = val;
pMem->flags = MEM_Int;
pMem->type = SQLITE_INTEGER;
pMem->memType = MEM_Int;
}
#ifndef SQLITE_OMIT_FLOATING_POINT
@@ -531,7 +531,7 @@ void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
sqlite3VdbeMemRelease(pMem);
pMem->r = val;
pMem->flags = MEM_Real;
pMem->type = SQLITE_FLOAT;
pMem->memType = MEM_Real;
}
}
#endif
@@ -587,7 +587,7 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
Mem *pX;
for(i=1, pX=&pVdbe->aMem[1]; i<=pVdbe->nMem; i++, pX++){
if( pX->pScopyFrom==pMem ){
pX->flags |= MEM_Invalid;
pX->flags |= MEM_Undefined;
pX->pScopyFrom = 0;
}
}
@@ -739,7 +739,7 @@ int sqlite3VdbeMemSetStr(
pMem->n = nByte;
pMem->flags = flags;
pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
pMem->type = (enc==0 ? SQLITE_BLOB : SQLITE_TEXT);
pMem->memType = flags&0x1f;
#ifndef SQLITE_OMIT_UTF16
if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
@@ -910,7 +910,7 @@ int sqlite3VdbeMemFromBtree(
}else if( SQLITE_OK==(rc = sqlite3VdbeMemGrow(pMem, amt+2, 0)) ){
pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term;
pMem->enc = 0;
pMem->type = SQLITE_BLOB;
pMem->memType = MEM_Blob;
if( key ){
rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
}else{
@@ -980,7 +980,7 @@ sqlite3_value *sqlite3ValueNew(sqlite3 *db){
Mem *p = sqlite3DbMallocZero(db, sizeof(*p));
if( p ){
p->flags = MEM_Null;
p->type = SQLITE_NULL;
p->memType = MEM_Null;
p->db = db;
}
return p;
@@ -1030,7 +1030,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
pRec->aMem = (Mem *)((u8*)pRec + ROUND8(sizeof(UnpackedRecord)));
for(i=0; i<nCol; i++){
pRec->aMem[i].flags = MEM_Null;
pRec->aMem[i].type = SQLITE_NULL;
pRec->aMem[i].memType = MEM_Null;
pRec->aMem[i].db = db;
}
}else{
@@ -1103,7 +1103,7 @@ static int valueFromExpr(
zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
if( zVal==0 ) goto no_mem;
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
if( op==TK_FLOAT ) pVal->type = SQLITE_FLOAT;
if( op==TK_FLOAT ) pVal->memType = MEM_Real;
}
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
+43 -22
View File
@@ -2348,17 +2348,16 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
** this routine sets up a loop that will iterate over all values of X.
*/
static int codeEqualityTerm(
WhereInfo *pWInfo, /* WHERE clause */
Parse *pParse, /* The parsing context */
WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
WhereLevel *pLevel, /* The level of the FROM clause we are working on */
int iEq, /* Index of the equality term within this level */
int bRev, /* True for reverse-order IN operations */
int iTarget /* Attempt to leave results in this register */
){
Expr *pX = pTerm->pExpr; /* Expression to be coded */
Parse *pParse = pWInfo->pParse; /* Parsing context */
Vdbe *v = pParse->pVdbe; /* Prepared stmt under construction */
int iReg; /* Register holding results */
Expr *pX = pTerm->pExpr;
Vdbe *v = pParse->pVdbe;
int iReg; /* Register holding results */
assert( iTarget>0 );
if( pX->op==TK_EQ ){
@@ -2383,7 +2382,7 @@ static int codeEqualityTerm(
}
assert( pX->op==TK_IN );
iReg = iTarget;
eType = sqlite3FindInIndex(pParse, pX, 0, pWInfo->bOBSat);
eType = sqlite3FindInIndex(pParse, pX, 0);
if( eType==IN_INDEX_INDEX_DESC ){
testcase( bRev );
bRev = !bRev;
@@ -2465,7 +2464,7 @@ static int codeEqualityTerm(
** string in this example would be set to SQLITE_AFF_NONE.
*/
static int codeAllEqualityTerms(
WhereInfo *pWInfo, /* WHERE clause */
Parse *pParse, /* Parsing context */
WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */
int bRev, /* Reverse the order of IN operators */
int nExtraReg, /* Number of extra registers to allocate */
@@ -2473,7 +2472,6 @@ static int codeAllEqualityTerms(
){
u16 nEq; /* The number of == or IN constraints to code */
u16 nSkip; /* Number of left-most columns to skip */
Parse *pParse = pWInfo->pParse; /* Parsing context */
Vdbe *v = pParse->pVdbe; /* The vm under construction */
Index *pIdx; /* The index being used for this loop */
WhereTerm *pTerm; /* A single constraint term */
@@ -2528,7 +2526,7 @@ static int codeAllEqualityTerms(
** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL );
r1 = codeEqualityTerm(pWInfo, pTerm, pLevel, j, bRev, regBase+j);
r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j);
if( r1!=regBase+j ){
if( nReg==1 ){
sqlite3ReleaseTempReg(pParse, regBase);
@@ -2787,10 +2785,9 @@ static Bitmask codeOneLoopStart(
/* Special case of a FROM clause subquery implemented as a co-routine */
if( pTabItem->viaCoroutine ){
int regYield = pTabItem->regReturn;
sqlite3VdbeAddOp2(v, OP_Integer, pTabItem->addrFillSub-1, regYield);
pLevel->p2 = sqlite3VdbeAddOp1(v, OP_Yield, regYield);
VdbeComment((v, "next row of co-routine %s", pTabItem->pTab->zName));
sqlite3VdbeAddOp2(v, OP_If, regYield+1, addrBrk);
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, pTabItem->addrFillSub);
pLevel->p2 = sqlite3VdbeAddOp2(v, OP_Yield, regYield, addrBrk);
VdbeComment((v, "next row of \"%s\"", pTabItem->pTab->zName));
pLevel->op = OP_Goto;
}else
@@ -2811,7 +2808,7 @@ static Bitmask codeOneLoopStart(
pTerm = pLoop->aLTerm[j];
if( pTerm==0 ) continue;
if( pTerm->eOperator & WO_IN ){
codeEqualityTerm(pWInfo, pTerm, pLevel, j, bRev, iTarget);
codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
addrNotFound = pLevel->addrNxt;
}else{
sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
@@ -2851,7 +2848,7 @@ static Bitmask codeOneLoopStart(
assert( pTerm->pExpr!=0 );
assert( omitTable==0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL );
iRowidReg = codeEqualityTerm(pWInfo, pTerm, pLevel, 0, bRev, iReleaseReg);
iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
addrNxt = pLevel->addrNxt;
sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
@@ -3041,7 +3038,7 @@ static Bitmask codeOneLoopStart(
** and store the values of those terms in an array of registers
** starting at regBase.
*/
regBase = codeAllEqualityTerms(pWInfo,pLevel,bRev,nExtraReg,&zStartAff);
regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff);
assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq );
if( zStartAff ) cEndAff = zStartAff[nEq];
addrNxt = pLevel->addrNxt;
@@ -3318,7 +3315,9 @@ static Bitmask codeOneLoopStart(
Expr *pExpr = pWC->a[iTerm].pExpr;
if( &pWC->a[iTerm] == pTerm ) continue;
if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
if( pWC->a[iTerm].wtFlags & (TERM_ORINFO) ) continue;
testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO );
testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
if( pWC->a[iTerm].wtFlags & (TERM_ORINFO|TERM_VIRTUAL) ) continue;
if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue;
pExpr = sqlite3ExprDup(db, pExpr, 0);
pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr);
@@ -5439,7 +5438,6 @@ WhereInfo *sqlite3WhereBegin(
initMaskSet(pMaskSet);
whereClauseInit(&pWInfo->sWC, pWInfo);
whereSplit(&pWInfo->sWC, pWhere, TK_AND);
sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
/* Special case: a WHERE clause that is constant. Evaluate the
** expression and either jump over all of the code or fall thru.
@@ -5728,7 +5726,7 @@ WhereInfo *sqlite3WhereBegin(
sqlite3VdbeSetP4KeyInfo(pParse, pIx);
VdbeComment((v, "%s", pIx->zName));
}
sqlite3CodeVerifySchema(pParse, iDb);
if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb);
notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor);
}
pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
@@ -5839,12 +5837,38 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
assert( pWInfo->nLevel<=pTabList->nSrc );
for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
int k, last;
VdbeOp *pOp;
Index *pIdx = 0;
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
pLoop = pLevel->pWLoop;
/* For a co-routine, change all OP_Column references to the table of
** the co-routine into OP_SCopy of result contained in a register.
** OP_Rowid becomes OP_Null.
*/
if( pTabItem->viaCoroutine ){
last = sqlite3VdbeCurrentAddr(v);
k = pLevel->addrBody;
pOp = sqlite3VdbeGetOp(v, k);
for(; k<last; k++, pOp++){
if( pOp->p1!=pLevel->iTabCur ) continue;
if( pOp->opcode==OP_Column ){
pOp->opcode = OP_SCopy;
pOp->p1 = pOp->p2 + pTabItem->regResult;
pOp->p2 = pOp->p3;
pOp->p3 = 0;
}else if( pOp->opcode==OP_Rowid ){
pOp->opcode = OP_Null;
pOp->p1 = 0;
pOp->p3 = 0;
}
}
continue;
}
/* Close all of the cursors that were opened by sqlite3WhereBegin.
** Except, do not close cursors that will be reused by the OR optimization
** (WHERE_OMIT_OPEN_CLOSE). And do not close the OP_OpenWrite cursors
@@ -5883,9 +5907,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
pIdx = pLevel->u.pCovidx;
}
if( pIdx && !db->mallocFailed ){
int k, last;
VdbeOp *pOp;
last = sqlite3VdbeCurrentAddr(v);
k = pLevel->addrBody;
pOp = sqlite3VdbeGetOp(v, k);
+2 -2
View File
@@ -333,14 +333,14 @@ do_test backup-3.$iTest.1 {
set iTab 1
db eval { PRAGMA page_size = 512 }
while {[file size test.db] <= $::sqlite_pending_byte} {
while {[file_size test.db] <= $::sqlite_pending_byte} {
db eval "CREATE TABLE t${iTab}(a, b, c)"
incr iTab
}
sqlite3 db2 test2.db
db2 eval { PRAGMA page_size = 4096 }
while {[file size test2.db] < $::sqlite_pending_byte} {
while {[file_size test2.db] < $::sqlite_pending_byte} {
db2 eval "CREATE TABLE t${iTab}(a, b, c)"
incr iTab
}
+2 -2
View File
@@ -72,7 +72,7 @@ do_test 2.3 {
file size test.db
} {1024}
do_test 2.4 { file size test.db2 } 0
do_test 2.4 { file_size test.db2 } 0
db close
forcedelete test.db
@@ -98,6 +98,6 @@ do_test 3.3 {
file size test.db
} {1024}
do_test 3.4 { file size test.db2 } 0
do_test 3.4 { file_size test.db2 } 0
finish_test
+4 -1
View File
@@ -70,9 +70,12 @@ foreach name $names {
sqlite3_errcode $db2
} {SQLITE_OK}
do_test capi3e-1.2.$i {
sqlite3_exec $db2 { CREATE TABLE t1(x) }
} {0 {}}
do_test capi3e-1.3.$i {
sqlite3_close $db2
} {SQLITE_OK}
do_test capi3e-1.3.$i {
do_test capi3e-1.4.$i {
file isfile $name
} {1}
}
+31 -3
View File
@@ -51,9 +51,12 @@ proc do_temptables_test {tn sql temptables} {
set ret ""
db eval "EXPLAIN [set sql]" {
if {$opcode == "OpenEphemeral" || $opcode == "SorterOpen"} {
lappend ret btree
} elseif {$opcode == "OpenHash"} {
lappend ret hash
if {$p5 != "08" && $p5!="00"} { error "p5 = $p5" }
if {$p5 == "08"} {
lappend ret hash
} else {
lappend ret btree
}
}
}
set ret
@@ -194,4 +197,29 @@ do_test 3.1 {
}]
} {0}
#-------------------------------------------------------------------------
# Ticket [fccbde530a6583bf2748400919f1603d5425995c] (2014-01-08)
# The logic that computes DISTINCT sometimes thinks that a zeroblob()
# and a blob of all zeros are different when they should be the same.
#
do_execsql_test 4.1 {
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;
CREATE TABLE t1(a INTEGER);
INSERT INTO t1 VALUES(3);
INSERT INTO t1 VALUES(2);
INSERT INTO t1 VALUES(1);
INSERT INTO t1 VALUES(2);
INSERT INTO t1 VALUES(3);
INSERT INTO t1 VALUES(1);
CREATE TABLE t2(x);
INSERT INTO t2
SELECT DISTINCT
CASE a WHEN 1 THEN x'0000000000'
WHEN 2 THEN zeroblob(5)
ELSE 'xyzzy' END
FROM t1;
SELECT quote(x) FROM t2 ORDER BY 1;
} {'xyzzy' X'0000000000'}
finish_test
+10 -1
View File
@@ -64,6 +64,7 @@ if {$tcl_platform(platform) == "unix"} {
do_test 1.1 {
forcedelete file:test.db test.db
set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]
sqlite3_exec $DB {CREATE TABLE t1(x)}
list [file exists file:test.db] [file exists test.db]
} {0 1}
do_test 1.2 {
@@ -71,12 +72,14 @@ if {$tcl_platform(platform) == "unix"} {
set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
sqlite3_step $STMT
sqlite3_finalize $STMT
sqlite3_exec $DB {CREATE TABLE aux.t1(x)}
list [file exists file:test.db2] [file exists test.db2]
} {0 1}
sqlite3_close $DB
do_test 1.3 {
forcedelete file:test.db test.db
set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]
sqlite3_exec $DB {CREATE TABLE t1(x)}
list [file exists file:test.db] [file exists test.db]
} {1 0}
do_test 1.4 {
@@ -84,6 +87,7 @@ if {$tcl_platform(platform) == "unix"} {
set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
sqlite3_step $STMT
sqlite3_finalize $STMT
sqlite3_exec $DB {CREATE TABLE aux.t1(x)}
list [file exists file:test.db2] [file exists test.db2]
} {1 0}
sqlite3_close $DB
@@ -96,6 +100,7 @@ if {$tcl_platform(platform) == "unix"} {
do_test 1.5 {
forcedelete file:test.db test.db
set DB [sqlite3_open_v2 file:test.db [concat $flags SQLITE_OPEN_URI] ""]
sqlite3_exec $DB {CREATE TABLE t1(x)}
list [file exists file:test.db] [file exists test.db]
} {0 1}
do_test 1.6 {
@@ -103,12 +108,14 @@ if {$tcl_platform(platform) == "unix"} {
set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
sqlite3_step $STMT
sqlite3_finalize $STMT
sqlite3_exec $DB {CREATE TABLE aux.t1(x)}
list [file exists file:test.db2] [file exists test.db2]
} {0 1}
sqlite3_close $DB
do_test 1.7 {
forcedelete file:test.db test.db
set DB [sqlite3_open_v2 file:test.db [concat $flags] ""]
sqlite3_exec $DB {CREATE TABLE t1(x)}
list [file exists file:test.db] [file exists test.db]
} {0 1}
do_test 1.8 {
@@ -116,6 +123,7 @@ if {$tcl_platform(platform) == "unix"} {
set STMT [sqlite3_prepare $DB "ATTACH 'file:test.db2' AS aux" -1 dummy]
sqlite3_step $STMT
sqlite3_finalize $STMT
sqlite3_exec $DB {CREATE TABLE aux.t1(x)}
list [file exists file:test.db2] [file exists test.db2]
} {0 1}
sqlite3_close $DB
@@ -314,6 +322,7 @@ foreach {tn uri read write create} {
#
forcedelete test.db
sqlite3 db test.db
db eval {CREATE TABLE t1(x)}
db close
foreach {tn uri flags error} {
1 {file:test.db?mode=ro} ro {not an error}
@@ -331,7 +340,7 @@ foreach {tn uri flags error} {
set f(ro) [list SQLITE_OPEN_READONLY SQLITE_OPEN_URI]
set f(rw) [list SQLITE_OPEN_READWRITE SQLITE_OPEN_URI]
set f(rwc) [list SQLITE_OPEN_READWRITE SQLITE_OPEN_CREATE SQLITE_OPEN_URI]
breakpoint
set DB [sqlite3_open_v2 $uri $f($flags) ""]
set e [sqlite3_errmsg $DB]
sqlite3_close $DB
+14 -12
View File
@@ -69,18 +69,20 @@ proc pagerChangeCounter {filename new {fd ""}} {
}
proc readPagerChangeCounter {filename} {
set fd [open $filename RDONLY]
fconfigure $fd -translation binary -encoding binary
seek $fd 24
foreach {a b c d} [list 0 0 0 0] {}
binary scan [read $fd 4] cccc a b c d
set ret [expr ($a&0x000000FF)<<24]
incr ret [expr ($b&0x000000FF)<<16]
incr ret [expr ($c&0x000000FF)<<8]
incr ret [expr ($d&0x000000FF)<<0]
close $fd
if {[file exists $filename]} {
set fd [open $filename RDONLY]
fconfigure $fd -translation binary -encoding binary
seek $fd 24
foreach {a b c d} [list 0 0 0 0] {}
binary scan [read $fd 4] cccc a b c d
set ret [expr ($a&0x000000FF)<<24]
incr ret [expr ($b&0x000000FF)<<16]
incr ret [expr ($c&0x000000FF)<<8]
incr ret [expr ($d&0x000000FF)<<0]
close $fd
} else {
set ret 0
}
return $ret
}
+1 -1
View File
@@ -29,7 +29,7 @@ ifcapable !subquery {
proc nEphemeral {sql} {
set nEph 0
foreach op [execsql "EXPLAIN $sql"] {
if {$op eq "OpenEphemeral" || $op eq "OpenHash"} {incr nEph}
if {$op eq "OpenEphemeral"} {incr nEph}
}
set nEph
}
+3 -3
View File
@@ -65,17 +65,17 @@ do_test in5-2.4 {
}
} {12a 56e}
do_test in5-2.5.1 {
regexp {Open(Ephemeral|Hash)} [db eval {
regexp {OpenEphemeral} [db eval {
EXPLAIN SELECT d FROM t2 WHERE a IN t3x AND b IN t1y AND c IN t1z
}]
} {1}
do_test in5-2.5.2 {
regexp {Open(Ephemeral|Hash)} [db eval {
regexp {OpenEphemeral} [db eval {
EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t3y AND c IN t1z
}]
} {1}
do_test in5-2.5.3 {
regexp {Open(Ephemeral|Hash)} [db eval {
regexp {OpenEphemeral} [db eval {
EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t3z
}]
} {1}
+2 -2
View File
@@ -38,7 +38,7 @@ do_test incrvacuum-1.2.0 {
# File size is sometimes 1 instead of 0 due to the hack we put in
# to work around ticket #3260. Search for comments on #3260 in
# os_unix.c.
expr {[file size test.db] > 1}
expr {[file_size test.db] > 1}
} {0}
do_test incrvacuum-1.2 {
# This command will create the database.
@@ -700,7 +700,7 @@ do_test incrvacuum-13.1 {
# File size is sometimes 1 instead of 0 due to the hack we put in
# to work around ticket #3260. Search for comments on #3260 in
# os_unix.c.
expr {[file size test.db]>1}
expr {[file_size test.db]>1}
} {0}
do_test incrvacuum-13.2 {
set ::STMT [sqlite3_prepare $::DB {PRAGMA auto_vacuum = 2} -1 DUMMY]
+1 -1
View File
@@ -391,7 +391,7 @@ ifcapable pager_pragmas {
}
# File size might be 1 due to the hack to work around ticket #3260.
# Search for #3260 in os_unix.c for additional information.
expr {[file size test.db]>1}
expr {[file_size test.db]>1}
} {0}
do_test io-3.2 {
execsql { CREATE TABLE abc(a, b) }
+1 -1
View File
@@ -1373,7 +1373,7 @@ do_test pager1-9.4.1 {
list [B step 10000] [B finish]
} {SQLITE_DONE SQLITE_OK}
do_test pager1-9.4.2 {
list [file size test.db2] [file size test.db]
list [file_size test.db2] [file_size test.db]
} {1024 0}
db2 close
+1 -1
View File
@@ -135,7 +135,7 @@ test_suite "veryquick" -prefix "" -description {
This test suite is the same as the "quick" tests, except that some files
that test malloc and IO errors are omitted.
} -files [
test_set $allquicktests -exclude *malloc* *ioerr* *fault*
test_set $allquicktests -exclude *malloc* *ioerr* *fault*
]
test_suite "mmap" -prefix "mm-" -description {
+17
View File
@@ -1292,5 +1292,22 @@ do_test selectA-3.97 {
ORDER BY y COLLATE NOCASE DESC,x,z)))
}
} {MAD}
do_execsql_test selectA-3.98 {
WITH RECURSIVE
xyz(n) AS (
SELECT upper((SELECT x FROM (
SELECT x,y,z FROM t2
INTERSECT SELECT a,b,c FROM t3
EXCEPT SELECT c,b,a FROM t1
UNION SELECT a,b,c FROM t3
INTERSECT SELECT a,b,c FROM t3
EXCEPT SELECT c,b,a FROM t1
UNION SELECT a,b,c FROM t3
ORDER BY y COLLATE NOCASE DESC,x,z)))
UNION ALL
SELECT n || '+' FROM xyz WHERE length(n)<5
)
SELECT n FROM xyz ORDER BY +n;
} {MAD MAD+ MAD++}
finish_test
+1 -1
View File
@@ -105,7 +105,7 @@ do_test shell1-1.7.1 {
set rc [lindex $res 0]
list $rc \
[regexp {SQLite version} $res] \
[regexp {Enter SQL statements} $res]
[regexp {Enter ".help" for usage hints} $res]
} {0 1 1}
# -batch force batch I/O
+157
View File
@@ -737,6 +737,161 @@ void testset_main(void){
speedtest1_end_test();
}
/*
** A testset for common table expressions. This exercises code
** for views, subqueries, co-routines, etc.
*/
void testset_cte(void){
static const char *azPuzzle[] = {
/* Easy */
"534...9.."
"67.195..."
".98....6."
"8...6...3"
"4..8.3..1"
"....2...6"
".6....28."
"...419..5"
"...28..79",
/* Medium */
"53....9.."
"6..195..."
".98....6."
"8...6...3"
"4..8.3..1"
"....2...6"
".6....28."
"...419..5"
"....8..79",
/* Hard */
"53......."
"6..195..."
".98....6."
"8...6...3"
"4..8.3..1"
"....2...6"
".6....28."
"...419..5"
"....8..79",
};
const char *zPuz;
double rSpacing;
int nElem;
if( g.szTest<25 ){
zPuz = azPuzzle[0];
}else if( g.szTest<70 ){
zPuz = azPuzzle[1];
}else{
zPuz = azPuzzle[2];
}
speedtest1_begin_test(100, "Sudoku with recursive 'digits'");
speedtest1_prepare(
"WITH RECURSIVE\n"
" input(sud) AS (VALUES(?1)),\n"
" digits(z,lp) AS (\n"
" VALUES('1', 1)\n"
" UNION ALL\n"
" SELECT CAST(lp+1 AS TEXT), lp+1 FROM digits WHERE lp<9\n"
" ),\n"
" x(s, ind) AS (\n"
" SELECT sud, instr(sud, '.') FROM input\n"
" UNION ALL\n"
" SELECT\n"
" substr(s, 1, ind-1) || z || substr(s, ind+1),\n"
" instr( substr(s, 1, ind-1) || z || substr(s, ind+1), '.' )\n"
" FROM x, digits AS z\n"
" WHERE ind>0\n"
" AND NOT EXISTS (\n"
" SELECT 1\n"
" FROM digits AS lp\n"
" WHERE z.z = substr(s, ((ind-1)/9)*9 + lp, 1)\n"
" OR z.z = substr(s, ((ind-1)%%9) + (lp-1)*9 + 1, 1)\n"
" OR z.z = substr(s, (((ind-1)/3) %% 3) * 3\n"
" + ((ind-1)/27) * 27 + lp\n"
" + ((lp-1) / 3) * 6, 1)\n"
" )\n"
" )\n"
"SELECT s FROM x WHERE ind=0;"
);
sqlite3_bind_text(g.pStmt, 1, zPuz, -1, SQLITE_STATIC);
speedtest1_run();
speedtest1_end_test();
speedtest1_begin_test(200, "Sudoku with VALUES 'digits'");
speedtest1_prepare(
"WITH RECURSIVE\n"
" input(sud) AS (VALUES(?1)),\n"
" digits(z,lp) AS (VALUES('1',1),('2',2),('3',3),('4',4),('5',5),\n"
" ('6',6),('7',7),('8',8),('9',9)),\n"
" x(s, ind) AS (\n"
" SELECT sud, instr(sud, '.') FROM input\n"
" UNION ALL\n"
" SELECT\n"
" substr(s, 1, ind-1) || z || substr(s, ind+1),\n"
" instr( substr(s, 1, ind-1) || z || substr(s, ind+1), '.' )\n"
" FROM x, digits AS z\n"
" WHERE ind>0\n"
" AND NOT EXISTS (\n"
" SELECT 1\n"
" FROM digits AS lp\n"
" WHERE z.z = substr(s, ((ind-1)/9)*9 + lp, 1)\n"
" OR z.z = substr(s, ((ind-1)%%9) + (lp-1)*9 + 1, 1)\n"
" OR z.z = substr(s, (((ind-1)/3) %% 3) * 3\n"
" + ((ind-1)/27) * 27 + lp\n"
" + ((lp-1) / 3) * 6, 1)\n"
" )\n"
" )\n"
"SELECT s FROM x WHERE ind=0;"
);
sqlite3_bind_text(g.pStmt, 1, zPuz, -1, SQLITE_STATIC);
speedtest1_run();
speedtest1_end_test();
rSpacing = 5.0/g.szTest;
speedtest1_begin_test(300, "Mandelbrot Set with spacing=%f", rSpacing);
speedtest1_prepare(
"WITH RECURSIVE \n"
" xaxis(x) AS (VALUES(-2.0) UNION ALL SELECT x+?1 FROM xaxis WHERE x<1.2),\n"
" yaxis(y) AS (VALUES(-1.0) UNION ALL SELECT y+?2 FROM yaxis WHERE y<1.0),\n"
" m(iter, cx, cy, x, y) AS (\n"
" SELECT 0, x, y, 0.0, 0.0 FROM xaxis, yaxis\n"
" UNION ALL\n"
" SELECT iter+1, cx, cy, x*x-y*y + cx, 2.0*x*y + cy FROM m \n"
" WHERE (x*x + y*y) < 4.0 AND iter<28\n"
" ),\n"
" m2(iter, cx, cy) AS (\n"
" SELECT max(iter), cx, cy FROM m GROUP BY cx, cy\n"
" ),\n"
" a(t) AS (\n"
" SELECT group_concat( substr(' .+*#', 1+min(iter/7,4), 1), '') \n"
" FROM m2 GROUP BY cy\n"
" )\n"
"SELECT group_concat(rtrim(t),x'0a') FROM a;"
);
sqlite3_bind_double(g.pStmt, 1, rSpacing*.05);
sqlite3_bind_double(g.pStmt, 2, rSpacing);
speedtest1_run();
speedtest1_end_test();
nElem = 10000*g.szTest;
speedtest1_begin_test(400, "EXCEPT operator on %d-element tables", nElem);
speedtest1_prepare(
"WITH RECURSIVE \n"
" t1(x) AS (VALUES(2) UNION ALL SELECT x+2 FROM t1 WHERE x<%d),\n"
" t2(y) AS (VALUES(3) UNION ALL SELECT y+3 FROM t2 WHERE y<%d)\n"
"SELECT count(x), avg(x) FROM (\n"
" SELECT x FROM t1 EXCEPT SELECT y FROM t2 ORDER BY 1\n"
");",
nElem, nElem
);
speedtest1_run();
speedtest1_end_test();
}
/*
** A testset used for debugging speedtest1 itself.
*/
@@ -945,6 +1100,8 @@ int main(int argc, char **argv){
testset_main();
}else if( strcmp(zTSet,"debug1")==0 ){
testset_debug1();
}else if( strcmp(zTSet,"cte")==0 ){
testset_cte();
}else{
fatal_error("unknown testset: \"%s\"\n", zTSet);
}
+4 -2
View File
@@ -236,9 +236,10 @@ catch { db close }
forcedelete test.db test.db2
do_test 8.1 {
close [open test.db w]
sqlite3 db test.db
file_control_chunksize_test db main 4096
file size test.db
file_size test.db
} {0}
foreach {tn hint size} {
1 1000 4096
@@ -249,13 +250,14 @@ foreach {tn hint size} {
} {
do_test 8.2.$tn {
file_control_sizehint_test db main $hint
file size test.db
file_size test.db
} $size
}
do_test 8.3 {
db close
forcedelete test.db test.db2
close [open test.db w]
sqlite3 db test.db
file_control_chunksize_test db main 16
file size test.db
+10
View File
@@ -185,6 +185,16 @@ proc forcecopy {from to} {
do_copy_file true $from $to
}
# If file $zFile exists in the file system, return its size in bytes.
# Otherwise, return zero.
proc file_size {zFile} {
if {[file exists $zFile]} {
return [file size $zFile]
}
return 0
}
proc do_copy_file {force from to} {
set nRetry [getFileRetries] ;# Maximum number of retries.
set nDelay [getFileRetryDelay] ;# Delay in ms before retrying.
+49
View File
@@ -0,0 +1,49 @@
# 2014-02-11
#
# 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. Specifically,
# it tests that ticket [4c86b126f22ad548fee0125337bdc9366912d9ac].
#
# When SQLite is compiled using SQLITE_ENABLE_STAT3 or SQLITE_ENABLE_STAT4,
# it gets the wrong answer...
#
# The problem was introduced in SQLite 3.8.1.
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_execsql_test tkt-4c86b126f2-1.1 {
CREATE TABLE nodes(
local_relpath TEXT PRIMARY KEY,
moved_to TEXT
);
INSERT INTO nodes VALUES('A',NULL);
INSERT INTO nodes VALUES('A/B',NULL);
INSERT INTO nodes VALUES('',NULL);
INSERT INTO nodes VALUES('A/B/C-move',NULL);
INSERT INTO nodes VALUES('A/B/C','A/B/C-move');
INSERT INTO nodes VALUES('A/B-move',NULL);
INSERT INTO nodes VALUES('A/B-move/C-move',NULL);
INSERT INTO nodes VALUES('A/B-move/C','x');
SELECT local_relpath, moved_to
FROM nodes
WHERE (local_relpath = 'A/B' OR
((local_relpath > 'A/B/') AND (local_relpath < 'A/B0')))
AND moved_to IS NOT NULL;
} {A/B/C A/B/C-move}
do_execsql_test tkt-4c86b126f2-2.1 {
CREATE TABLE t1(x TEXT UNIQUE, y TEXT UNIQUE, z);
INSERT INTO t1 VALUES('ghi','jkl','y');
SELECT * FROM t1 WHERE (x='ghi' OR y='jkl') AND z IS NOT NULL;
} {ghi jkl y}
finish_test
+1
View File
@@ -46,6 +46,7 @@ do_test tkt4018-1.1 {
# connection to test.db 10000 times. If file-descriptors are not being
# reused, then the process will quickly exceed its maximum number of
# file descriptors (1024 by default on linux).
breakpoint
do_test tkt4018-1.2 {
for {set i 0} {$i < 10000} {incr i} {
sqlite3 db2 test.db
+2
View File
@@ -76,6 +76,7 @@ foreach {tn uri file} {
forcedelete $file
do_test 1.$tn.1 { file exists $file } 0
set DB [sqlite3_open $uri]
sqlite3_exec $DB {CREATE TABLE t1(x)}
do_test 1.$tn.2 { file exists $file } 1
sqlite3_close $DB
forcedelete $file
@@ -83,6 +84,7 @@ foreach {tn uri file} {
do_test 1.$tn.3 { file exists $file } 0
sqlite3 db xxx.db
catchsql { ATTACH $uri AS aux }
db eval {CREATE TABLE aux.t1(x)}
do_test 1.$tn.4 { file exists $file } 1
db close
}
+2 -2
View File
@@ -56,8 +56,8 @@ do_faultsim_test wal4-2 -prep {
if { $testrc==0 && [file exists test.db-wal] } {
error "Wal file was not deleted"
}
if { [file size test.db]!=0 } {
error "Db file grew to [file size test.db] bytes"
if { [file_size test.db]!=0 } {
error "Db file grew to [file_size test.db] bytes"
}
}
+2 -2
View File
@@ -210,7 +210,7 @@ do_test where8-3.4 {
do_test where8-3.5 {
execsql_status {
SELECT a, d FROM t1, t2 WHERE (a = 2 OR a = 3) AND (d = a OR e = 'sixteen')
SELECT a, d FROM t1, t2 WHERE (a = 2 OR a = 3) AND (d = +a OR e = 'sixteen')
ORDER BY +a, +d;
}
} {2 2 2 4 3 3 3 4 0 1}
@@ -222,7 +222,7 @@ do_test where8-3.6 {
execsql_status {
SELECT a, d
FROM t1, t2
WHERE (a = 2 OR a = 3) AND (d = a OR e = 'sixteen')
WHERE (a = 2 OR a = 3) AND (d = +a OR e = 'sixteen')
ORDER BY t1.rowid
}
} {2 2 2 4 3 3 3 4 0 1}
+12 -1
View File
@@ -816,5 +816,16 @@ do_execsql_test 11.3 {
.........Noland
.........Olivia}}
finish_test
#--------------------------------------------------------------------------
# Ticket [31a19d11b97088296ac104aaff113a9790394927] (2014-02-09)
# Name resolution issue with compound SELECTs and Common Table Expressions
#
do_execsql_test 12.1 {
WITH RECURSIVE
t1(x) AS (VALUES(2) UNION ALL SELECT x+2 FROM t1 WHERE x<20),
t2(y) AS (VALUES(3) UNION ALL SELECT y+3 FROM t2 WHERE y<20)
SELECT x FROM t1 EXCEPT SELECT y FROM t2 ORDER BY 1;
} {2 4 8 10 14 16 20}
finish_test