Compare commits

..

44 Commits

Author SHA1 Message Date
drh 425ab50c8f Change more OP_OpenEphemeral operations to OP_OpenHash.
FossilOrigin-Name: 881164cf6e5c987ae0e40804267715d878135198
2014-02-06 14:59:47 +00:00
drh 5eba9b73da Use OpenHash instead of OpenEphemeral for the RHS of IN operators if the
result is not needed for sorting.

FossilOrigin-Name: 715fac7749a6b1523fe9f7de8263f0c4d1571d07
2014-02-06 03:31:41 +00:00
drh 34c5ed29e8 Separate out the code generators for the RHS of an IN operator and for
SELECT/EXISTS expressions.

FossilOrigin-Name: 61c34ba71b733b81312078d90c1e21a8cbad669a
2014-02-05 19:10:06 +00:00
drh e255f2d2ce Use a new opcode, OP_OpenHash, to indicate that ephemeral tables can be
unordered, rather than using the BTREE_UNORDERED bit in the P5 field.

FossilOrigin-Name: 2997e181575da7e37fe70d20bdddf934f064ae1d
2014-02-05 18:15:38 +00:00
drh c3caa4f091 Make the root page of an ephemeral index be page 1 instead of page 2.
FossilOrigin-Name: a332908b70afa4e77e60b30a3b96d8a8504363a2
2014-02-05 17:08:07 +00:00
mistachkin 5dfd3d9080 In the Win32 VFS, the winSysInfo variable should be static.
FossilOrigin-Name: 4a4dd371a72b7d475185923bebb4cd9bd83e1bd9
2014-02-05 11:05:47 +00:00
drh e08ecad58a Do not mark the ephemeral tables used to hold the RHS of IN clauses as
unordered because the NGQP will use those ephemeral tables to help order the
output.  This is not an issue for standard SQLite since ephemeral tables
there are always ordered, regardless of the hint.  It only affects systems
that substitute an alternative storage engine.

FossilOrigin-Name: f2504089df0bf4011864e67825b37f6aa3d03458
2014-02-04 23:45:45 +00:00
drh ee06c99b49 Remove the SF_Materialize flag from the SELECT object as it does not
accomplish anything useful.

FossilOrigin-Name: 65d5dcddbd34dfb2733a7a908c7c652ce2d610fe
2014-02-04 20:46:41 +00:00
drh 7df89c8c8a Rearrange fields in the Parse object for a tighter packing, resulting in
an 8% size reduction on x64.

FossilOrigin-Name: 3e1a3f68d7457ff708222a3448404b593f018fc2
2014-02-04 15:55:25 +00:00
drh fe21a796f7 Performance optimizations in sqlite3PcacheFetch().
FossilOrigin-Name: b60cc11ef775c23a2245d9e7a00dab34013f3ccb
2014-02-03 17:04:29 +00:00
drh e39a732ce2 Provide hints to the btree layer Next and Previous primitives to let them
know if they can be no-ops if the underlying index is unique.

FossilOrigin-Name: 6c643e45c274e755dc5a1a65673df79261c774be
2014-02-03 14:04:11 +00:00
drh 6645370e5b Version 3.8.3
FossilOrigin-Name: e816dd924619db5f766de6df74ea2194f3e3b538
2014-02-03 13:52:03 +00:00
drh dd31490e02 Minor change to TEA extension docs in an attempt to make links work correctly.
FossilOrigin-Name: af3c775e5d6a399bfc985a5dae27451908766546
2014-02-03 13:49:40 +00:00
drh d49c545968 Update the "sqlite3.1" unix manpage document.
FossilOrigin-Name: 21ce9e3a53aed62fbe075b0dbed9faa00218aadc
2014-01-31 11:50:20 +00:00
mistachkin a3fdec7172 Minor change to TEA extension docs in an attempt to make links work correctly.
FossilOrigin-Name: 492585c8208457120dde24f5fbf4db7e4e10ae73
2014-01-31 06:35:37 +00:00
drh bb44b3de39 Update evidence marks on SELECT tests. Comment changes only.
No changes to code or tests.

FossilOrigin-Name: 1973d80e474cb95d053e04415b22154897d4d710
2014-01-30 17:47:02 +00:00
drh 9a2555f538 Fix requirements marks only. No changes to code or tests.
FossilOrigin-Name: 4a34378b9b02e463081729186dcb9b0404dbcd06
2014-01-30 15:03:50 +00:00
drh a88aca5442 Update a requirement mark and add some additional test cases to cover
the requirement associated with ORDER BY and LIMIT on compound SELECT
statements.

FossilOrigin-Name: 8560091e85f2f99a24810648868bf2e081c32698
2014-01-30 14:10:00 +00:00
mistachkin b8e59bcb86 Enhance the MSVC makefile for better debugging symbol support.
FossilOrigin-Name: c9bef0f29a5a7f04914d80e58105104babd4168c
2014-01-30 12:45:32 +00:00
dan 81a034b62b Do not run test script mmapfault.test as part of the "inmemory_journal" permutation test.
FossilOrigin-Name: b222b61a98dc1f3c2c48ea06efe7d82d9fcf4d75
2014-01-30 12:16:23 +00:00
mistachkin b04275121c Enhance the MSVC makefile for better debugging symbol support.
FossilOrigin-Name: c723ec2784d6b60c9781a435c84800b2bc7818d5
2014-01-30 11:12:52 +00:00
drh ec2da85412 Make sure that sqlite3SelectDup() initializes the nSelectRow of the
duplicate Select object.

FossilOrigin-Name: 5bb29b82109224a2ad02920658fabd8fb0f27b3f
2014-01-29 01:46:12 +00:00
drh db718d8a3b Fix harmless compiler warnings in the showdb utility program.
FossilOrigin-Name: 27c27daa3324b7c9323acfb972330367630bb64e
2014-01-28 20:36:22 +00:00
drh 4d06798e56 Fix a potential over-size and hence undefined shift operation.
FossilOrigin-Name: 6379b0729521146bc4ec27a9924492c7dc1d8a31
2014-01-28 18:53:29 +00:00
dan 9c2552f2e8 Minor bugfix in main.c so that the library builds with SQLITE_OMIT_WSD defined.
FossilOrigin-Name: 5e3b9ecc7b2b2e50952de819b99bafdb7b9ff59e
2014-01-28 17:49:13 +00:00
dan 705a48758a Fix a couple of problems with new test scripts causing the permutations test to fail.
FossilOrigin-Name: 48d736c0ee1ac0879bd12d2f1901f208e87e538a
2014-01-27 16:35:15 +00:00
drh a820c05aa0 Update some requirements marks to conform with improvements
in the documentation.

FossilOrigin-Name: be1acb610f7e594b417dd8409b7a7aa8f3af5f77
2014-01-27 15:02:07 +00:00
dan d0879bad42 Fix a problem in pagerfault.test causing an assert() to fail.
FossilOrigin-Name: ba8d2d507f82e2baaceadcf7ac6d71bb91f7e06b
2014-01-27 14:19:22 +00:00
drh 729677720d Fix (harmless) duplicate variable declaration.
FossilOrigin-Name: 94ed9bc4207873e0f3f8114009002f56d5aff359
2014-01-27 13:58:58 +00:00
dan abfe034692 Fix some problems in test scripts. No code changes.
FossilOrigin-Name: 08acfc65877e207f1a62d31a14afb4add20c4c35
2014-01-27 08:48:10 +00:00
dan b68b97789e Fix a problem causing SQLITE_OMIT_COMPOUND_SELECT builds to fail.
FossilOrigin-Name: b30db0ac3096b43d55a6da40cafc7de569082bf8
2014-01-25 12:16:53 +00:00
drh 693e671936 Fixes for various clang warnings.
FossilOrigin-Name: 87bf60637e5863c54c5e2d05aaaca0835b7aace8
2014-01-24 22:58:00 +00:00
dan 53bed45ecb Select collation sequences for ORDER BY expressions attached to recursive CTEs in the same way as they are selected for other compound SELECT statements.
FossilOrigin-Name: 9554519c126c5e714421a82fd2e8aa9b19e11493
2014-01-24 20:37:18 +00:00
mistachkin 6ef5e12e1f Fix harmless compiler warnings in the Tcl interface.
FossilOrigin-Name: 35bc81f5ad4503c0db03127ba3c2ee4ce5227448
2014-01-24 17:03:55 +00:00
dan 05d3dc29c5 Add test cases for LIMIT and ORDER BY on recursive CTEs.
FossilOrigin-Name: 67d6c42d44cb191368ce20f553b32fcb14bfc4d7
2014-01-24 16:57:42 +00:00
drh dc3bb0deb2 Use an unsigned integer to accumulate the string hash. Avoids compiler
warnings.

FossilOrigin-Name: b1824344ea4918a13abbda4a3b7134d35fd867c4
2014-01-24 16:36:18 +00:00
drh 9e2c7ae1b0 Add a few more CTE test cases to closure.test.
FossilOrigin-Name: 1b6405d9788c1bb89761b2bcdce560a5020ff503
2014-01-24 15:42:51 +00:00
drh 3c2aeae16e Add test cases that compare the performance of the transitive_closure
virtual table again common table expressions for walking a tree.

FossilOrigin-Name: 9a23f020e8ed0e7a1ad227b4ab379fdf5e2de222
2014-01-24 14:37:44 +00:00
drh b090352b5a Add test cases showing the use of ORDER BY on a recursive query to control
depth-first versus breath-first search of a tree.

FossilOrigin-Name: 83b0b2916589db0184435dbd4c304387f393ed60
2014-01-24 11:16:01 +00:00
dan afcf9bd806 Modifications to test files to omit any tests that intentionally access out-of-bounds locations in clang -fsanitize=address builds.
FossilOrigin-Name: f4a701d55f5c4e1e62ed64b779ad4fff89dd31b7
2014-01-23 14:44:08 +00:00
dan cfe24586a8 Avoid an extra seek when inserting records into the epheremal index used to ensure that rows returned by UNION recursive queries are unique.
FossilOrigin-Name: 72c4b3f07a3faacb5b62d5bc374b4e125a0bd8b3
2014-01-22 19:23:30 +00:00
drh edf83d1e3d Fix harmless compiler warnings.
FossilOrigin-Name: dea2ca6a159d5dcfd8deceedf1c2a73fb4ac1cfc
2014-01-22 18:31:27 +00:00
drh 953dfa4e60 Change the WITH RECURSIVE implementation to use a queue instead of a pair of
tables.  Add support for ORDER BY, LIMIT, and OFFSET on recursive queries.

FossilOrigin-Name: b6cea42006910d590373e8f9e296d7672edb114b
2014-01-22 18:16:27 +00:00
dan a8a0617e06 Update the spellfix virtual table to optimize queries of the form "SELECT ... FROM tbl WHERE rowid=?".
FossilOrigin-Name: a0ba55ff0596c5f15e9cdb254c68ef50df2dfaad
2014-01-22 17:43:16 +00:00
54 changed files with 1449 additions and 696 deletions
+21 -10
View File
@@ -270,6 +270,17 @@ TCC = $(TCC) -I$(TOP)\ext\rtree
RCC = $(RCC) -I$(TOP)\ext\rtree
!ENDIF
# The mksqlite3c.tcl script accepts some options on the command
# line. When compiling with debugging enabled, some of these
# options are necessary in order to allow debugging symbols to
# work correctly with Visual Studio when using the amalgamation.
#
!IF $(DEBUG)>0
MKSQLITE3C_ARGS = --linemacros
!ELSE
MKSQLITE3C_ARGS =
!ENDIF
# Define -DNDEBUG to compile without debugging (i.e., for production usage)
# Omitting the define will cause extra debugging code to be inserted and
# includes extra comments when "EXPLAIN stmt" is used.
@@ -916,7 +927,7 @@ mptester.exe: $(TOP)\mptest\mptest.c libsqlite3.lib $(LIBRESOBJS) sqlite3.h
echo > .target_source
sqlite3.c: .target_source $(TOP)\tool\mksqlite3c.tcl
$(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl
$(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl $(MKSQLITE3C_ARGS)
copy tsrc\shell.c .
copy tsrc\sqlite3ext.h .
@@ -1334,17 +1345,17 @@ sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
$(LTLINK) -DBUILD_sqlite -DTCLSH=2 -I$(TCLINCDIR) sqlite3_analyzer.c \
/link $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
showdb.exe: $(TOP)\tool\showdb.c sqlite3.c
$(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o $@ \
$(TOP)\tool\showdb.c sqlite3.c
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C)
$(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\tool\showdb.c $(SQLITE3C)
wordcount.exe: $(TOP)\test\wordcount.c sqlite3.c
$(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o $@ \
$(TOP)\test\wordcount.c sqlite3.c
wordcount.exe: $(TOP)\test\wordcount.c $(SQLITE3C)
$(LTLINK) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\test\wordcount.c $(SQLITE3C)
speedtest1.exe: $(TOP)\test\speedtest1.c sqlite3.c
$(LTLINK) -DSQLITE_OMIT_LOAD_EXTENSION -o $@ \
$(TOP)\test\speedtest1.c sqlite3.c
speedtest1.exe: $(TOP)\test\speedtest1.c $(SQLITE3C)
$(LTLINK) -DSQLITE_OMIT_LOAD_EXTENSION -Fe$@ \
$(TOP)\test\speedtest1.c $(SQLITE3C)
clean:
del /Q *.lo *.ilk *.lib *.obj *.pdb sqlite3.exe libsqlite3.lib
+2 -2
View File
@@ -11,5 +11,5 @@ SQLite3 is a self-contains, zero-configuration, transactional SQL database
engine. This extension provides an easy to use interface for accessing
SQLite database files from Tcl.
.PP
For full documentation see http://www.sqlite.org/ and
in particular http://www.sqlite.org/tclsqlite.html.
For full documentation see \fIhttp://www.sqlite.org/\fR and
in particular \fIhttp://www.sqlite.org/tclsqlite.html\fR.
+2 -2
View File
@@ -96,13 +96,13 @@ void sqlite3Fts3HashClear(Fts3Hash *pH){
*/
static int fts3StrHash(const void *pKey, int nKey){
const char *z = (const char *)pKey;
int h = 0;
unsigned h = 0;
if( nKey<=0 ) nKey = (int) strlen(z);
while( nKey > 0 ){
h = (h<<3) ^ h ^ *z++;
nKey--;
}
return h & 0x7fffffff;
return (int)(h & 0x7fffffff);
}
static int fts3StrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
if( n1!=n2 ) return 1;
+28 -4
View File
@@ -2051,6 +2051,7 @@ static int spellfix1Close(sqlite3_vtab_cursor *cur){
** (D) scope = $scope
** (E) distance < $distance
** (F) distance <= $distance
** (G) rowid = $rowid
**
** The plan number is a bit mask formed with these bits:
**
@@ -2060,8 +2061,9 @@ static int spellfix1Close(sqlite3_vtab_cursor *cur){
** 0x08 (D) is found
** 0x10 (E) is found
** 0x20 (F) is found
** 0x40 (G) is found
**
** filter.argv[*] values contains $str, $langid, $top, and $scope,
** filter.argv[*] values contains $str, $langid, $top, $scope and $rowid
** if specified and in that order.
*/
static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
@@ -2070,6 +2072,7 @@ static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
int iTopTerm = -1;
int iScopeTerm = -1;
int iDistTerm = -1;
int iRowidTerm = -1;
int i;
const struct sqlite3_index_constraint *pConstraint;
pConstraint = pIdxInfo->aConstraint;
@@ -2122,6 +2125,15 @@ static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
iPlan |= pConstraint->op==SQLITE_INDEX_CONSTRAINT_LT ? 16 : 32;
iDistTerm = i;
}
/* Terms of the form: distance < $dist or distance <= $dist */
if( (iPlan & 64)==0
&& pConstraint->iColumn<0
&& pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ
){
iPlan |= 64;
iRowidTerm = i;
}
}
if( iPlan&1 ){
int idx = 2;
@@ -2149,6 +2161,11 @@ static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
pIdxInfo->aConstraintUsage[iDistTerm].omit = 1;
}
pIdxInfo->estimatedCost = 1e5;
}else if( (iPlan & 64) ){
pIdxInfo->idxNum = 64;
pIdxInfo->aConstraintUsage[iRowidTerm].argvIndex = 1;
pIdxInfo->aConstraintUsage[iRowidTerm].omit = 1;
pIdxInfo->estimatedCost = 5;
}else{
pIdxInfo->idxNum = 0;
pIdxInfo->estimatedCost = 1e50;
@@ -2465,16 +2482,23 @@ static int spellfix1FilterForFullScan(
int argc,
sqlite3_value **argv
){
int rc;
int rc = SQLITE_OK;
char *zSql;
spellfix1_vtab *pVTab = pCur->pVTab;
spellfix1ResetCursor(pCur);
assert( idxNum==0 || idxNum==64 );
zSql = sqlite3_mprintf(
"SELECT word, rank, NULL, langid, id FROM \"%w\".\"%w_vocab\"",
pVTab->zDbName, pVTab->zTableName);
"SELECT word, rank, NULL, langid, id FROM \"%w\".\"%w_vocab\"%s",
pVTab->zDbName, pVTab->zTableName,
((idxNum & 64) ? " WHERE rowid=?" : "")
);
if( zSql==0 ) return SQLITE_NOMEM;
rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pFullScan, 0);
sqlite3_free(zSql);
if( rc==SQLITE_OK && (idxNum & 64) ){
assert( argc==1 );
rc = sqlite3_bind_value(pCur->pFullScan, 1, argv[0]);
}
pCur->nRow = pCur->iRow = 0;
if( rc==SQLITE_OK ){
rc = sqlite3_step(pCur->pFullScan);
+57 -57
View File
@@ -1,9 +1,9 @@
C Add\ssupport\sfor\sLIMIT\sand\sOFFSET\sin\sa\srecursive\squery.
D 2014-01-22T18:07:04.473
C Change\smore\sOP_OpenEphemeral\soperations\sto\sOP_OpenHash.
D 2014-02-06T14:59:47.807
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc 4d4ead6b71d1bf03028fbd61da0ba0ec5e1556e1
F Makefile.msc 6ff3ff2eef45c7dd309a8626ff7947b20bd387e7
F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
F VERSION 8ed548d87d0a27fd7d7620476f9e25f9fa742d73
@@ -27,7 +27,7 @@ F autoconf/tea/Makefile.in 5c3b0bdfb66c20d55ebff59d1718864461570ca9
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
F autoconf/tea/configure.in e0466b881b53f31f5a4a69e7a91ad130902fb359
F autoconf/tea/doc/sqlite3.n e268faa1691c33663d3a7faf9fa30673d14bd879
F autoconf/tea/doc/sqlite3.n e1fe45d4f5286ee3d0ccc877aca2a0def488e9bb
F autoconf/tea/license.terms 13bd403c9610fd2b76ece0ab50c4c5eda933d523
F autoconf/tea/pkgIndex.tcl.in 3ef61715cf1c7bdcff56947ffadb26bc991ca39d
F autoconf/tea/tclconfig/install-sh b087e5c4b92820c60bffb74acc1d9c2d40d80b8f
@@ -83,7 +83,7 @@ F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h eb5f8029589f3d8f1dc7fd50c773326a640388b1
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
F ext/fts3/fts3_expr.c 5165c365cb5a035f5be8bb296f7aa3211d43e4ac
F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
F ext/fts3/fts3_porter.c 7f8b4bf5af7c0f20f73b8e87e14fa9298f52e290
@@ -114,7 +114,7 @@ F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/spellfix.c 76578f2c56ceaa23d22032338d90db79c68490fb
F ext/misc/spellfix.c adfc569fafef7a1eb8f21528e5277686b358c3ce
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
@@ -157,7 +157,7 @@ F mptest/mptest.c 499a74af4be293b7c1c7c3d40f332b67227dd739
F mptest/multiwrite01.test 499ad0310da8dff8e8f98d2e272fc2a8aa741b2e
F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
F src/analyze.c 581d5c18ce89c6f45d4dca65914d0de5b4dad41f
@@ -166,29 +166,29 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 02e1a4e71d8fc37e9fd5216c15d989d148a77c87
F src/btree.h a61ddebc78c66795a2b93181321a116746302cc9
F src/btree.c ae408b77caf025df8c1baab52aad8a5a393bed35
F src/btree.h f1c65e0511d7a228fd1a7c7463ef842525364348
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
F src/build.c 7e6c275ab1731510d6f793d0f88373ab3e858e69
F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c 91e1321021db5dc266360531b8b6550009d771ff
F src/expr.c 8c7e482bc8f7982333f046851a610ccdb8a1ba94
F src/delete.c 3987ac3e32f6a447b1f3ca0268d67bdaf0a8b97f
F src/expr.c fa9cd9b4bdc8989efce99d49c7e46484e17f41f4
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5
F src/func.c 6325ac2ec10833ccf4d5c36d323709221d37ea19
F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5
F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c a4450f0c46a9f221622e6551ab0953b03c4f8ee8
F src/insert.c c6b4ba486e62d0b600632fdfce4bca76213158cb
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
F src/main.c 4a05a9706579c7649d7eebb0094586728eb53fcb
F src/main.c 07225af6a00be0b7f34ac52e60f99cf5cbb2a475
F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
@@ -205,38 +205,38 @@ 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 3a4dcb554d3c915075766162f28c3fd4cdb75968
F src/os_win.c 1b21af72c5fa6f9e519a5fcab33e80d182b1aedb
F src/os_unix.c f3ed0e406cbf9c820565b2118232d0796346130f
F src/os_win.c d4284f003445054a26689f1264b1b9bf7261bd1b
F src/pager.c efa923693e958696eee69b205a20bfbc402c8480
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
F src/parse.y 475896cb883bbf4782e98abda42efbbdcbdb75f5
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
F src/parse.y bd51bc17cbfe7549adb4ca3747b1c3d384645065
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 57fee9a9a617218f5037afbbe49b09da65bde56b
F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c
F src/pragma.c ed409ce4104cf4d9de6ead40ace70974f124853b
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
F src/select.c f6d84f3a109d3e43d38089da6a4f131a5ce4c6ef
F src/select.c d1acf45637f70d71a76cb8312507550e3aee6caa
F src/shell.c 24722d24d4ea8ca93db35e44db7308de786767ca
F src/sqlite.h.in eed7f7d66a60daaa7b4a597dcd9bad87aad9611b
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h 87a90ad4818ac5d68d3463eb7fe3ed96e5209b25
F src/sqliteInt.h 29b97acb02309ad07de107a81c381512066fc2e4
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 46073db71011b6542fde1f234c56a076d5ff23f9
F src/test1.c db16ba651453b15001c7f2838c446284dde4ecaf
F src/tclsqlite.c 21ca0043d7c48cde5dabed5c1116eee1be692f62
F src/test1.c 2401eee14a4309a7cfe2aeb2f30ad517a1d9c299
F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
F src/test5.c a6d1ac55ac054d0b2b8f37b5e655b6c92645a013
F src/test6.c 41cacf3b0dd180823919bf9e1fbab287c9266723
F src/test7.c 72b732baa5642f795655ba1126ea032af46ecfd2
F src/test8.c c7aab1d9fbbf54fc33d43b73aa24aa55f9eaf534
F src/test8.c 54ccd7b1df5062f0ecbf50a8f7b618f8b1f13b20
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
@@ -276,25 +276,25 @@ 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 c2706a6eb232a96345c35b7e1e75a188e26812bb
F src/update.c 3d2bdfe24d78303cf7fd3017aaa2d848d47a1020
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
F src/util.c e71f19b272f05c8695cf747b4bac1732685f9e5c
F src/util.c 15ac2627f548f5481d0d7e6c4eb67be673027695
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
F src/vdbe.c dede894c2990329f8bc5a70da7de44ce8c3c6bf5
F src/vdbe.c 2e46c464e910cf0f11acf6690e8f72d7239a5f63
F src/vdbe.h e6c4c610fcabad4fa80ebb1efc6822a9367e2b26
F src/vdbeInt.h 42db251e9f863401ff847b90d5fe1614c89a6a56
F src/vdbeapi.c ce4e68ea4842cc6081046f533d088dcf01d247ad
F src/vdbeaux.c 9f4bfc52672acbb0bb4493d6a03603dc5a595ac1
F src/vdbeaux.c a3327afa8cfcc5bb3d38f2b2a599bac5fb63c6be
F src/vdbeblob.c bc40f98f256f0b34116d6a44b114da4a81a15d33
F src/vdbemem.c 0e69351b2c6ff7d8b638688c0ae336a26befa6b2
F src/vdbemem.c 23cdc14ed43e0aafa57bd72b9bf3d5b1641afa91
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 67ae3b5e97ecff36c70cb61ccc7d74cf228f1596
F src/whereInt.h 96a75c61f1d2b9d4a8e4bb17d89deb0cf7cba358
F src/where.c 087307272e374c35c7eb1eb722f0ab7db09317f2
F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
@@ -364,15 +364,15 @@ F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de
F test/capi2.test 011c16da245fdc0106a2785035de6b242c05e738
F test/capi3.test 56ab450125ead38846cbae7e5b6a216686c3cffa
F test/capi3.test 6cdd49656bd62a296924f4d2fcfd05cd2a298369
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
F test/capi3c.test 93d24621c9ff84da9da060f30431e0453db1cdb0
F test/capi3c.test a21869e4d50d5dbb7e566e328fc0bc7c2efa6a32
F test/capi3d.test 6d0fc0a86d73f42dd19a7d8b7761ab9bc02277d0
F test/capi3e.test ad90088b18b0367125ff2d4b5400153fd2f99aab
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
F test/check.test 5831ddb6f2c687782eaf2e1a07b6e17f24c4f763
F test/close.test 340bd24cc58b16c6bc01967402755027c37eb815
F test/closure01.test dbb28f1ea9eeaf0a53ec5bc0fed352e479def8c7
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
F test/collate1.test 73b91005f264b7c403e2d63a6708d150679ac99a
F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621
@@ -406,7 +406,7 @@ F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
F test/corruptG.test c150f156dace653c00a121ad0f5772a0568c41ba
F test/corruptH.test 0a247f3dc8a8f3578db5f639d86c6bb4d520207f
F test/corruptH.test 9d8186f6f8751efdfd445d8546fd98f073499039
F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5
F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
@@ -432,20 +432,20 @@ F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240
F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
F test/distinct.test 44028aaf161a5e80a2f229622b3a174d3b352810
F test/distinct.test b9f34f3827a67baf5b5bcb1cdf5185963d629d49
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
F test/e_createtable.test ee95d48664503d40f6cc9ef4a7d03216188e2ada
F test/e_delete.test d5186e2f5478b659f16a2c8b66c09892823e542a
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306
F test/e_expr.test 5c71d183fbf519a4769fd2e2124afdc70b5b1f42
F test/e_fkey.test d83a04478bb9c02d2c513518548a69f818869f41
F test/e_fkey.test 630597377549af579d34faaf64c6959a5a68ef76
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
F test/e_insert.test 1e44f84d2abe44d66e4fbf198be4b20e3cc724a0
F test/e_reindex.test 396b7b4f0a66863b4e95116a67d93b227193e589
F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
F test/e_select.test d3226cb94fae4af3f198e68e71f655e106d0be47
F test/e_select2.test 22c660a7becf0712c95e1ca1b2d9e716a1261460
F test/e_select.test 52692ff3849541e828ad4661fe3773a9b8711763
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
F test/e_update.test 312cb8f5ccfe41515a6bb092f8ea562a9bd54d52
F test/e_uri.test a2c92d80093a7efdcfbb11093651cbea87097b6b
F test/e_vacuum.test 5bfbdc21b65c0abf24398d0ba31dc88d93ca77a9
@@ -593,9 +593,9 @@ F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
F test/in3.test dbf41c0c073c10a8c0fee280cba3e9dddbd4a9c6
F test/in4.test 64f3cc1acde1b9161ccdd8e5bde3daefdb5b2617
F test/in5.test 99f9a40af01711b06d2d614ecfe96129f334fba3
F test/in5.test 9d8c15bfc9a06da5b354d4d4ecfea9f928769641
F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328
F test/incrblob2.test bf4d549aa4a466d7fbe3e3a3693d3861263d5600
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
@@ -700,8 +700,8 @@ F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
F test/misc5.test 528468b26d03303b1f047146e5eefc941b9069f5
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
F test/misc7.test 1265eb98c2e22a446a13fdef754118b272716684
F test/misuse.test ba4fb5d1a6101d1c171ea38b3c613d0661c83054
F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2
F test/misuse.test 3c34719944ba045cc6c188a4852ba04680728912
F test/mmap1.test 93d167b328255cbe6679fe1e1a23be1b1197d07b
F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
F test/mmap3.test c92273e16eb8d23c1d55c9815b446bb72ef0512e
@@ -728,8 +728,8 @@ F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
F test/pager4.test b40ecb4cc7dff957ee7916e41ab21d1ed702a642
F test/pagerfault.test 7285379906ab2f1108b8e82bbdf2d386cc8ff3ff
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
F test/pagerfault.test ae9ee0db5a30aecda9db8290ce3dd12e5f7bbaa1
F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6
@@ -737,11 +737,11 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
F test/permutations.test af3278cbea3a19e025d5169be8193ff48dc3f862
F test/permutations.test 40add071ba71aefe1c04f5845308cf46f7de8d04
F test/pragma.test e882183ecd21d064cec5c7aaea174fbd36293429
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
F test/printf2.test 414fcba6d6c10e0a5e58efd213811e5ead4635a0
F test/printf2.test bed79b4c3e5da08ba88ad637c0bf62586843cfb1
F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
@@ -783,7 +783,7 @@ F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
F test/select4.test 00179be44e531fe04c1c3f15df216439dff2519d
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
F test/select6.test e76bd10a56988f15726c097a5d5a7966fe82d3b2
F test/select7.test dad6f00f0d49728a879d6eb6451d4752db0b0abe
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
F test/selectA.test 99cf21df033b93033ea4f34aba14a500f48f04fe
@@ -825,7 +825,7 @@ F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c 7130d2cb6db45baa553a4ab2f715116c71c2d9f4
F test/spellfix.test 8c40b169b104086d8795781f670ba3c786d6d8be
F test/spellfix.test 61309f5efbec53603b3f86457d34a504f80abafe
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
@@ -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 08e9f317afe60d398fa900993503ecaef3295bad
F test/tester.tcl 9bd04481b8b0ef1f2049ad01f28e175ee9a14f7b
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -1092,7 +1092,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 97166cc72de5327bbae782aece707c45ee40e41b
F test/with1.test ce15d69d34a2576b0e47d78c244d1ba2a31679d1
F test/with2.test 2fe78fcd8deef2a0f9cfc49bfc755911d0b3fd64
F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991
F test/without_rowid1.test aaa26da19d543cd8d3d2d0e686dfa255556c15c8
@@ -1127,12 +1127,12 @@ F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12
F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795
F tool/mkvsix.tcl 6477fb9dab838b7eea1eed50658ff1cda04850b5
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
F tool/omittest.tcl 4665982e95a6e5c1bd806cf7bc3dea95be422d77
F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
F tool/showdb.c 525ecc443578647703051308ad50a93de6ba2c4b
F tool/showdb.c 1f3fe634d6f690b8d39ab1b9fd34583d468921e1
F tool/showjournal.c b62cecaab86a4053d944c276bb5232e4d17ece02
F tool/showwal.c 3f7f7da5ec0cba51b1449a75f700493377da57b5
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
@@ -1152,7 +1152,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 37b343b01841b338954ddfa9b76d92aa50037aec
R f6fa1b44c6431db29f11962241b14895
P 715fac7749a6b1523fe9f7de8263f0c4d1571d07
R f507eae713e5b72113d4535fdf641347
U drh
Z a802989c6813792648a40d2b5db727ef
Z 759564bb3627cf7a97644b4104ef33de
+1 -1
View File
@@ -1 +1 @@
1945484e6b9769c1943f750f5b09860417fb190a
881164cf6e5c987ae0e40804267715d878135198
+73 -23
View File
@@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH SQLITE3 1 "Mon Apr 15 23:49:17 2002"
.TH SQLITE3 1 "Mon Jan 31 11:14:00 2014"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@@ -49,7 +49,7 @@ a table named "memos" and insert a couple of records into that table:
$
.B sqlite3 mydata.db
.br
SQLite version 3.1.3
SQLite version 3.8.3
.br
Enter ".help" for instructions
.br
@@ -108,15 +108,24 @@ sqlite>
.B .help
.nf
.cc |
.backup ?DB? FILE Backup DB (default "main") to FILE
.bail ON|OFF Stop after hitting an error. Default OFF
.databases List names and files of attached databases
.dump ?TABLE? ... Dump the database in an SQL text format
If TABLE specified, only dump tables matching
LIKE pattern TABLE.
.echo ON|OFF Turn command echo on or off
.exit Exit this program
.explain ON|OFF Turn output mode suitable for EXPLAIN on or off.
.explain ?ON|OFF? Turn output mode suitable for EXPLAIN on or off.
With no args, it turns EXPLAIN on.
.header(s) ON|OFF Turn display of headers on or off
.help Show this message
.import FILE TABLE Import data from FILE into TABLE
.indices TABLE Show names of all indices on TABLE
.indices ?TABLE? Show names of all indices
If TABLE specified, only show indices for tables
matching LIKE pattern TABLE.
.load FILE ?ENTRY? Load an extension library
.log FILE|off Turn logging on or off. FILE can be stderr/stdout
.mode MODE ?TABLE? Set output mode where MODE is one of:
csv Comma-separated values
column Left-aligned columns. (See .width)
@@ -126,46 +135,76 @@ sqlite>
list Values delimited by .separator string
tabs Tab-separated values
tcl TCL list elements
.nullvalue STRING Print STRING in place of NULL values
.nullvalue STRING Use STRING in place of NULL values
.open ?FILENAME? Close existing database and reopen FILENAME
.output FILENAME Send output to FILENAME
.output stdout Send output to the screen
.print STRING... Print literal STRING
.prompt MAIN CONTINUE Replace the standard prompts
.quit Exit this program
.read FILENAME Execute SQL in FILENAME
.restore ?DB? FILE Restore content of DB (default "main") from FILE
.schema ?TABLE? Show the CREATE statements
If TABLE specified, only show tables matching
LIKE pattern TABLE.
.separator STRING Change separator used by output mode and .import
.show Show the current values for various settings
.tables ?PATTERN? List names of tables matching a LIKE pattern
.stats ON|OFF Turn stats on or off
.tables ?TABLE? List names of tables
If TABLE specified, only list tables matching
LIKE pattern TABLE.
.timeout MS Try opening locked tables for MS milliseconds
.width NUM NUM ... Set column widths for "column" mode
.trace FILE|off Output each SQL statement as it is run
.vfsname ?AUX? Print the name of the VFS stack
.width NUM1 NUM2 ... Set column widths for "column" mode
.timer ON|OFF Turn the CPU timer measurement on or off
sqlite>
|cc .
.sp
.fi
.SH OPTIONS
.B sqlite3
has the following options:
.TP
.BI \-init\ file
Read and execute commands from
.I file
, which can contain a mix of SQL statements and meta-commands.
.B \-bail
Stop after hitting an error.
.TP
.B \-echo
Print commands before execution.
.TP
.B \-[no]header
Turn headers on or off.
.B \-batch
Force batch I/O.
.TP
.B \-column
Query results will be displayed in a table like form, using
whitespace characters to separate the columns and align the
output.
.TP
.BI \-cmd\ command
run
.I command
before reading stdin
.TP
.B \-csv
Set output mode to CSV (comma separated values).
.TP
.B \-echo
Print commands before execution.
.TP
.BI \-init\ file
Read and execute commands from
.I file
, which can contain a mix of SQL statements and meta-commands.
.TP
.B \-[no]header
Turn headers on or off.
.TP
.B \-help
Show help on options and exit.
.TP
.B \-html
Query results will be output as simple HTML tables.
.TP
.B \-interactive
Force interactive I/O.
.TP
.B \-line
Query results will be displayed with one value per line, rows
separated by a blank line. Designed to be easily parsed by
@@ -175,18 +214,28 @@ scripts or other programs
Query results will be displayed with the separator (|, by default)
character between each field value. The default.
.TP
.BI \-separator\ separator
Set output field separator. Default is '|'.
.BI \-mmap\ N
Set default mmap size to
.I N
\.
.TP
.BI \-nullvalue\ string
Set string used to represent NULL values. Default is ''
(empty string).
.TP
.BI \-separator\ separator
Set output field separator. Default is '|'.
.TP
.B \-stats
Print memory stats before each finalize.
.TP
.B \-version
Show SQLite version.
.TP
.B \-help
Show help on options and exit.
.BI \-vfs\ name
Use
.I name
as the default VFS.
.SH INIT FILE
@@ -222,8 +271,9 @@ o All other command line options are processed.
.SH SEE ALSO
http://www.sqlite.org/
.br
The sqlite-doc package
The sqlite3-doc package.
.SH AUTHOR
This manual page was originally written by Andreas Rottmann
<rotty@debian.org>, for the Debian GNU/Linux system (but may be used
by others). It was subsequently revised by Bill Bumgarner <bbum@mac.com>.
by others). It was subsequently revised by Bill Bumgarner <bbum@mac.com> and
further updated by Laszlo Boszormenyi <gcs@debian.hu> .
+28 -5
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, int flags){
static void zeroPage(MemPage *pPage, u8 flags){
unsigned char *data = pPage->aData;
BtShared *pBt = pPage->pBt;
u8 hdr = pPage->hdrOffset;
@@ -2585,6 +2585,7 @@ static int newDatabase(BtShared *pBt){
MemPage *pP1;
unsigned char *data;
int rc;
u8 flags;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pBt->nPage>0 ){
@@ -2607,7 +2608,9 @@ static int newDatabase(BtShared *pBt){
data[22] = 32;
data[23] = 32;
memset(&data[24], 0, 100-24);
zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA );
flags = (pBt->openFlags&BTREE_SINGLE_INDEX) ? PTF_ZERODATA|PTF_LEAF
: PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF;
zeroPage(pP1, flags);
pBt->btsFlags |= BTS_PAGESIZE_FIXED;
#ifndef SQLITE_OMIT_AUTOVACUUM
assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 );
@@ -4777,6 +4780,15 @@ int sqlite3BtreeEof(BtCursor *pCur){
** successful then set *pRes=0. If the cursor
** was already pointing to the last entry in the database before
** this routine was called, then set *pRes=1.
**
** The calling function will set *pRes to 0 or 1. The initial *pRes value
** will be 1 if the cursor being stepped corresponds to an SQL index and
** if this routine could have been skipped if that SQL index had been
** a unique index. Otherwise the caller will have set *pRes to zero.
** Zero is the common case. The btree implementation is free to use the
** initial *pRes value as a hint to improve performance, but the current
** SQLite btree implementation does not. (Note that the comdb2 btree
** implementation does use this hint, however.)
*/
int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
int rc;
@@ -4785,6 +4797,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
assert( cursorHoldsMutex(pCur) );
assert( pRes!=0 );
assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
if( pCur->eState!=CURSOR_VALID ){
rc = restoreCursorPosition(pCur);
@@ -4863,6 +4876,15 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
** successful then set *pRes=0. If the cursor
** was already pointing to the first entry in the database before
** this routine was called, then set *pRes=1.
**
** The calling function will set *pRes to 0 or 1. The initial *pRes value
** will be 1 if the cursor being stepped corresponds to an SQL index and
** if this routine could have been skipped if that SQL index had been
** a unique index. Otherwise the caller will have set *pRes to zero.
** Zero is the common case. The btree implementation is free to use the
** initial *pRes value as a hint to improve performance, but the current
** SQLite btree implementation does not. (Note that the comdb2 btree
** implementation does use this hint, however.)
*/
int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
int rc;
@@ -4870,6 +4892,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
assert( cursorHoldsMutex(pCur) );
assert( pRes!=0 );
assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->atLast = 0;
if( pCur->eState!=CURSOR_VALID ){
@@ -6089,7 +6112,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 */
int pageFlags; /* Value of pPage->aData[0] */
u8 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[] */
@@ -7096,7 +7119,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
** sub-tree headed by the child page of the cell being deleted. This makes
** balancing the tree following the delete operation easier. */
if( !pPage->leaf ){
int notUsed;
int notUsed = 0;
rc = sqlite3BtreePrevious(pCur, &notUsed);
if( rc ) return rc;
}
@@ -7190,7 +7213,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
MemPage *pRoot;
Pgno pgnoRoot;
int rc;
int ptfFlags; /* Page-type flage for the root page of new table */
u8 ptfFlags; /* Page-type flage for the root page of new table */
assert( sqlite3BtreeHoldsMutex(p) );
assert( pBt->inTransaction==TRANS_WRITE );
+5 -4
View File
@@ -56,10 +56,11 @@ int sqlite3BtreeOpen(
** NOTE: These values must match the corresponding PAGER_ values in
** pager.h.
*/
#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 */
#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 */
int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetCacheSize(Btree*,int);
+6 -7
View File
@@ -97,10 +97,8 @@ void sqlite3MaterializeView(
SrcList *pFrom;
sqlite3 *db = pParse->db;
int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
pWhere = sqlite3ExprDup(db, pWhere, 0);
pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
if( pFrom ){
assert( pFrom->nSrc==1 );
pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
@@ -108,10 +106,7 @@ void sqlite3MaterializeView(
assert( pFrom->a[0].pOn==0 );
assert( pFrom->a[0].pUsing==0 );
}
pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
if( pSel ) pSel->selFlags |= SF_Materialize;
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
sqlite3Select(pParse, pSel, &dest);
sqlite3SelectDelete(db, pSel);
@@ -388,7 +383,9 @@ 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. */
** 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. */
pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk!=0 );
nPk = pPk->nKeyCol;
@@ -636,7 +633,9 @@ void sqlite3GenerateRowDelete(
** used by any BEFORE and AFTER triggers that exist. */
sqlite3VdbeAddOp2(v, OP_Copy, iPk, iOld);
for(iCol=0; iCol<pTab->nCol; iCol++){
if( mask==0xffffffff || mask&(1<<iCol) ){
testcase( mask!=0xffffffff && iCol==31 );
testcase( mask!=0xffffffff && iCol==32 );
if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
}
}
+226 -220
View File
@@ -1064,6 +1064,7 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->addrOpenEphm[2] = -1;
pNew->nSelectRow = p->nSelectRow;
pNew->pWith = withDup(db, p->pWith);
return pNew;
}
@@ -1489,6 +1490,177 @@ 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
@@ -1552,15 +1724,19 @@ int sqlite3CodeOnce(Parse *pParse){
**
** 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 sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound, int bOrdered){
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
@@ -1569,11 +1745,11 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
*/
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) */
@@ -1584,25 +1760,14 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
iCol = (i16)pExpr->iColumn;
/* Code an OP_VerifyCookie and OP_TableLock for <table>. */
if( ALWAYS(pTab->pSchema) ){
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
}
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;
iAddr = sqlite3CodeOnce(pParse);
int iAddr = sqlite3CodeOnce(pParse);
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
eType = IN_INDEX_ROWID;
sqlite3VdbeJumpHere(v, iAddr);
}else{
Index *pIdx; /* Iterator variable */
@@ -1657,7 +1822,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
eType = IN_INDEX_ROWID;
}
}
sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
sqlite3CreateInOperatorRhsTable(pParse, pX, eType==IN_INDEX_ROWID,bOrdered);
pParse->nQueryLoop = savedNQueryLoop;
}else{
pX->iTable = iTab;
@@ -1667,56 +1832,37 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
#endif
/*
** Generate code for scalar subqueries used as a subquery expression, EXISTS,
** or IN operators. Examples:
** Generate code for scalar subqueries used as a subquery expression:
**
** (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 IN
** operator or subquery.
** The pExpr parameter describes the expression that contains the subquery.
**
** 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.
** Return the register that holds the result.
*/
#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3CodeSubselect(
static int sqlite3CodeScalarSubquery(
Parse *pParse, /* Parsing context */
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 */
Expr *pExpr /* The SELECT or EXISTS operator */
){
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:
**
** * The right-hand side is a correlated subquery
** * The right-hand side is an expression list containing variables
** * pExpr is a correlated subquery
** * We are inside a trigger
**
** If all of the above are false, then we can run this code just once
@@ -1729,174 +1875,33 @@ int sqlite3CodeSubselect(
#ifndef SQLITE_OMIT_EXPLAIN
if( pParse->explain==2 ){
char *zMsg = sqlite3MPrintf(
pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr>=0?"":"CORRELATED ",
pExpr->op==TK_IN?"LIST":"SCALAR", pParse->iNextSelectId
pParse->db, "EXECUTE %sSCALAR SUBQUERY %d",
testAddr>=0?"":"CORRELATED ", pParse->iNextSelectId
);
sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
}
#endif
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);
if( rMayHaveNull==0 ) sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
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;
}
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);
if( testAddr>=0 ){
sqlite3VdbeJumpHere(v, testAddr);
@@ -1943,7 +1948,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);
eType = sqlite3FindInIndex(pParse, pExpr, &rRhsHasNull, 0);
/* Figure out the affinity to use to create a key from the results
** of the expression. affinityStr stores a static string suitable for
@@ -2687,7 +2692,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
FuncDef *pDef; /* The function definition object */
int nId; /* Length of the function name in bytes */
const char *zId; /* The function name */
int constMask = 0; /* Mask of function arguments that are constant */
u32 constMask = 0; /* Mask of function arguments that are constant */
int i; /* Loop counter */
u8 enc = ENC(db); /* The text encoding used by this database */
CollSeq *pColl = 0; /* A collating sequence */
@@ -2738,7 +2743,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
for(i=0; i<nFarg; i++){
if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
constMask |= (1<<i);
testcase( i==31 );
constMask |= MASKBIT32(i);
}
if( (pDef->funcFlags & SQLITE_FUNC_NEEDCOLL)!=0 && !pColl ){
pColl = sqlite3ExprCollSeq(pParse, pFarg->a[i].pExpr);
@@ -2814,7 +2820,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
case TK_SELECT: {
testcase( op==TK_EXISTS );
testcase( op==TK_SELECT );
inReg = sqlite3CodeSubselect(pParse, pExpr, 0, 0);
inReg = sqlite3CodeScalarSubquery(pParse, pExpr);
break;
}
case TK_IN: {
+1 -1
View File
@@ -137,7 +137,7 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
case SQLITE_INTEGER: {
i64 iVal = sqlite3_value_int64(argv[0]);
if( iVal<0 ){
if( (iVal<<1)==0 ){
if( iVal==SMALLEST_INT64 ){
/* IMP: R-31676-45509 If X is the integer -9223372036854775808
** then abs(X) throws an integer overflow error since there is no
** equivalent positive 64-bit two complement value. */
+1 -1
View File
@@ -53,7 +53,7 @@ void sqlite3HashClear(Hash *pH){
** The hashing function.
*/
static unsigned int strHash(const char *z, int nKey){
int h = 0;
unsigned int h = 0;
assert( nKey>=0 );
while( nKey > 0 ){
h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
+3
View File
@@ -719,6 +719,9 @@ void sqlite3Insert(
** 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 */
+1 -1
View File
@@ -3303,7 +3303,7 @@ int sqlite3_test_control(int op, ...){
** that demonstrat invariants on well-formed database files.
*/
case SQLITE_TESTCTRL_NEVER_CORRUPT: {
sqlite3Config.neverCorrupt = va_arg(ap, int);
sqlite3GlobalConfig.neverCorrupt = va_arg(ap, int);
break;
}
+1 -1
View File
@@ -4097,7 +4097,7 @@ static int unixShmSystemLock(
#ifdef SQLITE_DEBUG
{ u16 mask;
OSTRACE(("SHM-LOCK "));
mask = ofst>31 ? 0xffffffff : (1<<(ofst+n)) - (1<<ofst);
mask = ofst>31 ? 0xffff : (1<<(ofst+n)) - (1<<ofst);
if( rc==SQLITE_OK ){
if( lockType==F_UNLCK ){
OSTRACE(("unlock %d ok", ofst));
+1 -1
View File
@@ -3201,7 +3201,7 @@ static int winDeviceCharacteristics(sqlite3_file *id){
** During sqlite3_os_init() we do a GetSystemInfo()
** to get the granularity size.
*/
SYSTEM_INFO winSysInfo;
static SYSTEM_INFO winSysInfo;
#ifndef SQLITE_OMIT_WAL
+1 -1
View File
@@ -397,7 +397,7 @@ cmd ::= DROP VIEW ifexists(E) fullname(X). {
//////////////////////// The SELECT statement /////////////////////////////////
//
cmd ::= select(X). {
SelectDest dest = {SRT_Output, 0, 0, 0, 0};
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
sqlite3Select(pParse, X, &dest);
sqlite3ExplainBegin(pParse->pVdbe);
sqlite3ExplainSelect(pParse->pVdbe, X);
+26 -8
View File
@@ -23,7 +23,8 @@ struct PCache {
int szCache; /* Configured cache size */
int szPage; /* Size of every page in this cache */
int szExtra; /* Size of extra space for each page */
int bPurgeable; /* True if pages are on backing store */
u8 bPurgeable; /* True if pages are on backing store */
u8 eCreate; /* eCreate value for for xFetch() */
int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
void *pStress; /* Argument to xStress */
sqlite3_pcache *pCache; /* Pluggable cache module */
@@ -90,6 +91,10 @@ static void pcacheRemoveFromDirtyList(PgHdr *pPage){
}else{
assert( pPage==p->pDirty );
p->pDirty = pPage->pDirtyNext;
if( p->pDirty==0 && p->bPurgeable ){
assert( p->eCreate==1 );
p->eCreate = 2;
}
}
pPage->pDirtyNext = 0;
pPage->pDirtyPrev = 0;
@@ -110,6 +115,9 @@ static void pcacheAddToDirtyList(PgHdr *pPage){
if( pPage->pDirtyNext ){
assert( pPage->pDirtyNext->pDirtyPrev==0 );
pPage->pDirtyNext->pDirtyPrev = pPage;
}else if( p->bPurgeable ){
assert( p->eCreate==2 );
p->eCreate = 1;
}
p->pDirty = pPage;
if( !p->pDirtyTail ){
@@ -179,6 +187,7 @@ void sqlite3PcacheOpen(
p->szPage = szPage;
p->szExtra = szExtra;
p->bPurgeable = bPurgeable;
p->eCreate = 2;
p->xStress = xStress;
p->pStress = pStress;
p->szCache = 100;
@@ -218,7 +227,7 @@ int sqlite3PcacheFetch(
int createFlag, /* If true, create page if it does not exist already */
PgHdr **ppPage /* Write the page here */
){
sqlite3_pcache_page *pPage = 0;
sqlite3_pcache_page *pPage;
PgHdr *pPgHdr = 0;
int eCreate;
@@ -229,8 +238,12 @@ int sqlite3PcacheFetch(
/* If the pluggable cache (sqlite3_pcache*) has not been allocated,
** allocate it now.
*/
if( !pCache->pCache && createFlag ){
if( !pCache->pCache ){
sqlite3_pcache *p;
if( !createFlag ){
*ppPage = 0;
return SQLITE_OK;
}
p = sqlite3GlobalConfig.pcache2.xCreate(
pCache->szPage, pCache->szExtra + sizeof(PgHdr), pCache->bPurgeable
);
@@ -241,11 +254,16 @@ int sqlite3PcacheFetch(
pCache->pCache = p;
}
eCreate = createFlag * (1 + (!pCache->bPurgeable || !pCache->pDirty));
if( pCache->pCache ){
pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
}
/* eCreate defines what to do if the page does not exist.
** 0 Do not allocate a new page. (createFlag==0)
** 1 Allocate a new page if doing so is inexpensive.
** (createFlag==1 AND bPurgeable AND pDirty)
** 2 Allocate a new page even it doing so is difficult.
** (createFlag==1 AND !(bPurgeable AND pDirty)
*/
eCreate = createFlag==0 ? 0 : pCache->eCreate;
assert( (createFlag*(1+(!pCache->bPurgeable||!pCache->pDirty)))==eCreate );
pPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
if( !pPage && eCreate==1 ){
PgHdr *pPg;
+2 -1
View File
@@ -720,6 +720,7 @@ static sqlite3_pcache_page *pcache1Fetch(
PGroup *pGroup;
PgHdr1 *pPage = 0;
assert( offsetof(PgHdr1,page)==0 );
assert( pCache->bPurgeable || createFlag!=1 );
assert( pCache->bPurgeable || pCache->nMin==0 );
assert( pCache->bPurgeable==0 || pCache->nMin==10 );
@@ -825,7 +826,7 @@ fetch_out:
pCache->iMaxKey = iKey;
}
pcache1LeaveMutex(pGroup);
return &pPage->page;
return (sqlite3_pcache_page*)pPage;
}
+62 -41
View File
@@ -535,8 +535,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; /* Ephemeral table used for DISTINCT processing */
int addrTnct; /* Address of OP_OpenEphemeral opcode for tabTnct */
int tabTnct; /* Table containing previously seen values */
int addrTnct; /* Address of OpenEphemeral/OpenHash opcode for tabTnct */
};
/*
@@ -814,6 +814,7 @@ static void selectInnerLoop(
** been added */
addrTest = sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, 0, r3, 0);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r3);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
}
for(i=0; i<nKey; i++){
sqlite3VdbeAddOp2(v, OP_SCopy,
@@ -1724,7 +1725,44 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
}
return pRet;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
/*
** The select statement passed as the second parameter is a compound SELECT
** with an ORDER BY clause. This function allocates and returns a KeyInfo
** structure suitable for implementing the ORDER BY.
**
** Space to hold the KeyInfo structure is obtained from malloc. The calling
** function is responsible for ensuring that this structure is eventually
** freed.
*/
static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){
ExprList *pOrderBy = p->pOrderBy;
int nOrderBy = p->pOrderBy->nExpr;
sqlite3 *db = pParse->db;
KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1);
if( pRet ){
int i;
for(i=0; i<nOrderBy; i++){
struct ExprList_item *pItem = &pOrderBy->a[i];
Expr *pTerm = pItem->pExpr;
CollSeq *pColl;
if( pTerm->flags & EP_Collate ){
pColl = sqlite3ExprCollSeq(pParse, pTerm);
}else{
pColl = multiSelectCollSeq(pParse, p, pItem->u.x.iOrderByCol-1);
if( pColl==0 ) pColl = db->pDfltColl;
pOrderBy->a[i].pExpr =
sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
}
assert( sqlite3KeyInfoIsWriteable(pRet) );
pRet->aColl[i] = pColl;
pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder;
}
}
return pRet;
}
#ifndef SQLITE_OMIT_CTE
/*
@@ -1774,7 +1812,7 @@ static void generateWithRecursiveQuery(
Select *pSetup = p->pPrior; /* The setup query */
int addrTop; /* Top of the loop */
int addrCont, addrBreak; /* CONTINUE and BREAK addresses */
int iCurrent; /* The Current table */
int iCurrent = 0; /* The Current table */
int regCurrent; /* Register holding Current table */
int iQueue; /* The Queue table */
int iDistinct = 0; /* To ensure unique results if UNION */
@@ -1798,6 +1836,7 @@ static void generateWithRecursiveQuery(
regOffset = p->iOffset;
p->pLimit = p->pOffset = 0;
p->iLimit = p->iOffset = 0;
pOrderBy = p->pOrderBy;
/* Locate the cursor number of the Current table */
for(i=0; ALWAYS(i<pSrc->nSrc); i++){
@@ -1807,10 +1846,6 @@ static void generateWithRecursiveQuery(
}
}
/* Detach the ORDER BY clause from the compound SELECT */
pOrderBy = p->pOrderBy;
p->pOrderBy = 0;
/* Allocate cursors numbers for Queue and Distinct. The cursor number for
** the Distinct table must be exactly one greater than Queue in order
** for the SRT_DistTable and SRT_DistQueue destinations to work. */
@@ -1827,7 +1862,7 @@ static void generateWithRecursiveQuery(
regCurrent = ++pParse->nMem;
sqlite3VdbeAddOp3(v, OP_OpenPseudo, iCurrent, regCurrent, nCol);
if( pOrderBy ){
KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pOrderBy, 1);
KeyInfo *pKeyInfo = multiSelectOrderByKeyInfo(pParse, p, 1);
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, iQueue, pOrderBy->nExpr+2, 0,
(char*)pKeyInfo, P4_KEYINFO);
destQueue.pOrderBy = pOrderBy;
@@ -1836,10 +1871,13 @@ static void generateWithRecursiveQuery(
}
VdbeComment((v, "Queue table"));
if( iDistinct ){
p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, iDistinct, 0);
p->addrOpenEphm[0] = sqlite3VdbeAddOp2(v, OP_OpenHash, iDistinct, 0);
p->selFlags |= SF_UsesEphemeral;
}
/* Detach the ORDER BY clause from the compound SELECT */
p->pOrderBy = 0;
/* Store the results of the setup-query in Queue. */
rc = sqlite3Select(pParse, pSetup, &destQueue);
if( rc ) goto end_of_recursive_query;
@@ -1882,7 +1920,7 @@ end_of_recursive_query:
p->pOffset = pOffset;
return;
}
#endif
#endif /* SQLITE_OMIT_CTE */
/* Forward references */
static int multiSelectOrderBy(
@@ -1892,7 +1930,6 @@ static int multiSelectOrderBy(
);
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** This routine is called to process a compound query form from
** two or more separate queries using UNION, UNION ALL, EXCEPT, or
@@ -1936,8 +1973,8 @@ static int multiSelect(
Select *pDelete = 0; /* Chain of simple selects to delete */
sqlite3 *db; /* Database connection */
#ifndef SQLITE_OMIT_EXPLAIN
int iSub1; /* EQP id of left-hand query */
int iSub2; /* EQP id of right-hand query */
int iSub1 = 0; /* EQP id of left-hand query */
int iSub2 = 0; /* EQP id of right-hand query */
#endif
/* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only
@@ -1970,8 +2007,7 @@ static int multiSelect(
*/
if( dest.eDest==SRT_EphemTab ){
assert( p->pEList );
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iSDParm, p->pEList->nExpr);
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
sqlite3VdbeAddOp2(v, OP_OpenHash, dest.iSDParm, p->pEList->nExpr);
dest.eDest = SRT_Table;
}
@@ -2071,7 +2107,7 @@ static int multiSelect(
*/
unionTab = pParse->nTab++;
assert( p->pOrderBy==0 );
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);
addr = sqlite3VdbeAddOp2(v, OP_OpenHash, unionTab, 0);
assert( p->addrOpenEphm[0] == -1 );
p->addrOpenEphm[0] = addr;
p->pRightmost->selFlags |= SF_UsesEphemeral;
@@ -2154,7 +2190,8 @@ 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.
** by allocating the tables we will need. The tables must be
** ordered: Use OP_OpenEphermeral, not OP_OpenHash.
*/
tab1 = pParse->nTab++;
tab2 = pParse->nTab++;
@@ -2624,24 +2661,7 @@ static int multiSelectOrderBy(
&& pItem->u.x.iOrderByCol<=p->pEList->nExpr );
aPermute[i] = pItem->u.x.iOrderByCol - 1;
}
pKeyMerge = sqlite3KeyInfoAlloc(db, nOrderBy, 1);
if( pKeyMerge ){
for(i=0; i<nOrderBy; i++){
CollSeq *pColl;
Expr *pTerm = pOrderBy->a[i].pExpr;
if( pTerm->flags & EP_Collate ){
pColl = sqlite3ExprCollSeq(pParse, pTerm);
}else{
pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
if( pColl==0 ) pColl = db->pDfltColl;
pOrderBy->a[i].pExpr =
sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName);
}
assert( sqlite3KeyInfoIsWriteable(pKeyMerge) );
pKeyMerge->aColl[i] = pColl;
pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
}
}
pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
}else{
pKeyMerge = 0;
}
@@ -4282,7 +4302,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
pFunc->iDistinct = -1;
}else{
KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList, 0);
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
sqlite3VdbeAddOp4(v, OP_OpenHash, pFunc->iDistinct, 0, 0,
(char*)pKeyInfo, P4_KEYINFO);
}
}
@@ -4532,8 +4552,8 @@ int sqlite3Select(
p->selFlags |= SF_Aggregate;
}
i = -1;
}else if( pTabList->nSrc==1 && (p->selFlags & SF_Materialize)==0
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
}else if( pTabList->nSrc==1
&& OptimizationEnabled(db, SQLITE_SubqCoroutine)
){
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
@@ -4701,6 +4721,8 @@ 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);
@@ -4720,11 +4742,10 @@ int sqlite3Select(
*/
if( p->selFlags & SF_Distinct ){
sDistinct.tabTnct = pParse->nTab++;
sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenHash,
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;
+14 -10
View File
@@ -1982,6 +1982,7 @@ typedef u64 Bitmask;
** A bit in a Bitmask
*/
#define MASKBIT(n) (((Bitmask)1)<<(n))
#define MASKBIT32(n) (((unsigned int)1)<<(n))
/*
** The following structure describes the FROM clause of a SELECT statement.
@@ -2160,7 +2161,7 @@ struct Select {
#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
#define SF_UseSorter 0x0040 /* Sort using a sorter */
#define SF_Values 0x0080 /* Synthesized from VALUES clause */
#define SF_Materialize 0x0100 /* Force materialization of views */
#define SF_Materialize 0x0100 /* NOT USED */
#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 */
@@ -2357,22 +2358,23 @@ struct Parse {
int nSet; /* Number of sets used so far */
int nOnce; /* Number of OP_Once instructions so far */
int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
int nLabel; /* Number of labels used */
int *aLabel; /* Space to hold the labels */
int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */
int ckBase; /* Base register of data during check constraints */
int iPartIdxTab; /* Table corresponding to a partial index */
int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
int iCacheCnt; /* Counter used to generate aColCache[].lru values */
int nLabel; /* Number of labels used */
int *aLabel; /* Space to hold the labels */
struct yColCache {
int iTable; /* Table cursor number */
int iColumn; /* Table column number */
i16 iColumn; /* Table column number */
u8 tempReg; /* iReg is a temp register that needs to be freed */
int iLevel; /* Nesting level */
int iReg; /* Reg with value of this column. 0 means none. */
int lru; /* Least recently used entry has the smallest value */
} aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
ExprList *pConstExpr;/* Constant expressions */
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 */
@@ -2380,7 +2382,6 @@ struct Parse {
int regRowid; /* Register holding rowid of CREATE TABLE entry */
int regRoot; /* Register holding root page number for new objects */
int nMaxArg; /* Max args passed to user function by sub-program */
Token constraintName;/* Name of the constraint currently being parsed */
#ifndef SQLITE_OMIT_SHARED_CACHE
int nTableLock; /* Number of locks in aTableLock */
TableLock *aTableLock; /* Required table locks for shared-cache mode */
@@ -2399,12 +2400,17 @@ struct Parse {
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
u8 disableTriggers; /* True to disable triggers */
/* Above is constant between recursions. Below is reset before and after
** each recursion */
/************************************************************************
** Above is constant between recursions. Below is reset before and after
** each recursion. The boundary between these two regions is determined
** using offsetof(Parse,nVar) so the nVar field must be the first field
** in the recursive region.
************************************************************************/
int nVar; /* Number of '?' variables seen in the SQL so far */
int nzVar; /* Number of available slots in azVar[] */
u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
u8 bFreeWith; /* True if pWith should be freed with parser */
u8 explain; /* True if the EXPLAIN flag is found on the query */
#ifndef SQLITE_OMIT_VIRTUALTABLE
u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
@@ -2431,7 +2437,6 @@ struct Parse {
Table *pZombieTab; /* List of Table objects to delete after code gen */
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
With *pWith; /* Current WITH clause, or NULL */
u8 bFreeWith; /* True if pWith should be freed with parser */
};
/*
@@ -3278,7 +3283,6 @@ 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*);
@@ -3474,7 +3478,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 sqlite3FindInIndex(Parse *, Expr *, int*, int);
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
+8 -8
View File
@@ -873,7 +873,7 @@ static int auth_callback(
const char *zArg3,
const char *zArg4
){
char *zCode;
const char *zCode;
Tcl_DString str;
int rc;
const char *zReply;
@@ -999,7 +999,7 @@ static int DbTransPostCmd(
Tcl_Interp *interp, /* Tcl interpreter */
int result /* Result of evaluating SCRIPT */
){
static const char *azEnd[] = {
static const char *const azEnd[] = {
"RELEASE _tcl_transaction", /* rc==TCL_ERROR, nTransaction!=0 */
"COMMIT", /* rc!=TCL_ERROR, nTransaction==0 */
"ROLLBACK TO _tcl_transaction ; RELEASE _tcl_transaction",
@@ -1937,7 +1937,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
Tcl_AppendResult(interp, pDb->zCommit, 0);
}
}else{
char *zCommit;
const char *zCommit;
int len;
if( pDb->zCommit ){
Tcl_Free(pDb->zCommit);
@@ -2010,14 +2010,14 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
char *zSql; /* An SQL statement */
char *zLine; /* A single line of input from the file */
char **azCol; /* zLine[] broken up into columns */
char *zCommit; /* How to commit changes */
const char *zCommit; /* How to commit changes */
FILE *in; /* The input file */
int lineno = 0; /* Line number of input file */
char zLineNum[80]; /* Line number print buffer */
Tcl_Obj *pResult; /* interp result */
char *zSep;
char *zNull;
const char *zSep;
const char *zNull;
if( objc<5 || objc>7 ){
Tcl_WrongNumArgs(interp, 2, objv,
"CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?");
@@ -2935,7 +2935,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
if( objc==2 ){
zArg = Tcl_GetStringFromObj(objv[1], 0);
if( strcmp(zArg,"-version")==0 ){
Tcl_AppendResult(interp,sqlite3_version,0);
Tcl_AppendResult(interp,sqlite3_libversion(),0);
return TCL_OK;
}
if( strcmp(zArg,"-has-codec")==0 ){
@@ -3017,7 +3017,7 @@ static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
zErrMsg = 0;
p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
if( p==0 ){
Tcl_SetResult(interp, "malloc failed", TCL_STATIC);
Tcl_SetResult(interp, (char *)"malloc failed", TCL_STATIC);
return TCL_ERROR;
}
memset(p, 0, sizeof(*p));
+23 -1
View File
@@ -242,7 +242,28 @@ static int test_io_trace(
return TCL_OK;
}
/*
** Usage: clang_sanitize_address
**
** Returns true if the program was compiled using clang with the
** -fsanitize=address switch on the command line. False otherwise.
*/
static int clang_sanitize_address(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
char **argv /* Text of each argument */
){
int res = 0;
#if defined(__has_feature)
# if __has_feature(address_sanitizer)
res = 1;
# endif
#endif
Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
return TCL_OK;
}
/*
** Usage: sqlite3_exec_printf DB FORMAT STRING
**
@@ -6323,6 +6344,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout },
{ "printf", (Tcl_CmdProc*)test_printf },
{ "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace },
{ "clang_sanitize_address", (Tcl_CmdProc*)clang_sanitize_address },
};
static struct {
char *zName;
+1 -1
View File
@@ -892,7 +892,7 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
pIdxInfo->estimatedCost = cost;
}else if( useIdx ){
/* Approximation of log2(nRow). */
for( ii=0; ii<(sizeof(int)*8); ii++ ){
for( ii=0; ii<(sizeof(int)*8)-1; ii++ ){
if( nRow & (1<<ii) ){
pIdxInfo->estimatedCost = (double)ii;
}
+4 -4
View File
@@ -467,9 +467,10 @@ void sqlite3Update(
);
for(i=0; i<pTab->nCol; i++){
if( oldmask==0xffffffff
|| (i<32 && (oldmask & (1<<i)))
|| (i<32 && (oldmask & MASKBIT32(i))!=0)
|| (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
){
testcase( oldmask!=0xffffffff && i==31 );
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
@@ -504,7 +505,7 @@ void sqlite3Update(
j = aXRef[i];
if( j>=0 ){
sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
}else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){
}else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
/* This branch loads the value of a column that will not be changed
** into a register. This is done if there are no BEFORE triggers, or
** if there are one or more BEFORE triggers that use this value via
@@ -734,8 +735,7 @@ static void updateVirtualTable(
*/
assert( v );
ephemTab = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));
sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
sqlite3VdbeAddOp2(v, OP_OpenHash, ephemTab, pTab->nCol+1+(pRowid!=0));
/* fill the ephemeral table
*/
+2 -1
View File
@@ -1001,7 +1001,8 @@ int sqlite3VarintLen(u64 v){
** Read or write a four-byte big-endian integer value.
*/
u32 sqlite3Get4byte(const u8 *p){
return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
testcase( p[0]&0x80 );
return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
}
void sqlite3Put4byte(unsigned char *p, u32 v){
p[0] = (u8)(v>>24);
+55 -35
View File
@@ -3295,7 +3295,7 @@ case OP_OpenWrite: {
break;
}
/* Opcode: OpenEphemeral P1 P2 * P4 P5
/* Opcode: OpenEphemeral P1 P2 * P4 *
** Synopsis: nColumn=P2
**
** Open a new cursor P1 to a transient table.
@@ -3307,11 +3307,18 @@ 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
**
** 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.
** 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.
*/
/* Opcode: OpenAutoindex P1 P2 * P4 *
** Synopsis: nColumn=P2
@@ -3322,9 +3329,10 @@ case OP_OpenWrite: {
** indices in joins.
*/
case OP_OpenAutoindex:
case OP_OpenHash:
case OP_OpenEphemeral: {
VdbeCursor *pCx;
KeyInfo *pKeyInfo;
int btreeFlags;
static const int vfsFlags =
SQLITE_OPEN_READWRITE |
@@ -3334,38 +3342,35 @@ 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;
rc = sqlite3BtreeOpen(db->pVfs, 0, db, &pCx->pBt,
BTREE_OMIT_JOURNAL | BTREE_SINGLE | pOp->p5, vfsFlags);
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);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeBeginTrans(pCx->pBt, 1);
}
if( rc==SQLITE_OK ){
/* 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;
}
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, pOp->p4.pKeyInfo,
pCx->pCursor);
}
pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED);
pCx->pKeyInfo = pOp->p4.pKeyInfo;
break;
}
@@ -3599,6 +3604,7 @@ case OP_SeekGt: { /* jump, in3 */
#endif
if( oc>=OP_SeekGe ){ assert( oc==OP_SeekGe || oc==OP_SeekGt );
if( res<0 || (res==0 && oc==OP_SeekGt) ){
res = 0;
rc = sqlite3BtreeNext(pC->pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
pC->rowidIsValid = 0;
@@ -3608,6 +3614,7 @@ case OP_SeekGt: { /* jump, in3 */
}else{
assert( oc==OP_SeekLt || oc==OP_SeekLe );
if( res>0 || (res==0 && oc==OP_SeekLt) ){
res = 0;
rc = sqlite3BtreePrevious(pC->pCursor, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
pC->rowidIsValid = 0;
@@ -4460,7 +4467,7 @@ case OP_Rewind: { /* jump */
break;
}
/* Opcode: Next P1 P2 * * P5
/* Opcode: Next P1 P2 P3 * 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
@@ -4470,6 +4477,11 @@ case OP_Rewind: { /* jump */
** The P1 cursor must be for a real table, not a pseudo-table. P1 must have
** been opened prior to this opcode or the program will segfault.
**
** The P3 value is a hint to the btree implementation. If P3==1, that
** means P1 is an SQL index and that this instruction could have been
** omitted if that index had been unique. P3 is usually 0. P3 is
** always either 0 or 1.
**
** P4 is always of type P4_ADVANCE. The function pointer points to
** sqlite3BtreeNext().
**
@@ -4478,12 +4490,12 @@ case OP_Rewind: { /* jump */
**
** See also: Prev, NextIfOpen
*/
/* Opcode: NextIfOpen P1 P2 * * P5
/* Opcode: NextIfOpen P1 P2 P3 * 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 * * P5
/* Opcode: Prev P1 P2 P3 * 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
@@ -4493,13 +4505,18 @@ case OP_Rewind: { /* jump */
** The P1 cursor must be for a real table, not a pseudo-table. If P1 is
** not open then the behavior is undefined.
**
** The P3 value is a hint to the btree implementation. If P3==1, that
** means P1 is an SQL index and that this instruction could have been
** omitted if that index had been unique. P3 is usually 0. P3 is
** always either 0 or 1.
**
** P4 is always of type P4_ADVANCE. The function pointer points to
** sqlite3BtreePrevious().
**
** 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 * * P5
/* Opcode: PrevIfOpen P1 P2 P3 * P5
**
** This opcode works just like OP_Prev except that if cursor P1 is not
** open it behaves a no-op.
@@ -4521,9 +4538,12 @@ case OP_Next: /* jump */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( pOp->p5<ArraySize(p->aCounter) );
pC = p->apCsr[pOp->p1];
res = pOp->p3;
assert( pC!=0 );
assert( pC->deferredMoveto==0 );
assert( pC->pCursor );
assert( res==0 || (res==1 && pC->isTable==0) );
testcase( res==1 );
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
@@ -6174,7 +6194,7 @@ case OP_Trace: {
if( zTrace ){
int i;
for(i=0; i<db->nDb; i++){
if( ((1<<i) & p->btreeMask)==0 ) continue;
if( MASKBIT(i) & p->btreeMask)==0 ) continue;
sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
}
}
+15 -11
View File
@@ -2615,8 +2615,9 @@ void sqlite3VdbeDeleteAuxData(Vdbe *pVdbe, int iOp, int mask){
while( *pp ){
AuxData *pAux = *pp;
if( (iOp<0)
|| (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & ((u32)1<<pAux->iArg))))
|| (pAux->iOp==iOp && (pAux->iArg>31 || !(mask & MASKBIT32(pAux->iArg))))
){
testcase( pAux->iArg==31 );
if( pAux->xDelete ){
pAux->xDelete(pAux->pAux);
}
@@ -2931,6 +2932,9 @@ u32 sqlite3VdbeSerialGet(
u32 serial_type, /* Serial type to deserialize */
Mem *pMem /* Memory cell to write value into */
){
u64 x;
u32 y;
int i;
switch( serial_type ){
case 10: /* Reserved for future use */
case 11: /* Reserved for future use */
@@ -2944,23 +2948,26 @@ u32 sqlite3VdbeSerialGet(
return 1;
}
case 2: { /* 2-byte signed integer */
pMem->u.i = (((signed char)buf[0])<<8) | buf[1];
i = 256*(signed char)buf[0] | buf[1];
pMem->u.i = (i64)i;
pMem->flags = MEM_Int;
return 2;
}
case 3: { /* 3-byte signed integer */
pMem->u.i = (((signed char)buf[0])<<16) | (buf[1]<<8) | buf[2];
i = 65536*(signed char)buf[0] | (buf[1]<<8) | buf[2];
pMem->u.i = (i64)i;
pMem->flags = MEM_Int;
return 3;
}
case 4: { /* 4-byte signed integer */
pMem->u.i = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
y = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
pMem->u.i = (i64)*(int*)&y;
pMem->flags = MEM_Int;
return 4;
}
case 5: { /* 6-byte signed integer */
u64 x = (((signed char)buf[0])<<8) | buf[1];
u32 y = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
x = 256*(signed char)buf[0] + buf[1];
y = ((unsigned)buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
x = (x<<32) | y;
pMem->u.i = *(i64*)&x;
pMem->flags = MEM_Int;
@@ -2968,8 +2975,6 @@ u32 sqlite3VdbeSerialGet(
}
case 6: /* 8-byte signed integer */
case 7: { /* IEEE floating point */
u64 x;
u32 y;
#if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT)
/* Verify that integers and floating point values use the same
** byte order. Or, that if SQLITE_MIXED_ENDIAN_64BIT_FLOAT is
@@ -2982,9 +2987,8 @@ u32 sqlite3VdbeSerialGet(
swapMixedEndianFloat(t2);
assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
#endif
x = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
y = (buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
x = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
y = ((unsigned)buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
x = (x<<32) | y;
if( serial_type==6 ){
pMem->u.i = *(i64*)&x;
+1 -1
View File
@@ -598,7 +598,7 @@ void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
/*
** Size of struct Mem not including the Mem.zMalloc member.
*/
#define MEMCELLSIZE (size_t)(&(((Mem *)0)->zMalloc))
#define MEMCELLSIZE offsetof(Mem,zMalloc)
/*
** Make an shallow copy of pFrom into pTo. Prior contents of
+21 -16
View File
@@ -2348,16 +2348,17 @@ 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(
Parse *pParse, /* The parsing context */
WhereInfo *pWInfo, /* WHERE clause */
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;
Vdbe *v = pParse->pVdbe;
int iReg; /* Register holding results */
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 */
assert( iTarget>0 );
if( pX->op==TK_EQ ){
@@ -2382,7 +2383,7 @@ static int codeEqualityTerm(
}
assert( pX->op==TK_IN );
iReg = iTarget;
eType = sqlite3FindInIndex(pParse, pX, 0);
eType = sqlite3FindInIndex(pParse, pX, 0, pWInfo->bOBSat);
if( eType==IN_INDEX_INDEX_DESC ){
testcase( bRev );
bRev = !bRev;
@@ -2464,7 +2465,7 @@ static int codeEqualityTerm(
** string in this example would be set to SQLITE_AFF_NONE.
*/
static int codeAllEqualityTerms(
Parse *pParse, /* Parsing context */
WhereInfo *pWInfo, /* WHERE clause */
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 */
@@ -2472,6 +2473,7 @@ 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 */
@@ -2526,7 +2528,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(pParse, pTerm, pLevel, j, bRev, regBase+j);
r1 = codeEqualityTerm(pWInfo, pTerm, pLevel, j, bRev, regBase+j);
if( r1!=regBase+j ){
if( nReg==1 ){
sqlite3ReleaseTempReg(pParse, regBase);
@@ -2809,7 +2811,7 @@ static Bitmask codeOneLoopStart(
pTerm = pLoop->aLTerm[j];
if( pTerm==0 ) continue;
if( pTerm->eOperator & WO_IN ){
codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
codeEqualityTerm(pWInfo, pTerm, pLevel, j, bRev, iTarget);
addrNotFound = pLevel->addrNxt;
}else{
sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
@@ -2849,7 +2851,7 @@ static Bitmask codeOneLoopStart(
assert( pTerm->pExpr!=0 );
assert( omitTable==0 );
testcase( pTerm->wtFlags & TERM_VIRTUAL );
iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
iRowidReg = codeEqualityTerm(pWInfo, pTerm, pLevel, 0, bRev, iReleaseReg);
addrNxt = pLevel->addrNxt;
sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
@@ -3039,7 +3041,7 @@ static Bitmask codeOneLoopStart(
** and store the values of those terms in an array of registers
** starting at regBase.
*/
regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff);
regBase = codeAllEqualityTerms(pWInfo,pLevel,bRev,nExtraReg,&zStartAff);
assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq );
if( zStartAff ) cEndAff = zStartAff[nEq];
addrNxt = pLevel->addrNxt;
@@ -3184,6 +3186,8 @@ static Bitmask codeOneLoopStart(
pLevel->op = OP_Next;
}
pLevel->p1 = iIdxCur;
assert( (WHERE_UNQ_WANTED>>16)==1 );
pLevel->p3 = (pLoop->wsFlags>>16)&1;
if( (pLoop->wsFlags & WHERE_CONSTRAINT)==0 ){
pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP;
}else{
@@ -3986,12 +3990,13 @@ static int whereLoopAddBtreeIndex(
|| nInMul==0
);
pNew->wsFlags |= WHERE_COLUMN_EQ;
if( iCol<0
|| (pProbe->onError!=OE_None && nInMul==0
&& pNew->u.btree.nEq==pProbe->nKeyCol-1)
){
if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1)){
assert( (pNew->wsFlags & WHERE_COLUMN_IN)==0 || iCol<0 );
pNew->wsFlags |= WHERE_ONEROW;
if( iCol>=0 && pProbe->onError==OE_None ){
pNew->wsFlags |= WHERE_UNQ_WANTED;
}else{
pNew->wsFlags |= WHERE_ONEROW;
}
}
pNew->u.btree.nEq++;
pNew->nOut = nRowEst + nInMul;
@@ -5785,7 +5790,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
pLoop = pLevel->pWLoop;
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
if( pLevel->op!=OP_Noop ){
sqlite3VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2);
sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
sqlite3VdbeChangeP5(v, pLevel->p5);
}
if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){
+2 -1
View File
@@ -70,7 +70,7 @@ struct WhereLevel {
int addrFirst; /* First instruction of interior of the loop */
int addrBody; /* Beginning of the body of this loop */
u8 iFrom; /* Which entry in the FROM clause */
u8 op, p5; /* Opcode and P5 of the opcode that ends the loop */
u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
int p1, p2; /* Operands of the opcode used to ends the loop */
union { /* Information that depends on pWLoop->wsFlags */
struct {
@@ -457,3 +457,4 @@ struct WhereInfo {
#define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
#define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
#define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */
#define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/
+24 -18
View File
@@ -179,16 +179,18 @@ do_test capi3-3.4 {
do_test capi3-3.5 {
sqlite3_close $db2
} {SQLITE_OK}
do_test capi3-3.6.1-misuse {
sqlite3_close $db2
} {SQLITE_MISUSE}
do_test capi3-3.6.2-misuse {
sqlite3_errmsg $db2
} {library routine called out of sequence}
ifcapable {utf16} {
do_test capi3-3.6.3-misuse {
utf8 [sqlite3_errmsg16 $db2]
if {[clang_sanitize_address]==0} {
do_test capi3-3.6.1-misuse {
sqlite3_close $db2
} {SQLITE_MISUSE}
do_test capi3-3.6.2-misuse {
sqlite3_errmsg $db2
} {library routine called out of sequence}
ifcapable {utf16} {
do_test capi3-3.6.3-misuse {
utf8 [sqlite3_errmsg16 $db2]
} {library routine called out of sequence}
}
}
do_test capi3-3.7 {
@@ -661,10 +663,12 @@ do_test capi3-6.3 {
sqlite3_finalize $STMT
} {SQLITE_OK}
do_test capi3-6.4-misuse {
db cache flush
sqlite3_close $DB
} {SQLITE_OK}
if {[clang_sanitize_address]==0} {
do_test capi3-6.4-misuse {
db cache flush
sqlite3_close $DB
} {SQLITE_OK}
}
db close
# This procedure sets the value of the file-format in file 'test.db'
@@ -1060,11 +1064,13 @@ if {[llength [info commands sqlite3_sleep]]>0} {
}
# Ticket #1219: Make sure binding APIs can handle a NULL pointer.
#
do_test capi3-14.1-misuse {
set rc [catch {sqlite3_bind_text 0 1 hello 5} msg]
lappend rc $msg
} {1 SQLITE_MISUSE}
#
if {[clang_sanitize_address]==0} {
do_test capi3-14.1-misuse {
set rc [catch {sqlite3_bind_text 0 1 hello 5} msg]
lappend rc $msg
} {1 SQLITE_MISUSE}
}
# Ticket #1650: Honor the nBytes parameter to sqlite3_prepare.
#
+21 -15
View File
@@ -169,16 +169,18 @@ do_test capi3c-3.4 {
do_test capi3c-3.5 {
sqlite3_close $db2
} {SQLITE_OK}
do_test capi3c-3.6.1-misuse {
sqlite3_close $db2
} {SQLITE_MISUSE}
do_test capi3c-3.6.2-misuse {
sqlite3_errmsg $db2
} {library routine called out of sequence}
ifcapable {utf16} {
do_test capi3c-3.6.3-misuse {
utf8 [sqlite3_errmsg16 $db2]
if {[clang_sanitize_address]==0} {
do_test capi3c-3.6.1-misuse {
sqlite3_close $db2
} {SQLITE_MISUSE}
do_test capi3c-3.6.2-misuse {
sqlite3_errmsg $db2
} {library routine called out of sequence}
ifcapable {utf16} {
do_test capi3c-3.6.3-misuse {
utf8 [sqlite3_errmsg16 $db2]
} {library routine called out of sequence}
}
}
# rename sqlite3_open ""
@@ -627,13 +629,17 @@ check_data $STMT capi3c-6.3 {INTEGER} {1} {1.0} {1}
do_test capi3c-6.3 {
sqlite3_finalize $STMT
} {SQLITE_OK}
do_test capi3c-6.4 {
db cache flush
sqlite3_close $DB
} {SQLITE_OK}
do_test capi3c-6.99-misuse {
if {[clang_sanitize_address]==0} {
do_test capi3c-6.4 {
db cache flush
sqlite3_close $DB
} {SQLITE_OK}
do_test capi3c-6.99-misuse {
db close
} {}
} else {
db close
} {}
}
# This procedure sets the value of the file-format in file 'test.db'
# to $newval. Also, the schema cookie is incremented.
+75 -25
View File
@@ -15,51 +15,68 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix closure01
ifcapable !vtab { finish_test ; return }
ifcapable !vtab||!cte { finish_test ; return }
load_static_extension db closure
do_execsql_test 1.0 {
BEGIN;
CREATE TABLE t1(x INTEGER PRIMARY KEY, y INTEGER);
WITH RECURSIVE
cnt(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM cnt LIMIT 131072)
INSERT INTO t1(x, y) SELECT i, nullif(i,1)/2 FROM cnt;
CREATE INDEX t1y ON t1(y);
INSERT INTO t1(x) VALUES(1),(2);
INSERT INTO t1(x) SELECT x+2 FROM t1;
INSERT INTO t1(x) SELECT x+4 FROM t1;
INSERT INTO t1(x) SELECT x+8 FROM t1;
INSERT INTO t1(x) SELECT x+16 FROM t1;
INSERT INTO t1(x) SELECT x+32 FROM t1;
INSERT INTO t1(x) SELECT x+64 FROM t1;
INSERT INTO t1(x) SELECT x+128 FROM t1;
INSERT INTO t1(x) SELECT x+256 FROM t1;
INSERT INTO t1(x) SELECT x+512 FROM t1;
INSERT INTO t1(x) SELECT x+1024 FROM t1;
INSERT INTO t1(x) SELECT x+2048 FROM t1;
INSERT INTO t1(x) SELECT x+4096 FROM t1;
INSERT INTO t1(x) SELECT x+8192 FROM t1;
INSERT INTO t1(x) SELECT x+16384 FROM t1;
INSERT INTO t1(x) SELECT x+32768 FROM t1;
INSERT INTO t1(x) SELECT x+65536 FROM t1;
UPDATE t1 SET y=x/2 WHERE x>1;
COMMIT;
CREATE VIRTUAL TABLE cx
USING transitive_closure(tablename=t1, idcolumn=x, parentcolumn=y);
} {}
# The entire table
do_execsql_test 1.1 {
do_timed_execsql_test 1.1 {
SELECT count(*), depth FROM cx WHERE root=1 GROUP BY depth ORDER BY 1;
} {/1 0 1 17 2 1 4 2 8 3 16 4 .* 65536 16/}
do_timed_execsql_test 1.1-cte {
WITH RECURSIVE
below(id,depth) AS (
VALUES(1,0)
UNION ALL
SELECT t1.x, below.depth+1
FROM t1 JOIN below on t1.y=below.id
)
SELECT count(*), depth FROM below GROUP BY depth ORDER BY 1;
} {/1 0 1 17 2 1 4 2 8 3 16 4 .* 65536 16/}
# descendents of 32768
do_execsql_test 1.2 {
do_timed_execsql_test 1.2 {
SELECT * FROM cx WHERE root=32768 ORDER BY id;
} {32768 0 65536 1 65537 1 131072 2}
do_timed_execsql_test 1.2-cte {
WITH RECURSIVE
below(id,depth) AS (
VALUES(32768,0)
UNION ALL
SELECT t1.x, below.depth+1
FROM t1 JOIN below on t1.y=below.id
WHERE below.depth<2
)
SELECT id, depth FROM below ORDER BY id;
} {32768 0 65536 1 65537 1 131072 2}
# descendents of 16384
do_execsql_test 1.3 {
do_timed_execsql_test 1.3 {
SELECT * FROM cx WHERE root=16384 AND depth<=2 ORDER BY id;
} {16384 0 32768 1 32769 1 65536 2 65537 2 65538 2 65539 2}
do_timed_execsql_test 1.3-cte {
WITH RECURSIVE
below(id,depth) AS (
VALUES(16384,0)
UNION ALL
SELECT t1.x, below.depth+1
FROM t1 JOIN below on t1.y=below.id
WHERE below.depth<2
)
SELECT id, depth FROM below ORDER BY id;
} {16384 0 32768 1 32769 1 65536 2 65537 2 65538 2 65539 2}
# children of 16384
do_execsql_test 1.4 {
@@ -70,19 +87,41 @@ do_execsql_test 1.4 {
} {32768 1 {} t1 x y 32769 1 {} t1 x y}
# great-grandparent of 16384
do_execsql_test 1.5 {
do_timed_execsql_test 1.5 {
SELECT id, depth, root, tablename, idcolumn, parentcolumn FROM cx
WHERE root=16384
AND depth=3
AND idcolumn='Y'
AND parentcolumn='X';
} {2048 3 {} t1 Y X}
do_timed_execsql_test 1.5-cte {
WITH RECURSIVE
above(id,depth) AS (
VALUES(16384,0)
UNION ALL
SELECT t1.y, above.depth+1
FROM t1 JOIN above ON t1.x=above.id
WHERE above.depth<3
)
SELECT id FROM above WHERE depth=3;
} {2048}
# depth<5
do_execsql_test 1.6 {
do_timed_execsql_test 1.6 {
SELECT count(*), depth FROM cx WHERE root=1 AND depth<5
GROUP BY depth ORDER BY 1;
} {1 0 2 1 4 2 8 3 16 4}
do_timed_execsql_test 1.6-cte {
WITH RECURSIVE
below(id,depth) AS (
VALUES(1,0)
UNION ALL
SELECT t1.x, below.depth+1
FROM t1 JOIN below ON t1.y=below.id
WHERE below.depth<4
)
SELECT count(*), depth FROM below GROUP BY depth ORDER BY 1;
} {1 0 2 1 4 2 8 3 16 4}
# depth<=5
do_execsql_test 1.7 {
@@ -103,9 +142,20 @@ do_execsql_test 1.9 {
} {8 3 16 4 32 5}
# depth==5 with min() and max()
do_execsql_test 1.10 {
do_timed_execsql_test 1.10 {
SELECT count(*), min(id), max(id) FROM cx WHERE root=1 AND depth=5;
} {32 32 63}
do_timed_execsql_test 1.10-cte {
WITH RECURSIVE
below(id,depth) AS (
VALUES(1,0)
UNION ALL
SELECT t1.x, below.depth+1
FROM t1 JOIN below ON t1.y=below.id
WHERE below.depth<5
)
SELECT count(*), min(id), max(id) FROM below WHERE depth=5;
} {32 32 63}
# Create a much smaller table t2 with only 32 elements
db eval {
+27 -1
View File
@@ -66,6 +66,7 @@ reset_db
# Initialize the database.
#
do_execsql_test 2.1 {
PRAGMA auto_vacuum=0;
PRAGMA page_size=1024;
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
@@ -95,8 +96,31 @@ do_test 2.2 {
sqlite3 db test.db
} {}
# The corruption migration caused by the test case below does not
# cause corruption to be detected in mmap mode.
#
# The trick here is that the root page of the tree scanned by the outer
# query is also currently on the free-list. So while the first seek on
# the table (for a==1) works, by the time the second is attempted The
# "INSERT INTO t2..." statements have recycled the root page of t1 and
# used it as an index leaf. Normally, BtreeMovetoUnpacked() detects
# that the PgHdr object associated with said root page does not match
# the cursor (as it is now marked with PgHdr.intKey==0) and returns
# SQLITE_CORRUPT.
#
# However, in mmap mode, the outer query and the inner queries use
# different PgHdr objects (same data, but different PgHdr container
# objects). And so the corruption is not detected. Instead, the second
# seek fails to find anything and only a single row is returned.
#
set res23 {1 {database disk image is malformed}}
if {[permutation]=="mmap"} {
set res23 {0 one}
}
do_test 2.3 {
list [catch {
set res [list]
db eval { SELECT * FROM t1 WHERE a IN (1, 2) } {
db eval {
INSERT INTO t2 SELECT randomblob(100) FROM t2;
@@ -105,9 +129,11 @@ do_test 2.3 {
INSERT INTO t2 SELECT randomblob(100) FROM t2;
INSERT INTO t2 SELECT randomblob(100) FROM t2;
}
lappend res $b
}
set res
} msg] $msg
} {1 {database disk image is malformed}}
} $res23
#-------------------------------------------------------------------------
reset_db
+3 -6
View File
@@ -51,12 +51,9 @@ proc do_temptables_test {tn sql temptables} {
set ret ""
db eval "EXPLAIN [set sql]" {
if {$opcode == "OpenEphemeral" || $opcode == "SorterOpen"} {
if {$p5 != "08" && $p5!="00"} { error "p5 = $p5" }
if {$p5 == "08"} {
lappend ret hash
} else {
lappend ret btree
}
lappend ret btree
} elseif {$opcode == "OpenHash"} {
lappend ret hash
}
}
set ret
+39 -32
View File
@@ -2946,38 +2946,45 @@ proc test_on_update_recursion {limit} {
"
}
do_test e_fkey-63.1.1 {
test_on_delete_recursion $SQLITE_MAX_TRIGGER_DEPTH
} {0 0}
do_test e_fkey-63.1.2 {
test_on_delete_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1]
} {1 {too many levels of trigger recursion}}
do_test e_fkey-63.1.3 {
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5
test_on_delete_recursion 5
} {0 0}
do_test e_fkey-63.1.4 {
test_on_delete_recursion 6
} {1 {too many levels of trigger recursion}}
do_test e_fkey-63.1.5 {
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000
} {5}
do_test e_fkey-63.2.1 {
test_on_update_recursion $SQLITE_MAX_TRIGGER_DEPTH
} {0 0}
do_test e_fkey-63.2.2 {
test_on_update_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1]
} {1 {too many levels of trigger recursion}}
do_test e_fkey-63.2.3 {
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5
test_on_update_recursion 5
} {0 0}
do_test e_fkey-63.2.4 {
test_on_update_recursion 6
} {1 {too many levels of trigger recursion}}
do_test e_fkey-63.2.5 {
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000
} {5}
# If the current build was created using clang with the -fsanitize=address
# switch, then the library uses considerably more stack space than usual.
# So much more, that some of the following tests cause stack overflows
# if they are run under this configuration.
#
if {[clang_sanitize_address]==0} {
do_test e_fkey-63.1.1 {
test_on_delete_recursion $SQLITE_MAX_TRIGGER_DEPTH
} {0 0}
do_test e_fkey-63.1.2 {
test_on_delete_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1]
} {1 {too many levels of trigger recursion}}
do_test e_fkey-63.1.3 {
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5
test_on_delete_recursion 5
} {0 0}
do_test e_fkey-63.1.4 {
test_on_delete_recursion 6
} {1 {too many levels of trigger recursion}}
do_test e_fkey-63.1.5 {
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000
} {5}
do_test e_fkey-63.2.1 {
test_on_update_recursion $SQLITE_MAX_TRIGGER_DEPTH
} {0 0}
do_test e_fkey-63.2.2 {
test_on_update_recursion [expr $SQLITE_MAX_TRIGGER_DEPTH+1]
} {1 {too many levels of trigger recursion}}
do_test e_fkey-63.2.3 {
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 5
test_on_update_recursion 5
} {0 0}
do_test e_fkey-63.2.4 {
test_on_update_recursion 6
} {1 {too many levels of trigger recursion}}
do_test e_fkey-63.2.5 {
sqlite3_limit db SQLITE_LIMIT_TRIGGER_DEPTH 1000000
} {5}
}
#-------------------------------------------------------------------------
# The setting of the recursive_triggers pragma does not affect foreign
+51 -43
View File
@@ -333,9 +333,9 @@ do_select_tests e_select-1.1 {
6 "SELECT count(*) WHERE 1" {1}
}
# EVIDENCE-OF: R-48114-33255 If there is only a single table in the
# join-source following the FROM clause, then the input data used by the
# SELECT statement is the contents of the named table.
# EVIDENCE-OF: R-45424-07352 If there is only a single table or subquery
# in the FROM clause, then the input data used by the SELECT statement
# is the contents of the named table.
#
# The results of the SELECT queries suggest that they are operating on the
# contents of the table 'xx'.
@@ -357,10 +357,10 @@ do_select_tests e_select-1.2 {
3 "SELECT sum(x), sum(y) FROM xx" {-17.89 -16.87}
}
# EVIDENCE-OF: R-23593-12456 If there is more than one table specified
# as part of the join-source following the FROM keyword, then the
# contents of each named table are joined into a single dataset for the
# simple SELECT statement to operate on.
# EVIDENCE-OF: R-28355-09804 If there is more than one table or subquery
# in FROM clause then the contents of all tables and/or subqueries are
# joined into a single dataset for the simple SELECT statement to
# operate on.
#
# There are more detailed tests for subsequent requirements that add
# more detail to this idea. We just add a single test that shows that
@@ -383,10 +383,10 @@ do_select_tests e_select-1.3 {
# of cartesian joins in the SELECT documentation is consistent with SQLite.
# In doing so, we test the following three requirements as a side-effect:
#
# EVIDENCE-OF: R-46122-14930 If the join-op is "CROSS JOIN", "INNER
# JOIN", "JOIN" or a comma (",") and there is no ON or USING clause,
# then the result of the join is simply the cartesian product of the
# left and right-hand datasets.
# EVIDENCE-OF: R-49872-03192 If the join-operator is "CROSS JOIN",
# "INNER JOIN", "JOIN" or a comma (",") and there is no ON or USING
# clause, then the result of the join is simply the cartesian product of
# the left and right-hand datasets.
#
# The tests are built on this assertion. Really, they test that the output
# of a CROSS JOIN, JOIN, INNER JOIN or "," join matches the expected result
@@ -464,10 +464,10 @@ do_join_test e_select-1.4.2.1 {
]
# TODO: Come back and add a few more like the above.
# EVIDENCE-OF: R-20659-43267 In other words, if the left-hand dataset
# consists of Nlhs rows of Mlhs columns, and the right-hand dataset of
# Nrhs rows of Mrhs columns, then the cartesian product is a dataset of
# Nlhs.Nrhs rows, each containing Mlhs+Mrhs columns.
# EVIDENCE-OF: R-18439-38548 In other words, if the left-hand dataset
# consists of Nleft rows of Mleft columns, and the right-hand dataset of
# Nright rows of Mright columns, then the cartesian product is a dataset
# of Nleft&times;Nright rows, each containing Mleft+Mright columns.
#
# x1, x2 (Nlhs=3, Nrhs=2) (Mlhs=2, Mrhs=3)
do_join_test e_select-1.4.3.1 {
@@ -513,11 +513,10 @@ do_select_tests e_select-1.4.5 [list \
4 { SELECT * FROM t1 AS y INNER JOIN t1 AS x } $t1_cross_t1 \
]
# EVIDENCE-OF: R-22775-56496 If there is an ON clause specified, then
# the ON expression is evaluated for each row of the cartesian product
# as a boolean expression. All rows for which the expression evaluates
# to false are excluded from the dataset.
# EVIDENCE-OF: R-38465-03616 If there is an ON clause then the ON
# expression is evaluated for each row of the cartesian product as a
# boolean expression. Only rows for which the expression evaluates to
# true are included from the dataset.
#
foreach {tn select res} [list \
1 { SELECT * FROM t1 %JOIN% t2 ON (1) } $t1_cross_t2 \
@@ -540,9 +539,9 @@ foreach {tn select res} [list \
do_join_test e_select-1.3.$tn $select $res
}
# EVIDENCE-OF: R-63358-54862 If there is a USING clause specified as
# part of the join-constraint, then each of the column names specified
# must exist in the datasets to both the left and right of the join-op.
# EVIDENCE-OF: R-49933-05137 If there is a USING clause then each of the
# column names specified must exist in the datasets to both the left and
# right of the join-operator.
#
do_select_tests e_select-1.4 -error {
cannot join using column %s - column not present in both tables
@@ -552,10 +551,10 @@ do_select_tests e_select-1.4 -error {
3 { SELECT * FROM t3, (SELECT a AS b, b AS c FROM t1) USING (a) } "a"
}
# EVIDENCE-OF: R-55987-04584 For each pair of namesake columns, the
# EVIDENCE-OF: R-22776-52830 For each pair of named columns, the
# expression "lhs.X = rhs.X" is evaluated for each row of the cartesian
# product as a boolean expression. All rows for which one or more of the
# expressions evaluates to false are excluded from the result set.
# product as a boolean expression. Only rows for which all such
# expressions evaluates to true are included from the result set.
#
do_select_tests e_select-1.5 {
1 { SELECT * FROM t1, t3 USING (a) } {a one 1 b two 2}
@@ -566,8 +565,8 @@ do_select_tests e_select-1.5 {
# USING clause, the normal rules for handling affinities, collation
# sequences and NULL values in comparisons apply.
#
# EVIDENCE-OF: R-35466-18578 The column from the dataset on the
# left-hand side of the join operator is considered to be on the
# EVIDENCE-OF: R-38422-04402 The column from the dataset on the
# left-hand side of the join-operator is considered to be on the
# left-hand side of the comparison operator (=) for the purposes of
# collation sequence and affinity precedence.
#
@@ -622,10 +621,9 @@ foreach {tn select res} {
} {
do_join_test e_select-1.7.$tn $select $res
}
# EVIDENCE-OF: R-41434-12448 If the join-op is a "LEFT JOIN" or "LEFT
# OUTER JOIN", then after the ON or USING filtering clauses have been
# applied, an extra row is added to the output for each row in the
# EVIDENCE-OF: R-42531-52874 If the join-operator is a "LEFT JOIN" or
# "LEFT OUTER JOIN", then after the ON or USING filtering clauses have
# been applied, an extra row is added to the output for each row in the
# original left-hand input dataset that corresponds to no rows at all in
# the composite dataset (if any).
#
@@ -660,8 +658,8 @@ do_select_tests e_select-1.9 {
2b "SELECT * FROM t7 LEFT JOIN t8 USING (a)" {x ex 24 abc 24 y why 25 {} {}}
}
# EVIDENCE-OF: R-01809-52134 If the NATURAL keyword is added to any of
# the join-ops, then an implicit USING clause is added to the
# EVIDENCE-OF: R-04932-55942 If the NATURAL keyword is in the
# join-operator then an implicit USING clause is added to the
# join-constraints. The implicit USING clause contains each of the
# column names that appear in both the left and right-hand input
# datasets.
@@ -734,10 +732,10 @@ do_execsql_test e_select-3.0 {
INSERT INTO x2 VALUES(7, 'mistrusted', 'standardized');
} {}
# EVIDENCE-OF: R-06999-14330 If a WHERE clause is specified, the WHERE
# EVIDENCE-OF: R-60775-64916 If a WHERE clause is specified, the WHERE
# expression is evaluated for each row in the input data as a boolean
# expression. All rows for which the WHERE clause expression evaluates
# to false are excluded from the dataset before continuing.
# expression. Only rows for which the WHERE clause expression evaluates
# to true are included from the dataset before continuing.
#
do_execsql_test e_select-3.1.1 { SELECT k FROM x1 WHERE x } {3}
do_execsql_test e_select-3.1.2 { SELECT k FROM x1 WHERE y } {3 5 6}
@@ -815,8 +813,8 @@ do_select_tests e_select-4.1 {
}
}
# EVIDENCE-OF: R-61869-22578 It is an error to use a "*" or "alias.*"
# expression in any context other than than a result expression list.
# EVIDENCE-OF: R-38023-18396 It is an error to use a "*" or "alias.*"
# expression in any context other than a result expression list.
#
# EVIDENCE-OF: R-44324-41166 It is also an error to use a "*" or
# "alias.*" expression in a simple SELECT query that does not have a
@@ -1009,12 +1007,12 @@ do_execsql_test e_select-4.9.0 {
INSERT INTO b3 VALUES('dEF', 'dEF');
} {}
# EVIDENCE-OF: R-57754-57109 If the SELECT statement is an aggregate
# EVIDENCE-OF: R-07284-35990 If the SELECT statement is an aggregate
# query with a GROUP BY clause, then each of the expressions specified
# as part of the GROUP BY clause is evaluated for each row of the
# dataset. Each row is then assigned to a "group" based on the results;
# rows for which the results of evaluating the GROUP BY expressions are
# the same are assigned to the same group.
# the same get assigned to the same group.
#
# These tests also show that the following is not untrue:
#
@@ -1373,8 +1371,9 @@ foreach {tn select op1 op2} {
do_catchsql_test e_select-7.2.$tn $select [list 1 $err]
}
# EVIDENCE-OF: R-22874-32655 ORDER BY and LIMIT clauses may only occur
# at the end of the entire compound SELECT.
# EVIDENCE-OF: R-45440-25633 ORDER BY and LIMIT clauses may only occur
# at the end of the entire compound SELECT, and then only if the final
# element of the compound is not a VALUES clause.
#
foreach {tn select} {
1 "SELECT * FROM j1 UNION ALL SELECT * FROM j2,j3 ORDER BY a"
@@ -1386,6 +1385,7 @@ foreach {tn select} {
7 "SELECT * FROM j1 UNION SELECT * FROM j2,j3 ORDER BY a"
8 "SELECT count(*) FROM j1 UNION SELECT max(e) FROM j2 ORDER BY 1"
8b "VALUES('8b') UNION SELECT max(e) FROM j2 ORDER BY 1"
9 "SELECT count(*), * FROM j1 UNION SELECT *,* FROM j2 ORDER BY 1,2,3"
10 "SELECT * FROM j1 UNION SELECT * FROM j2,j3 LIMIT 10"
11 "SELECT * FROM j1 UNION SELECT * FROM j2,j3 LIMIT 10 OFFSET 5"
@@ -1407,6 +1407,14 @@ foreach {tn select} {
} {
do_test e_select-7.3.$tn { catch {execsql $select} msg } 0
}
foreach {tn select} {
50 "SELECT * FROM j1 ORDER BY 1 UNION ALL SELECT * FROM j2,j3"
51 "SELECT * FROM j1 LIMIT 1 UNION ALL SELECT * FROM j2,j3"
52 "SELECT count(*) FROM j1 UNION ALL VALUES(11) ORDER BY 1"
53 "SELECT count(*) FROM j1 UNION ALL VALUES(11) LIMIT 1"
} {
do_test e_select-7.3.$tn { catch {execsql $select} msg } 1
}
# EVIDENCE-OF: R-08531-36543 A compound SELECT created using UNION ALL
# operator returns all the rows from the SELECT to the left of the UNION
+15 -15
View File
@@ -344,10 +344,10 @@ foreach {tn indexes} {
catchsql { DROP INDEX i3 }
execsql $indexes
# EVIDENCE-OF: R-46122-14930 If the join-op is "CROSS JOIN", "INNER
# JOIN", "JOIN" or a comma (",") and there is no ON or USING clause,
# then the result of the join is simply the cartesian product of the
# left and right-hand datasets.
# EVIDENCE-OF: R-49872-03192 If the join-operator is "CROSS JOIN",
# "INNER JOIN", "JOIN" or a comma (",") and there is no ON or USING
# clause, then the result of the join is simply the cartesian product of
# the left and right-hand datasets.
#
# EVIDENCE-OF: R-46256-57243 There is no difference between the "INNER
# JOIN", "JOIN" and "," join operators.
@@ -368,10 +368,10 @@ foreach {tn indexes} {
test_join $tn.1.11 "t2 CROSS JOIN t2 AS x" {t2 t2}
test_join $tn.1.12 "t2 JOIN t2 AS x" {t2 t2}
# EVIDENCE-OF: R-22775-56496 If there is an ON clause specified, then
# the ON expression is evaluated for each row of the cartesian product
# as a boolean expression. All rows for which the expression evaluates
# to false are excluded from the dataset.
# EVIDENCE-OF: R-38465-03616 If there is an ON clause then the ON
# expression is evaluated for each row of the cartesian product as a
# boolean expression. Only rows for which the expression evaluates to
# true are included from the dataset.
#
test_join $tn.2.1 "t1, t2 ON (t1.a=t2.a)" {t1 t2 -on {te_equals a a}}
test_join $tn.2.2 "t2, t1 ON (t1.a=t2.a)" {t2 t1 -on {te_equals a a}}
@@ -504,14 +504,14 @@ do_execsql_test e_select-2.2.0 {
INSERT INTO t5 VALUES(2, 'two');
} {}
# EVIDENCE-OF: R-55824-40976 A sub-select specified in the join-source
# following the FROM clause in a simple SELECT statement is handled as
# if it was a table containing the data returned by executing the
# sub-select statement.
# EVIDENCE-OF: R-59237-46742 A subquery specified in the
# table-or-subquery following the FROM clause in a simple SELECT
# statement is handled as if it was a table containing the data returned
# by executing the subquery statement.
#
# EVIDENCE-OF: R-42612-06757 Each column of the sub-select dataset
# inherits the collation sequence and affinity of the corresponding
# expression in the sub-select statement.
# EVIDENCE-OF: R-27438-53558 Each column of the subquery has the
# collation sequence and affinity of the corresponding expression in the
# subquery statement.
#
foreach {tn subselect select spec} {
1 "SELECT * FROM t2" "SELECT * FROM t1 JOIN %ss%"
+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"} {incr nEph}
if {$op eq "OpenEphemeral" || $op eq "OpenHash"} {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 {OpenEphemeral} [db eval {
regexp {Open(Ephemeral|Hash)} [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 {OpenEphemeral} [db eval {
regexp {Open(Ephemeral|Hash)} [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 {OpenEphemeral} [db eval {
regexp {Open(Ephemeral|Hash)} [db eval {
EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t3z
}]
} {1}
+5 -3
View File
@@ -15,9 +15,11 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_test misc7-1-misuse {
c_misuse_test
} {}
if {[clang_sanitize_address]==0} {
do_test misc7-1-misuse {
c_misuse_test
} {}
}
do_test misc7-2 {
c_realloc_test
+32 -29
View File
@@ -171,37 +171,40 @@ do_test misuse-4.3 {
} msg]
lappend v $msg $r
} {0 {} SQLITE_BUSY}
do_test misuse-4.4 {
if {[clang_sanitize_address]==0} {
do_test misuse-4.4 {
# Flush the TCL statement cache here, otherwise the sqlite3_close() will
# fail because there are still un-finalized() VDBEs.
db cache flush
sqlite3_close $::DB
catchsql2 {SELECT * FROM t1}
} {1 {library routine called out of sequence}}
do_test misuse-4.5 {
catchsql {
SELECT * FROM t1
}
} {1 {library routine called out of sequence}}
db cache flush
sqlite3_close $::DB
catchsql2 {SELECT * FROM t1}
} {1 {library routine called out of sequence}}
do_test misuse-4.5 {
catchsql {
SELECT * FROM t1
}
} {1 {library routine called out of sequence}}
# Attempt to use a database after it has been closed.
#
do_test misuse-5.1 {
db close
sqlite3 db test2.db; set ::DB [sqlite3_connection_pointer db]
execsql {
SELECT * FROM t1
}
} {1 2}
do_test misuse-5.2 {
catchsql2 {SELECT * FROM t1}
} {0 {a b 1 2}}
do_test misuse-5.3 {
db close
set r [catch {
sqlite3_prepare $::DB {SELECT * FROM t1} -1 TAIL
} msg]
lappend r $msg
} {1 {(21) library routine called out of sequence}}
# Attempt to use a database after it has been closed.
#
do_test misuse-5.1 {
db close
sqlite3 db test2.db; set ::DB [sqlite3_connection_pointer db]
execsql {
SELECT * FROM t1
}
} {1 2}
do_test misuse-5.2 {
catchsql2 {SELECT * FROM t1}
} {0 {a b 1 2}}
do_test misuse-5.3 {
db close
set r [catch {
sqlite3_prepare $::DB {SELECT * FROM t1} -1 TAIL
} msg]
lappend r $msg
} {1 {(21) library routine called out of sequence}}
}
finish_test
+6 -1
View File
@@ -9,7 +9,7 @@
#
#***********************************************************************
#
# Tests for the SQLITE_IOERR_NODB error condition: the database file file
# Tests for the SQLITE_READONLY_DBMOVED error condition: the database file
# is unlinked or renamed out from under SQLite.
#
@@ -18,6 +18,11 @@ if {$tcl_platform(platform)!="unix"} return
set testdir [file dirname $argv0]
source $testdir/tester.tcl
if {[permutation]=="inmemory_journal"} {
finish_test
return
}
# Create a database file for testing
#
do_execsql_test pager4-1.1 {
+1
View File
@@ -1544,5 +1544,6 @@ do_faultsim_test pagerfault-36 -prep {
sqlite3_shutdown
sqlite3_config_uri 0
sqlite3_initialize
finish_test
+1 -1
View File
@@ -642,7 +642,7 @@ test_suite "inmemory_journal" -description {
ioerr.test ioerr2.test ioerr3.test ioerr4.test ioerr5.test
vacuum3.test incrblob_err.test diskfull.test backup_ioerr.test
e_fts3.test fts3cov.test fts3malloc.test fts3rnd.test
fts3snippet.test
fts3snippet.test mmapfault.test
# Exclude test scripts that use tcl IO to access journal files or count
# the number of fsync() calls.
+1 -1
View File
@@ -59,7 +59,7 @@ do_execsql_test printf2-1.11 {
SELECT printf('%lld%n',314159.2653,'hi');
} {314159}
# EVIDENCE-OF: R-20555-31089 The %z format is interchangable with %s.
# EVIDENCE-OF: R-17002-27534 The %z format is interchangeable with %s.
#
do_execsql_test printf2-1.12 {
SELECT printf('%.*z',5,'abcdefghijklmnop');
+16 -14
View File
@@ -138,21 +138,23 @@ ifcapable {subquery && compound} {
# Verify that an error occurs if you have too many terms on a
# compound select statement.
#
ifcapable compound {
if {$SQLITE_MAX_COMPOUND_SELECT>0} {
set sql {SELECT 0}
set result 0
for {set i 1} {$i<$SQLITE_MAX_COMPOUND_SELECT} {incr i} {
append sql " UNION ALL SELECT $i"
lappend result $i
if {[clang_sanitize_address]==0} {
ifcapable compound {
if {$SQLITE_MAX_COMPOUND_SELECT>0} {
set sql {SELECT 0}
set result 0
for {set i 1} {$i<$SQLITE_MAX_COMPOUND_SELECT} {incr i} {
append sql " UNION ALL SELECT $i"
lappend result $i
}
do_test select7-6.1 {
catchsql $sql
} [list 0 $result]
append sql { UNION ALL SELECT 99999999}
do_test select7-6.2 {
catchsql $sql
} {1 {too many terms in compound SELECT}}
}
do_test select7-6.1 {
catchsql $sql
} [list 0 $result]
append sql { UNION ALL SELECT 99999999}
do_test select7-6.2 {
catchsql $sql
} {1 {too many terms in compound SELECT}}
}
}
+47
View File
@@ -221,6 +221,53 @@ foreach {tn word res} {
} $res
}
#-------------------------------------------------------------------------
# Try some queries by rowid.
#
do_execsql_test 6.1.1 {
SELECT word FROM t3 WHERE rowid = 10;
} {keener}
do_execsql_test 6.1.2 {
SELECT word, distance FROM t3 WHERE rowid = 10;
} {keener {}}
do_execsql_test 6.1.3 {
SELECT word, distance FROM t3 WHERE rowid = 10 AND word MATCH 'kiiner';
} {keener 300}
ifcapable trace {
proc trace_callback {sql} {
if {[string range $sql 0 2] == "-- "} {
lappend ::trace [string range $sql 3 end]
}
}
proc do_tracesql_test {tn sql {res {}}} {
set ::trace [list]
uplevel [list do_test $tn [subst -nocommands {
set vals [execsql {$sql}]
concat [set vals] [set ::trace]
}] [list {*}$res]]
}
db trace trace_callback
do_tracesql_test 6.2.1 {
SELECT word FROM t3 WHERE rowid = 10;
} {keener
{SELECT word, rank, NULL, langid, id FROM "main"."t3_vocab" WHERE rowid=?}
}
do_tracesql_test 6.2.2 {
SELECT word, distance FROM t3 WHERE rowid = 10;
} {keener {}
{SELECT word, rank, NULL, langid, id FROM "main"."t3_vocab" WHERE rowid=?}
}
do_tracesql_test 6.2.3 {
SELECT word, distance FROM t3 WHERE rowid = 10 AND word MATCH 'kiiner';
} {keener 300
{SELECT id, word, rank, k1 FROM "main"."t3_vocab" WHERE langid=0 AND k2>=?1 AND k2<?2}
}
}
finish_test
+14
View File
@@ -59,6 +59,7 @@
# do_test TESTNAME SCRIPT EXPECTED
# do_execsql_test TESTNAME SQL EXPECTED
# do_catchsql_test TESTNAME SQL EXPECTED
# do_timed_execsql_test TESTNAME SQL EXPECTED
#
# Commands providing a lower level interface to the global test counters:
#
@@ -717,6 +718,11 @@ proc do_catchsql_test {testname sql result} {
fix_testname testname
uplevel do_test [list $testname] [list "catchsql {$sql}"] [list $result]
}
proc do_timed_execsql_test {testname sql {result {}}} {
fix_testname testname
uplevel do_test [list $testname] [list "execsql_timed {$sql}"]\
[list [list {*}$result]]
}
proc do_eqp_test {name sql res} {
uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] [list $res]
}
@@ -1013,6 +1019,14 @@ proc execsql {sql {db db}} {
# puts "SQL = $sql"
uplevel [list $db eval $sql]
}
proc execsql_timed {sql {db db}} {
set tm [time {
set x [uplevel [list $db eval $sql]]
} 1]
set tm [lindex $tm 0]
puts -nonewline " ([expr {$tm*0.001}]ms) "
set x
}
# Execute SQL and catch exceptions.
#
+367 -2
View File
@@ -374,7 +374,7 @@ do_catchsql_test 7.6 {
# Compute the mandelbrot set using a recursive query
#
do_execsql_test 8.1 {
do_execsql_test 8.1-mandelbrot {
WITH RECURSIVE
xaxis(x) AS (VALUES(-2.0) UNION ALL SELECT x+0.05 FROM xaxis WHERE x<1.2),
yaxis(y) AS (VALUES(-1.0) UNION ALL SELECT y+0.1 FROM yaxis WHERE y<1.0),
@@ -417,7 +417,7 @@ do_execsql_test 8.1 {
# Solve a sudoku puzzle using a recursive query
#
do_execsql_test 8.2 {
do_execsql_test 8.2-soduko {
WITH RECURSIVE
input(sud) AS (
VALUES('53..7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79')
@@ -452,4 +452,369 @@ do_execsql_test 8.2 {
SELECT s FROM x WHERE ind=0;
} {534678912672195348198342567859761423426853791713924856961537284287419635345286179}
#--------------------------------------------------------------------------
# Some tests that use LIMIT and OFFSET in the definition of recursive CTEs.
#
set I [list 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
proc limit_test {tn iLimit iOffset} {
if {$iOffset < 0} { set iOffset 0 }
if {$iLimit < 0 } {
set result [lrange $::I $iOffset end]
} else {
set result [lrange $::I $iOffset [expr $iLimit+$iOffset-1]]
}
uplevel [list do_execsql_test $tn [subst -nocommands {
WITH ii(a) AS (
VALUES(1)
UNION ALL
SELECT a+1 FROM ii WHERE a<20
LIMIT $iLimit OFFSET $iOffset
)
SELECT * FROM ii
}] $result]
}
limit_test 9.1 20 0
limit_test 9.2 0 0
limit_test 9.3 19 1
limit_test 9.4 20 -1
limit_test 9.5 5 5
limit_test 9.6 0 -1
limit_test 9.7 40 -1
limit_test 9.8 -1 -1
limit_test 9.9 -1 -1
#--------------------------------------------------------------------------
# Test the ORDER BY clause on recursive tables.
#
do_execsql_test 10.1 {
DROP TABLE IF EXISTS tree;
CREATE TABLE tree(id INTEGER PRIMARY KEY, parentid, payload);
}
proc insert_into_tree {L} {
db eval { DELETE FROM tree }
foreach key $L {
unset -nocomplain parentid
foreach seg [split $key /] {
if {$seg==""} continue
set id [db one {
SELECT id FROM tree WHERE parentid IS $parentid AND payload=$seg
}]
if {$id==""} {
db eval { INSERT INTO tree VALUES(NULL, $parentid, $seg) }
set parentid [db last_insert_rowid]
} else {
set parentid $id
}
}
}
}
insert_into_tree {
/a/a/a
/a/b/c
/a/b/c/d
/a/b/d
}
do_execsql_test 10.2 {
WITH flat(fid, p) AS (
SELECT id, '/' || payload FROM tree WHERE parentid IS NULL
UNION ALL
SELECT id, p || '/' || payload FROM flat, tree WHERE parentid=fid
)
SELECT p FROM flat ORDER BY p;
} {
/a /a/a /a/a/a
/a/b /a/b/c /a/b/c/d
/a/b/d
}
# Scan the tree-structure currently stored in table tree. Return a list
# of nodes visited.
#
proc scan_tree {bDepthFirst bReverse} {
set order "ORDER BY "
if {$bDepthFirst==0} { append order "2 ASC," }
if {$bReverse==0} {
append order " 3 ASC"
} else {
append order " 3 DESC"
}
db eval "
WITH flat(fid, depth, p) AS (
SELECT id, 1, '/' || payload FROM tree WHERE parentid IS NULL
UNION ALL
SELECT id, depth+1, p||'/'||payload FROM flat, tree WHERE parentid=fid
$order
)
SELECT p FROM flat;
"
}
insert_into_tree {
/a/b
/a/b/c
/a/d
/a/d/e
/a/d/f
/g/h
}
# Breadth first, siblings in ascending order.
#
do_test 10.3 {
scan_tree 0 0
} [list {*}{
/a /g
/a/b /a/d /g/h
/a/b/c /a/d/e /a/d/f
}]
# Depth first, siblings in ascending order.
#
do_test 10.4 {
scan_tree 1 0
} [list {*}{
/a /a/b /a/b/c
/a/d /a/d/e
/a/d/f
/g /g/h
}]
# Breadth first, siblings in descending order.
#
do_test 10.5 {
scan_tree 0 1
} [list {*}{
/g /a
/g/h /a/d /a/b
/a/d/f /a/d/e /a/b/c
}]
# Depth first, siblings in ascending order.
#
do_test 10.6 {
scan_tree 1 1
} [list {*}{
/g /g/h
/a /a/d /a/d/f
/a/d/e
/a/b /a/b/c
}]
# Test name resolution in ORDER BY clauses.
#
do_catchsql_test 10.7.1 {
WITH t(a) AS (
SELECT 1 AS b UNION ALL SELECT a+1 AS c FROM t WHERE a<5 ORDER BY a
)
SELECT * FROM t
} {1 {1st ORDER BY term does not match any column in the result set}}
do_execsql_test 10.7.2 {
WITH t(a) AS (
SELECT 1 AS b UNION ALL SELECT a+1 AS c FROM t WHERE a<5 ORDER BY b
)
SELECT * FROM t
} {1 2 3 4 5}
do_execsql_test 10.7.3 {
WITH t(a) AS (
SELECT 1 AS b UNION ALL SELECT a+1 AS c FROM t WHERE a<5 ORDER BY c
)
SELECT * FROM t
} {1 2 3 4 5}
# Test COLLATE clauses attached to ORDER BY.
#
insert_into_tree {
/a/b
/a/C
/a/d
/B/e
/B/F
/B/g
/c/h
/c/I
/c/j
}
do_execsql_test 10.8.1 {
WITH flat(fid, depth, p) AS (
SELECT id, 1, '/' || payload FROM tree WHERE parentid IS NULL
UNION ALL
SELECT id, depth+1, p||'/'||payload FROM flat, tree WHERE parentid=fid
ORDER BY 2, 3 COLLATE nocase
)
SELECT p FROM flat;
} {
/a /B /c
/a/b /a/C /a/d /B/e /B/F /B/g /c/h /c/I /c/j
}
do_execsql_test 10.8.2 {
WITH flat(fid, depth, p) AS (
SELECT id, 1, ('/' || payload) COLLATE nocase
FROM tree WHERE parentid IS NULL
UNION ALL
SELECT id, depth+1, (p||'/'||payload)
FROM flat, tree WHERE parentid=fid
ORDER BY 2, 3
)
SELECT p FROM flat;
} {
/a /B /c
/a/b /a/C /a/d /B/e /B/F /B/g /c/h /c/I /c/j
}
do_execsql_test 10.8.3 {
WITH flat(fid, depth, p) AS (
SELECT id, 1, ('/' || payload)
FROM tree WHERE parentid IS NULL
UNION ALL
SELECT id, depth+1, (p||'/'||payload) COLLATE nocase
FROM flat, tree WHERE parentid=fid
ORDER BY 2, 3
)
SELECT p FROM flat;
} {
/a /B /c
/a/b /a/C /a/d /B/e /B/F /B/g /c/h /c/I /c/j
}
do_execsql_test 10.8.4.1 {
CREATE TABLE tst(a,b);
INSERT INTO tst VALUES('a', 'A');
INSERT INTO tst VALUES('b', 'B');
INSERT INTO tst VALUES('c', 'C');
SELECT a COLLATE nocase FROM tst UNION ALL SELECT b FROM tst ORDER BY 1;
} {a A b B c C}
do_execsql_test 10.8.4.2 {
SELECT a FROM tst UNION ALL SELECT b COLLATE nocase FROM tst ORDER BY 1;
} {A B C a b c}
do_execsql_test 10.8.4.3 {
SELECT a||'' FROM tst UNION ALL SELECT b COLLATE nocase FROM tst ORDER BY 1;
} {a A b B c C}
# Test cases to illustrate on the ORDER BY clause on a recursive query can be
# used to control depth-first versus breath-first search in a tree.
#
do_execsql_test 11.1 {
CREATE TABLE org(
name TEXT PRIMARY KEY,
boss TEXT REFERENCES org
) WITHOUT ROWID;
INSERT INTO org VALUES('Alice',NULL);
INSERT INTO org VALUES('Bob','Alice');
INSERT INTO org VALUES('Cindy','Alice');
INSERT INTO org VALUES('Dave','Bob');
INSERT INTO org VALUES('Emma','Bob');
INSERT INTO org VALUES('Fred','Cindy');
INSERT INTO org VALUES('Gail','Cindy');
INSERT INTO org VALUES('Harry','Dave');
INSERT INTO org VALUES('Ingrid','Dave');
INSERT INTO org VALUES('Jim','Emma');
INSERT INTO org VALUES('Kate','Emma');
INSERT INTO org VALUES('Lanny','Fred');
INSERT INTO org VALUES('Mary','Fred');
INSERT INTO org VALUES('Noland','Gail');
INSERT INTO org VALUES('Olivia','Gail');
-- The above are all under Alice. Add a few more records for people
-- not in Alice's group, just to prove that they won't be selected.
INSERT INTO org VALUES('Xaviar',NULL);
INSERT INTO org VALUES('Xia','Xaviar');
INSERT INTO org VALUES('Xerxes','Xaviar');
INSERT INTO org VALUES('Xena','Xia');
-- Find all members of Alice's group, breath-first order
WITH RECURSIVE
under_alice(name,level) AS (
VALUES('Alice','0')
UNION ALL
SELECT org.name, under_alice.level+1
FROM org, under_alice
WHERE org.boss=under_alice.name
ORDER BY 2
)
SELECT group_concat(substr('...............',1,level*3) || name,x'0a')
FROM under_alice;
} {{Alice
...Bob
...Cindy
......Dave
......Emma
......Fred
......Gail
.........Harry
.........Ingrid
.........Jim
.........Kate
.........Lanny
.........Mary
.........Noland
.........Olivia}}
# The previous query used "ORDER BY level" to yield a breath-first search.
# Change that to "ORDER BY level DESC" for a depth-first search.
#
do_execsql_test 11.2 {
WITH RECURSIVE
under_alice(name,level) AS (
VALUES('Alice','0')
UNION ALL
SELECT org.name, under_alice.level+1
FROM org, under_alice
WHERE org.boss=under_alice.name
ORDER BY 2 DESC
)
SELECT group_concat(substr('...............',1,level*3) || name,x'0a')
FROM under_alice;
} {{Alice
...Bob
......Dave
.........Harry
.........Ingrid
......Emma
.........Jim
.........Kate
...Cindy
......Fred
.........Lanny
.........Mary
......Gail
.........Noland
.........Olivia}}
# Without an ORDER BY clause, the recursive query should use a FIFO,
# resulting in a breath-first search.
#
do_execsql_test 11.3 {
WITH RECURSIVE
under_alice(name,level) AS (
VALUES('Alice','0')
UNION ALL
SELECT org.name, under_alice.level+1
FROM org, under_alice
WHERE org.boss=under_alice.name
)
SELECT group_concat(substr('...............',1,level*3) || name,x'0a')
FROM under_alice;
} {{Alice
...Bob
...Cindy
......Dave
......Emma
......Fred
......Gail
.........Harry
.........Ingrid
.........Jim
.........Kate
.........Lanny
.........Mary
.........Noland
.........Olivia}}
finish_test
+1
View File
@@ -190,6 +190,7 @@ proc main {argv} {
SQLITE_OMIT_COMPILEOPTION_DIAGS \
SQLITE_OMIT_COMPLETE \
SQLITE_OMIT_COMPOUND_SELECT \
SQLITE_OMIT_CTE \
SQLITE_OMIT_DATETIME_FUNCS \
SQLITE_OMIT_DECLTYPE \
SQLITE_OMIT_DEPRECATED \
+5 -6
View File
@@ -119,7 +119,7 @@ static unsigned char *print_byte_range(
/*
** Print an entire page of content as hex
*/
static print_page(int iPg){
static void print_page(int iPg){
int iStart;
unsigned char *aData;
iStart = (iPg-1)*pagesize;
@@ -131,7 +131,7 @@ static print_page(int iPg){
/* Print a line of decode output showing a 4-byte integer.
*/
static print_decode_line(
static void print_decode_line(
unsigned char *aData, /* Content being decoded */
int ofst, int nByte, /* Start and size of decode */
const char *zMsg /* Message to append */
@@ -428,7 +428,7 @@ static void decode_trunk_page(
int detail, /* Show leaf pages if true */
int recursive /* Follow the trunk change if true */
){
int n, i, k;
int n, i;
unsigned char *a;
while( pgno>0 ){
a = getContent((pgno-1)*pagesize, pagesize);
@@ -495,7 +495,6 @@ static void page_usage_cell(
int cellno /* Index of the cell on the page */
){
int i;
int nDesc = 0;
int n = 0;
i64 nPayload;
i64 rowid;
@@ -677,7 +676,7 @@ static void page_usage_report(const char *zDbName){
if( rc==SQLITE_OK ){
while( sqlite3_step(pStmt)==SQLITE_ROW ){
int pgno = sqlite3_column_int(pStmt, 2);
page_usage_btree(pgno, 0, 0, sqlite3_column_text(pStmt, 1));
page_usage_btree(pgno, 0, 0, (const char*)sqlite3_column_text(pStmt,1));
}
}else{
printf("ERROR: cannot query database: %s\n", sqlite3_errmsg(db));
@@ -835,7 +834,6 @@ int main(int argc, char **argv){
free(a);
continue;
}else if( zLeft && zLeft[0]=='t' ){
unsigned char *a;
int detail = 0;
int recursive = 0;
int i;
@@ -861,4 +859,5 @@ int main(int argc, char **argv){
}
}
close(db);
return 0;
}