Compare commits

..

42 Commits

Author SHA1 Message Date
drh 37f686bd33 Break up the sqlite3BtreeMovetoUnpacked() routine into an eponymous routine
and sqlite3BtreeMovetoIntkey().  Each routine specializes in a single kind of
btree.

FossilOrigin-Name: 9a64a4f2353576ba742c2ddbf4264d00704066a1
2016-11-10 21:19:35 +00:00
drh 7a1c28defe Avoid a few unnecessary calls to sqlite3BtreeMovetoUnpacked().
FossilOrigin-Name: eac0e827a61cfec4dd9b6d407ff398e9fda3510b
2016-11-10 20:42:08 +00:00
drh c6c9e158c5 When doing a REPLACE on a WITHOUT ROWID table with no secondary indexes,
bypass the OP_NoConflict/OP_Delete sequence and directly overwrite any
preexisting row, for a performance increase.

FossilOrigin-Name: f7041cbb63b912f9ecad538804b6f2383efbec4e
2016-11-10 17:01:36 +00:00
drh bf2f5739c9 Remove C++ style comments. No code changes.
FossilOrigin-Name: 42f8aa6231bf4ed74bebdc85aa79d23dc20b3c14
2016-11-10 16:07:43 +00:00
drh 2c4dfc3095 Add the unpacked key fields to OP_IdxInsert for INSERT and UPDATE statements.
FossilOrigin-Name: 67602e40f122cbb6354048a64c5d3a72b2855ec7
2016-11-10 14:24:04 +00:00
drh eaf6ae2992 Comment changes that attempt to better explain the behavior of the "seekResult"
field on VdbeCursor objects and the seekResult parameter to
sqlite3BtreeInsert() and the OPFLAG_USESEEKRESULT flag on insert opcodes.
No changes to code.

FossilOrigin-Name: 345b46be75bdf6f9fb7367a6164d89bae11995a6
2016-11-09 20:14:34 +00:00
drh 7405fa745e Fix a simple comment typo. No changes to code.
FossilOrigin-Name: 51d0aed8d63d0710e4aa8925ff18cf3c45dc9e42
2016-11-09 16:03:36 +00:00
drh 4a8b013ef6 Make use of the unpacked key on the OP_IdxInsert on sorters with a LIMIT.
FossilOrigin-Name: 42db7cd2c0b367f7dfe733bdaf006538937b812a
2016-11-09 01:38:56 +00:00
drh fb8c56f21b Fix a typo on the OP_IdxInsert documentation. No code changes.
FossilOrigin-Name: e4acd98207bf12b28f6c0f77896ba8f0b0a155d5
2016-11-09 01:19:25 +00:00
drh 9b4eaebc68 Enhance the OP_IdxInsert opcode to optionally accept unpacked key material.
FossilOrigin-Name: 89d958abbac45f2ca5954080cd9e74ec9a07ebb2
2016-11-09 00:10:33 +00:00
dan 3b908d41a0 Avoid superfluous cursor seeks in "INSERT OR REPLACE" statements.
FossilOrigin-Name: bec5b6d4d083556d111a89186b4f7b35b5e7cebf
2016-11-08 19:22:32 +00:00
drh 9d06ff2cb7 Avoid generating OP_TableLock unnecessary instructions on btrees that
are not sharable.

FossilOrigin-Name: 8cb8516d2009d52d35a22263e4c892f162b34b81
2016-11-08 17:19:22 +00:00
drh 0a22c865e4 Fix the speedtest1.c test program so that it gives closing "%" wildcards
on LIKE searches.

FossilOrigin-Name: c2f84f637f994c3b4522b48161185a4a2c5bca23
2016-11-08 16:27:59 +00:00
drh 662389b265 Tweaks to speedtest1.c to better reflect mobile usage based on findings in
the "Pocket Data" paper by Kennedy, Ajay, Challen, and Ziarek.

FossilOrigin-Name: b5733cae3c519482cf6bc642bd63814afb113d35
2016-11-08 00:30:11 +00:00
drh 6850a63393 Fix OOM error reporting in the json1_group_object() SQL function. Remove
an unreachable branch from the JSON1 logic.

FossilOrigin-Name: b54098491531cd26ed461275ef4aae3d3ec9065e
2016-11-07 18:18:08 +00:00
drh 27b2d1b88b Replace some unreachable branches from the JSON1 extension with assert().
FossilOrigin-Name: 145cd13e3c5a42a717807bcc13c0f7212f38bff8
2016-11-07 15:15:42 +00:00
drh ad875e7416 Fix the JSON1 extension so that the JSON validator correctly rejects malformed
backslash escapes within string literals.

FossilOrigin-Name: 7a63539169a384960e30a63e0c8e9b0f07fa431e
2016-11-07 13:37:28 +00:00
dan a2bfa046ea Avoid a crash that can occur after an obscure OOM in the built-in INSTR()
function.

FossilOrigin-Name: b86b79c442a58d10aa005ba4f34095375a88d242
2016-11-04 12:05:29 +00:00
drh b1c9633493 Mark the ICU extension functions as deterministic.
FossilOrigin-Name: afbbb6c66a85ff3f4c8dce677e0892a2a51d2b8e
2016-11-04 12:03:26 +00:00
drh 54fc5cc2ae Add an assert() to silence a coverity false-positive.
FossilOrigin-Name: 97354093bceff28714a605068851cfa026c8272a
2016-11-04 11:23:30 +00:00
dan 792557ac67 Fix a test case in vacuum5.test so that it works with the in-memory journal
permutation.

FossilOrigin-Name: 81c86401463df6be4ac21987b3b1703e38ab933b
2016-11-04 07:25:43 +00:00
mistachkin a622d90040 Replace a couple more references to Tcl 8.5 in the Windows build tools.
FossilOrigin-Name: 1d0e43c549c36d0919a18d61285e94cad29e7a07
2016-11-03 21:35:10 +00:00
dan af58068550 Fix a test case in vacuum5.test sot aht it works with
-DSQLITE_ENABLE_ATOMIC_WRITE.

FossilOrigin-Name: 3ca80010397676eca57c8a4c9b3a9c2c40629663
2016-11-03 19:24:14 +00:00
dan 7df9b8e6e4 Fix a test case in vacuum5.test so that it works with -DSQLITE_TEMP_STORE=2.
FossilOrigin-Name: f5dd95e25c703a825ad7af9a4b3886bd3ef8c2e8
2016-11-03 19:01:20 +00:00
drh 59ce2c434c In the command-line shell, fix the .imposter command so that it works
with indexes on expressions.  Fix the ".mode quote" mode so that it works
with ".headers ON".

FossilOrigin-Name: ba9873da94d21873ff76f16a5332fc0092d83f70
2016-11-03 13:12:28 +00:00
drh 16eb59484f Add the ".imposter" command to the command-line shell.
FossilOrigin-Name: be3ec8fdcf1541017ca9375df07645db2a9a3f5a
2016-11-03 13:01:38 +00:00
drh 6027561178 Fix an possible NULL pointer deference in the command-line shell that can
occur when using imposter mode.

FossilOrigin-Name: ad08753a8bbf073ec4af9c3a5783ed664244d954
2016-11-03 02:25:30 +00:00
drh 506a1400a3 Adjust the MSVC makefile to use Tcl8.6 by default.
FossilOrigin-Name: def8f598b8e33b5bab3a024cc57f4c5e300cd8cd
2016-11-02 19:49:22 +00:00
dan 75ba676790 Fix an issue that was causing the new database image to be assembled entirely
in heap memory when VACUUMing a database, even if it should use a temp file.
This could cause SQLITE_NOMEM errors when vacuuming very large databases on
32-bit systems.

FossilOrigin-Name: 3028845329c9b7acdec2ec8b01d00d782347454c
2016-11-02 14:50:19 +00:00
drh e77caa191b Fix a requirement mark. No changes to code.
FossilOrigin-Name: d18f61b78c8fafef742efbc890382537e8584180
2016-11-02 13:18:46 +00:00
drh 1ad93a003d Use NOT NULL partial indexes when the query is constrained by a single
LIKE or GLOB.

FossilOrigin-Name: 9b3a3b41b59a7ce7d3dd82c7402d6fdc6a5ca43c
2016-11-02 02:17:52 +00:00
dan d7265378fd Add the SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE sqlite3_dbconfig() option - for
disabling SQLite's default checkpoint-on-close behaviour.

FossilOrigin-Name: 6d142025c74f66f2d48155354b556cd5b2682cb2
2016-10-31 16:49:18 +00:00
dan 298af02308 Add the SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE sqlite3_dbconfig() option - for
disabling SQLite's default checkpoint-on-close behaviour.

FossilOrigin-Name: 093d2fc2288b75c15ccf877bfa0e622d3918a562
2016-10-31 16:16:49 +00:00
dan dadafa881f Remove the mutex from test_multiplex.c.
FossilOrigin-Name: 6374978e8f1ac091394a9f5a1896be92af658bcd
2016-10-27 14:51:02 +00:00
drh c52496f57f Make sure left-join markings are transferred to the virtual scalar
subexpressions when decomposing a vector comparison in the ON clause of
a LEFT JOIN.
Fix for ticket [fef4bb4bd9185ec8f].

FossilOrigin-Name: 619f5cc71774a37648e185c8502d7af14eb09b7f
2016-10-27 01:02:20 +00:00
drh 9904298bb3 Small size reduction and performance enhancement in whereScanInit().
FossilOrigin-Name: c23f5ef337533c1ec6e3ba78a2910352181cc9ee
2016-10-26 18:41:43 +00:00
drh 392ddeb12d Small size reduction and performance improvement in whereScanNext().
FossilOrigin-Name: d861ee17eb900a607de6ec3f4a5d5c24cfb834a0
2016-10-26 17:57:40 +00:00
dan d15f430111 If all branches of an OR optimize scan that is the rhs of a LEFT JOIN use the
same index, set the index cursor to return NULL values if there are no matches
for a row on the lhs.

FossilOrigin-Name: ec9dab8054c71d112c68f58a45821b38c2a45677
2016-10-26 16:05:10 +00:00
dan b40897ab5e If all branches of an OR optimize scan that is the rhs of a LEFT JOIN use the
same index, set the index cursor to return NULL values if there are no matches
for a row on the lhs.

FossilOrigin-Name: e7b9bc678ecb75c594d9d3ade12a99a8d551cdc9
2016-10-26 15:46:09 +00:00
drh d240f091c6 Merge the SQLITE_ENABLE_URI_00_ERROR compile-time option.
FossilOrigin-Name: 86675ae0abc78960a2faec55d115804acfc3be6d
2016-10-26 13:58:47 +00:00
dan 635f83c062 Add extra tests to check the result of including a %00 escape in a URI
when ENABLE_URI_00_ERROR is defined.

FossilOrigin-Name: 1aaa06e37f44309c62335d8eda59ca6890d4be9d
2016-10-26 13:44:07 +00:00
dan 5c35e90377 Add compile time option SQLITE_ENABLE_URI_00_ERROR. If defined, any "%00"
escape found in a URI is treated as an error.

FossilOrigin-Name: e8a9bfece27e2af178a206ad6bce3f24d64e7ee4
2016-10-26 12:15:41 +00:00
47 changed files with 1297 additions and 499 deletions
+3 -3
View File
@@ -794,11 +794,11 @@ TCLLIBDIR = c:\tcl\lib
!ENDIF
!IFNDEF LIBTCL
LIBTCL = tcl85.lib
LIBTCL = tcl86.lib
!ENDIF
!IFNDEF LIBTCLSTUB
LIBTCLSTUB = tclstub85.lib
LIBTCLSTUB = tclstub86.lib
!ENDIF
!IFNDEF LIBTCLPATH
@@ -828,7 +828,7 @@ LIBICU = icuuc.lib icuin.lib
# specific Tcl shell to use.
#
!IFNDEF TCLSH_CMD
TCLSH_CMD = tclsh85
TCLSH_CMD = tclsh
!ENDIF
# <</mark>>
+11 -11
View File
@@ -500,20 +500,20 @@ int sqlite3IcuInit(sqlite3 *db){
void *pContext; /* sqlite3_user_data() context */
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} scalars[] = {
{"regexp", 2, SQLITE_ANY, 0, icuRegexpFunc},
{"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc},
{"lower", 1, SQLITE_UTF16, 0, icuCaseFunc16},
{"lower", 2, SQLITE_UTF16, 0, icuCaseFunc16},
{"upper", 1, SQLITE_UTF16, (void*)1, icuCaseFunc16},
{"upper", 2, SQLITE_UTF16, (void*)1, icuCaseFunc16},
{"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"upper", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
{"upper", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
{"lower", 1, SQLITE_UTF8, 0, icuCaseFunc16},
{"lower", 2, SQLITE_UTF8, 0, icuCaseFunc16},
{"upper", 1, SQLITE_UTF8, (void*)1, icuCaseFunc16},
{"upper", 2, SQLITE_UTF8, (void*)1, icuCaseFunc16},
{"lower", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"lower", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
{"upper", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
{"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, (void*)1, icuCaseFunc16},
{"like", 2, SQLITE_UTF8, 0, icuLikeFunc},
{"like", 3, SQLITE_UTF8, 0, icuLikeFunc},
{"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
{"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
{"icu_load_collation", 2, SQLITE_UTF8, (void*)db, icuLoadCollation},
};
+31 -14
View File
@@ -49,13 +49,15 @@ SQLITE_EXTENSION_INIT1
#ifdef sqlite3Isdigit
/* Use the SQLite core versions if this routine is part of the
** SQLite amalgamation */
# define safe_isdigit(x) sqlite3Isdigit(x)
# define safe_isalnum(x) sqlite3Isalnum(x)
# define safe_isdigit(x) sqlite3Isdigit(x)
# define safe_isalnum(x) sqlite3Isalnum(x)
# define safe_isxdigit(x) sqlite3Isxdigit(x)
#else
/* Use the standard library for separate compilation */
#include <ctype.h> /* amalgamator: keep */
# define safe_isdigit(x) isdigit((unsigned char)(x))
# define safe_isalnum(x) isalnum((unsigned char)(x))
# define safe_isdigit(x) isdigit((unsigned char)(x))
# define safe_isalnum(x) isalnum((unsigned char)(x))
# define safe_isxdigit(x) isxdigit((unsigned char)(x))
#endif
/*
@@ -593,12 +595,13 @@ static void jsonReturn(
c = z[++i];
if( c=='u' ){
u32 v = 0, k;
for(k=0; k<4 && i<n-2; i++, k++){
for(k=0; k<4; i++, k++){
assert( i<n-2 );
c = z[i+1];
if( c>='0' && c<='9' ) v = v*16 + c - '0';
else if( c>='A' && c<='F' ) v = v*16 + c - 'A' + 10;
else if( c>='a' && c<='f' ) v = v*16 + c - 'a' + 10;
else break;
assert( safe_isxdigit(c) );
if( c<='9' ) v = v*16 + c - '0';
else if( c<='F' ) v = v*16 + c - 'A' + 10;
else v = v*16 + c - 'a' + 10;
}
if( v==0 ) break;
if( v<=0x7f ){
@@ -702,6 +705,15 @@ static int jsonParseAddNode(
return pParse->nNode++;
}
/*
** Return true if z[] begins with 4 (or more) hexadecimal digits
*/
static int jsonIs4Hex(const char *z){
int i;
for(i=0; i<4; i++) if( !safe_isxdigit(z[i]) ) return 0;
return 1;
}
/*
** Parse a single JSON value which begins at pParse->zJson[i]. Return the
** index of the first character past the end of the value parsed.
@@ -776,8 +788,13 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
if( c==0 ) return -1;
if( c=='\\' ){
c = pParse->zJson[++j];
if( c==0 ) return -1;
jnFlags = JNODE_ESCAPE;
if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f'
|| c=='n' || c=='r' || c=='t'
|| (c=='u' && jsonIs4Hex(pParse->zJson+j+1)) ){
jnFlags = JNODE_ESCAPE;
}else{
return -1;
}
}else if( c=='"' ){
break;
}
@@ -1645,7 +1662,7 @@ static void jsonObjectFinal(sqlite3_context *ctx){
if( pStr ){
jsonAppendChar(pStr, '}');
if( pStr->bErr ){
if( pStr->bErr==0 ) sqlite3_result_error_nomem(ctx);
if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
assert( pStr->bStatic );
}else{
sqlite3_result_text(ctx, pStr->zBuf, pStr->nUsed,
@@ -1923,9 +1940,9 @@ static int jsonEachColumn(
/* For json_each() path and root are the same so fall through
** into the root case */
}
case JEACH_ROOT: {
default: {
const char *zRoot = p->zRoot;
if( zRoot==0 ) zRoot = "$";
if( zRoot==0 ) zRoot = "$";
sqlite3_result_text(ctx, zRoot, -1, SQLITE_STATIC);
break;
}
+53 -50
View File
@@ -1,8 +1,8 @@
C Enhance\sthe\s"PRAGMA\sindex_info"\sand\s"PRAGMA\sindex_xinfo"\sstatements\sso\sthat\nthey\swork\son\sWITHOUT\sROWID\stables\sand\sprovide\sinformation\sabout\sthe\sunderlying\nindex\sbtree\sthat\simplements\sthe\sWITHOUT\sROWID\stable.
D 2016-10-25T15:39:58.696
C Break\sup\sthe\ssqlite3BtreeMovetoUnpacked()\sroutine\sinto\san\seponymous\sroutine\nand\ssqlite3BtreeMovetoIntkey().\s\sEach\sroutine\sspecializes\sin\sa\ssingle\skind\sof\nbtree.
D 2016-11-10T21:19:35.219
F Makefile.in 6fd48ffcf7c2deea7499062d1f3747f986c19678
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 5151cc64c4c05f3455f4f692ad11410a810d937f
F Makefile.msc e0217f2d35a0448abbe4b066132ae20136e8b408
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
F VERSION 661b3e6a778cfbfd7bdce8bbb1545b22f4b6f09e
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
@@ -202,7 +202,7 @@ F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
F ext/fts5/tool/mkfts5c.tcl d1c2a9ab8e0ec690a52316f33dd9b1d379942f45
F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c
F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
F ext/icu/icu.c 7d371146fff9c21d4f7a806866c578f61b566511
F ext/icu/icu.c 03ff6f90f3004a7e5a86205b581b2b7035ebf6e1
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
F ext/misc/amatch.c 211108e201105e4bb0c076527b8cfd34330fc234
F ext/misc/carray.c 40c27641010a4dc67e3690bdb7c9d36ca58b3c2d
@@ -213,7 +213,7 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
F ext/misc/json1.c 9799e4252b305edcbe659329eec3ca80ed85f968
F ext/misc/json1.c e0797ef1bfa637429ceab9140ecba620809ee02a
F ext/misc/memvfs.c e5225bc22e79dde6b28380f3a068ddf600683a33
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
@@ -330,29 +330,29 @@ F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63
F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
F src/btree.c 6ae1c17347fb2888b2b28a260b947b7717a9fca9
F src/btree.h d05b2fcc290991a8a3d9ea1816ddd55a4359dcde
F src/btree.c 0974c9d93786648343ba7a271c070d8f9a7ba4cd
F src/btree.h f62e4c550e704acb12dc9c4089e05dcd2bc1808b
F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5
F src/build.c 59dcfdc1ee55439d069af301ef7f2e84421b5102
F src/build.c 178f16698cbcb43402c343a9413fe22c99ffee21
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 72c9d01cf446069234e9b54db6fec3e1fc063f58
F src/ctime.c a2a52d6e353f459d8ab0f07321f60fafa47d5421
F src/date.c 95c9a8d00767e7221a8e9a31f4e913fc8029bf6b
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
F src/delete.c cb3f6300df24c26c609778b2731f82644b5532ec
F src/expr.c aac0b8d39373ce8f1d47829ce12c3d7af90c46a6
F src/delete.c 6cac3a6c3f3c5ad4cacc402aee1610fc94ebc3dc
F src/expr.c ddd46bafbbd77b83c8daa733ebbe906093b558dc
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c b9ca262f6ad4d030a3cab737ebf9b0b3c8b4ac80
F src/func.c 29cc9acb170ec1387b9f63eb52cd85f8de96c771
F src/func.c 7057bc2c105b82faa668d8e2ec85fad4540e5c51
F src/global.c 9da4ca5d74b90715f0ec4957f3d17a4749009f34
F src/hash.c 63d0ee752a3b92d4695b2b1f5259c4621b2cfebd
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 2d5e197f2f60351937b201196965fd14cd88489c
F src/insert.c 40c64f0ad405d491127ac13ef450a1b44b076e2f
F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e
F src/loadext.c 5d6642d141c07d366e43d359e94ec9de47add41d
F src/main.c 395bfa7a200943395f7742a40b6671ec400559ea
F src/main.c 694ac90557abdaa62151a6090670e107b0f2c2ab
F src/malloc.c 5ee7c2d3dcb1b0a902c9c6d0115deef54736bdfa
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
@@ -380,24 +380,24 @@ F src/parse.y 0338f906b61e311c2b7e11a3f89b0092c780b664
F src/pcache.c 5ff2a08f76a9c1b22f43eb063b7068fb085465ac
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953
F src/pragma.c 18a2b0aa050396725e8ebb74b055d5afa802b54f
F src/pragma.c d932ba278654617cdd281f88a790a3185fca7c44
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a
F src/printf.c a5f0ca08ddede803c241266abb46356ec748ded1
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c 3fac1b2737ea5a724f20b921ac7e259c9be2100b
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c ea3af83e2d0f245fef81ea4cf04cb730ce67f722
F src/shell.c f0e8b54c58a8a13cc046f5af6d72de7e0a118a2b
F src/sqlite.h.in 7ef021d74ac7d4004c784a16ad015508f171c4bf
F src/select.c 0a7c523d755bcd39ae54f6a44bb66a7f0e1d89b3
F src/shell.c 63e54cfa1c7ec5b70a4c9a86502bc10280c3d5a3
F src/sqlite.h.in 97e9b0f952306677db82b055147ed1d99cb7ba66
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
F src/sqliteInt.h 8d241c2c0a1a7b6611d3e9398f41d69426da850d
F src/sqliteInt.h 37628fe30c464dc790bcee3bfd3d0caa8f222ed1
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
F src/tclsqlite.c aef87dcd8cb66564d560ab48d43d19ac812a1eab
F src/test1.c 1f1a399956c8730d5f7b09c729e98764f2082162
F src/test1.c f52bed152c97be23be794efa234374d0de593eeb
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
F src/test3.c d03f5b5da9a2410b7a91c64b0d3306ed28ab6fee
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
@@ -412,7 +412,7 @@ F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c d23f80d334c59662af69191854c76b8d3d0c8c96
F src/test_blob.c a0f7ad49a0c9d4b72f693fe2a71c58d7e507174d
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
F src/test_config.c 4d3d4a886416f369771d69a6dba926866deda788
F src/test_config.c 371853b4691b482ec0bcdf77ec9e3f96dca75b04
F src/test_delete.c 32690ea215abf29dda589a580cd1b790389759b6
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
F src/test_devsym.c 4e58dec2602d8e139ca08659f62a62450587cb58
@@ -425,7 +425,7 @@ F src/test_intarray.h f3b7672f5d1056eac563c0d6ea8480a660b1475c
F src/test_journal.c d3b83f2bcb7792c709e57abddc456a2b1818643a
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
F src/test_malloc.c c05f6c40bd6c8bfe5f1718212f81fd5687f91766
F src/test_multiplex.c 7c5b218d855cd0505a43185d55283b3fc257c8da
F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e
F src/test_multiplex.h 5436d03f2d0501d04f3ed50a75819e190495b635
F src/test_mutex.c 7f4337ba23ee6b1d2ec81c189653608cb069926a
F src/test_onefile.c 416f87a28d6d673352d33fc4b1c7d39db878e50f
@@ -448,30 +448,30 @@ F src/test_windirent.h 7edc57e2faa727026dbd5d010dd0e2e665d5aa01
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 78c8085bc7af1922aa687f0f4bbd716821330de5
F src/treeview.c f51b75a28b377adde9f79bc3deb6c7770bcf97c0
F src/treeview.c 4e44ade3bfe59d82005039f72e09333ce2b4162c
F src/trigger.c 3419bb9862983d84d70735fb4c94b21b934cd0c5
F src/update.c 8179e699dbd45b92934fd02d3d8e3732e8da8802
F src/update.c bb9854778bdbbbca55d7533e55058733bd3fefe3
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
F src/util.c 3e2da6101888d073e79ecc6af5e0a2f70fa1e498
F src/vacuum.c 913970b9d86dd6c2b8063ef1af421880f1464ec3
F src/vdbe.c c93ae647b3b302234f3593fd686577216aa22543
F src/vacuum.c 33c174b28886b2faf26e503b5a49a1c01a9b1c16
F src/vdbe.c d9e17f9804d6ce20ec2d5b844fc9461713e60596
F src/vdbe.h c044be7050ac6bf596eecc6ab159f5dbc020a3b7
F src/vdbeInt.h d8a56a491b752dbb5f671963b8c861ec72ea875e
F src/vdbeInt.h 29b25318a0286c4b2599c0fbef6acf524398489a
F src/vdbeapi.c 97129bec6b1553da50d8e73f523c278bda66d9f6
F src/vdbeaux.c 52d9b840859f260ce8418be9333dd77c902e1c74
F src/vdbeaux.c ba211189d07b4ecb3209c5b236512e786b499786
F src/vdbeblob.c 3e82a797b60c3b9fed7b8de8c539ca7607874937
F src/vdbemem.c fcdd73a2001a673f48a244a77b1038928ae729c9
F src/vdbesort.c 91fda3909326860382b0ca8aa251e609c6a9d62c
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
F src/vtab.c e02cacb5c7ae742631edeb9ae9f53d399f093fd8
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 0b44e89742024d3b6992bf404d2ab692113e1e60
F src/wal.c 358ab4d296a12bc9dcb6f8974dd155ba8a9b10c4
F src/wal.h bf03a23da3100ab25e5c0363450233cfee09cfc2
F src/walker.c 91a6df7435827e41cff6bb7df50ea00934ee78b0
F src/where.c 5f846d94bb3d35b3146d9915eb301ee362957b0a
F src/where.c 952f76e7a03727480b274b66ca6641b1657cd591
F src/whereInt.h 2bcc3d176e6091cb8f50a30b65c006e88a73614d
F src/wherecode.c 717a65294df46f30e9b9933d2a63a4bcbca5a9a8
F src/whereexpr.c 379d0017fb7bc9e5a4d8cd4b056c747de946430e
F src/wherecode.c 507738d957dcc3cfa93020bcc1e4b02d11ecab9e
F src/whereexpr.c a83d70154f3bbce5051a7e9710021f647c0fe4f2
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -624,7 +624,7 @@ F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
F test/csv01.test e0ba3caaa57e4c667a0b45977689fb8082f14348
F test/ctime.test ff6c38e822459d6ca743c34901caf57740b08b54
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
F test/cursorhint2.test 2b45341d32d1aae9991a00ef31ebca339b274255
F test/cursorhint2.test fa41f0d997e67db921d08c31e73111b32811201a
F test/date.test 984ac1e3e5e031386866f034006148d3972b4a65
F test/dbstatus.test 73149851b3aff14fc6db478e58f9083a66422cf5
F test/dbstatus2.test e93ab03bfae6d62d4d935f20de928c19ca0ed0ab
@@ -862,6 +862,7 @@ F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
F test/insert4.test a20432f1c0fbbcff8f11d0e6ab4acb8c9db58023
F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
F test/instr.test 737bbf80685232033f3abedc6ae92f75860b5dd2
F test/instrfault.test aa90b7c3486a069151b28384ae525644a1f79d51
F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4
F test/interrupt.test dfe9a67a94b0b2d8f70545ba1a6cca10780d71cc
F test/interrupt2.test 829b06f9e20a6c378d8bd121b26c337f4dfa36e5
@@ -885,7 +886,7 @@ F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/json101.test 865776ed8580703e1684fe4b8ee2e473333bb121
F test/json101.test c0897616f32d95431f37fd291cb78742181980ac
F test/json102.test bf3fe7a706d30936a76a0f7a0375e1e8e73aff5a
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
@@ -955,13 +956,14 @@ F test/mmap2.test 9d6dd9ddb4ad2379f29cc78f38ce1e63ed418022
F test/mmap3.test b3c297e78e6a8520aafcc1a8f140535594c9086e
F test/mmap4.test 2e2b4e32555b58da15176e6fe750f17c9dcf7f93
F test/mmapfault.test d4c9eff9cd8c2dc14bc43e71e042f175b0a26fe3
F test/multiplex.test efd015ca0b5b4a57dc9535b8feb1273eebeadb60
F test/multiplex.test dc0d67b66f84b484a83cb8bbdf3f0a7f49562ccd
F test/multiplex2.test 580ca5817c7edbe4cc68fa150609c9473393003a
F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101
F test/multiplex4.test e8ae4c4bd70606a5727743241f13b5701990abe4
F test/mutex1.test ea2cc74d97f077b9e74c84cbd024f14d79a8126f
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test dacc57f80859c06a433d30839336fe227d2038b3
F test/nockpt.test faeeb1daa357d634103fd0a1d54f449e4a5b3ef1
F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
@@ -1025,7 +1027,7 @@ F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test 5b7509f384f4f6fae1af3c8c104c8ca299fea18d
F test/rowvalue.test 753eb744b7efeb5ac643d35d6e1e5066452ccf79
F test/rowvalue.test bcd78c91fe2aadade6fd00d2616546650b9ebc9e
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
F test/rowvalue3.test 01399b7bf150b0d41abce76c18072da777c2500c
F test/rowvalue4.test 4b556d7de161a0dd8cff095c336e913986398bea
@@ -1114,7 +1116,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c ffb96750d02e21d1acdbf63464153580825206d7
F test/speedtest1.c cb433ff792a1b317d0787416bb8a57bbc3266871
F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
@@ -1336,14 +1338,15 @@ F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
F test/update.test 6c68446b8a0a33d522a7c72b320934596a2d7d32
F test/uri.test 6630ecbdea2aac10df3c89dbae2243f4c2c353e4
F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
F test/vacuum2.test aa048abee196c16c9ba308465494009057b79f9b
F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
F test/vacuum5.test 0b7ac80c64eed657b4ce2dd6535092c0d6afec6c
F test/vacuum5.test c87234e8ca4107f349da4edbeda3e4ea5adc93f3
F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
@@ -1373,7 +1376,7 @@ F test/wal2.test 56b0bc95b8693a0be294f8d210c49025dd094bd7
F test/wal3.test 2a93004bc0fb2b5c29888964024695bade278ab2
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
F test/wal5.test 9c11da7aeccd83a46d79a556ad11a18d3cb15aa9
F test/wal6.test 504b24ddb3a75d4b7a6e7c09dc7563622e652fd2
F test/wal6.test b602704e4b066199bc89d91ca9000f335dcf4572
F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8
F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd
F test/wal8.test d9df3fba4caad5854ed69ed673c68482514203c8
@@ -1410,7 +1413,7 @@ F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2
F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
F test/whereD.test 51366b07cb6f546cd30cc803f7e754f063b940de
F test/whereD.test 711d4df58d6d4fb9b3f5ce040b818564198be002
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
F test/whereG.test dde4c52a97385a55be6a7cd46be8373f0cf35501
@@ -1429,7 +1432,7 @@ F test/with1.test cef099a491eac9874f2c28bd2dc86394fb3e47b3
F test/with2.test 2b40da883658eb74ad8ad06afabe11a408e7fb87
F test/with3.test 511bacdbe41c49cf34f9fd1bd3245fe1575bca98
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
F test/without_rowid1.test eaac24556ed2dfaf84d8a32fac46229bd61b1015
F test/without_rowid1.test 1a7b9bd51b899928d327052df9741d2fe8dbe701
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
F test/without_rowid3.test aad4f9d383e199349b6c7e508a778f7dff5dff79
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
@@ -1442,7 +1445,7 @@ F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
F tool/GetTclKit.bat f94784e3bdc2f50c539266f5467cbf1f27612cb3
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
F tool/addopcodes.tcl 10c889c4a65ec6c5604e4a47306fa77ff57ae189
F tool/build-all-msvc.bat 3e4e4043b53f1aede4308e0d2567bbd773614630 x
F tool/build-all-msvc.bat 018c1b273458a90c8ba633c6f0c5654cfcb138bf x
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
F tool/cg_anno.tcl 692ce4b8693d59e3a3de77ca97f4139ecfa641b0 x
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
@@ -1471,7 +1474,7 @@ F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
F tool/mksqlite3c.tcl 06b2e6a0f21cc0a5d70fbbd136b3e0a96470645e
F tool/mksqlite3h.tcl c006c4e5da57c649b24b689511dcd270dd7b0249
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
F tool/mkvsix.tcl 4abcaf3267171b2faadaf9b82a0dfbaa6e98f8b7
F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97
F tool/opcodesum.tcl 740ed206ba8c5040018988129abbf3089a0ccf4a
@@ -1527,10 +1530,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P b115856408b6aa5538be67beb619d7aff0630bea
R 169c1df42ad3211c7cffa140b51fc0ef
T *branch * index-info-on-table
T *sym-index-info-on-table *
T -sym-trunk *
P eac0e827a61cfec4dd9b6d407ff398e9fda3510b
R ba7bc1acb04a8d9f868e5f35605c70ca
T *branch * split-moveto
T *sym-split-moveto *
T -sym-unpacked-IdxInsert *
U drh
Z c67713b53054dcc5980cf7c3020b1123
Z 427f2c7c546b65337746f9a6ce50edb5
+1 -1
View File
@@ -1 +1 @@
fe49fb03133fec8bed51c2e2c1b6848ab9fc563e
9a64a4f2353576ba742c2ddbf4264d00704066a1
+234 -165
View File
@@ -777,12 +777,10 @@ static int btreeMoveto(
sqlite3DbFree(pCur->pKeyInfo->db, pFree);
return SQLITE_CORRUPT_BKPT;
}
rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, bias, pRes);
if( pFree ) sqlite3DbFree(pCur->pKeyInfo->db, pFree);
}else{
pIdxKey = 0;
}
rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
if( pFree ){
sqlite3DbFree(pCur->pKeyInfo->db, pFree);
rc = sqlite3BtreeMovetoIntkey(pCur, nKey, bias, pRes);
}
return rc;
}
@@ -5075,7 +5073,6 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
int sqlite3BtreeMovetoUnpacked(
BtCursor *pCur, /* The cursor to be moved */
UnpackedRecord *pIdxKey, /* Unpacked index key */
i64 intKey, /* The table key */
int biasRight, /* If true, bias the search to the high end */
int *pRes /* Write search results here */
){
@@ -5085,35 +5082,15 @@ int sqlite3BtreeMovetoUnpacked(
assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( pRes );
assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
assert( pCur->eState!=CURSOR_VALID || (pIdxKey==0)==(pCur->curIntKey!=0) );
/* If the cursor is already positioned at the point we are trying
** to move to, then just return without doing any work */
if( pIdxKey==0
&& pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0
){
if( pCur->info.nKey==intKey ){
*pRes = 0;
return SQLITE_OK;
}
if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKey<intKey ){
*pRes = -1;
return SQLITE_OK;
}
}
if( pIdxKey ){
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
pIdxKey->errCode = 0;
assert( pIdxKey->default_rc==1
|| pIdxKey->default_rc==0
|| pIdxKey->default_rc==-1
);
}else{
xRecordCompare = 0; /* All keys are integers */
}
assert( pIdxKey );
assert( pCur->curIntKey==0 || pCur->eState!=CURSOR_VALID );
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
pIdxKey->errCode = 0;
assert( pIdxKey->default_rc==1
|| pIdxKey->default_rc==0
|| pIdxKey->default_rc==-1
);
rc = moveToRoot(pCur);
if( rc ){
return rc;
@@ -5126,8 +5103,8 @@ int sqlite3BtreeMovetoUnpacked(
assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
return SQLITE_OK;
}
assert( pCur->apPage[0]->intKey==pCur->curIntKey );
assert( pCur->curIntKey || pIdxKey );
assert( !pCur->apPage[0]->intKey );
assert( !pCur->curIntKey );
for(;;){
int lwr, upr, idx, c;
Pgno chldPg;
@@ -5147,124 +5124,89 @@ int sqlite3BtreeMovetoUnpacked(
assert( biasRight==0 || biasRight==1 );
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
pCur->aiIdx[pCur->iPage] = (u16)idx;
if( xRecordCompare==0 ){
for(;;){
i64 nCellKey;
pCell = findCellPastPtr(pPage, idx);
if( pPage->intKeyLeaf ){
while( 0x80 <= *(pCell++) ){
if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
}
}
getVarint(pCell, (u64*)&nCellKey);
if( nCellKey<intKey ){
lwr = idx+1;
if( lwr>upr ){ c = -1; break; }
}else if( nCellKey>intKey ){
upr = idx-1;
if( lwr>upr ){ c = +1; break; }
}else{
assert( nCellKey==intKey );
pCur->curFlags |= BTCF_ValidNKey;
pCur->info.nKey = nCellKey;
pCur->aiIdx[pCur->iPage] = (u16)idx;
if( !pPage->leaf ){
lwr = idx;
goto moveto_next_layer;
}else{
*pRes = 0;
rc = SQLITE_OK;
goto moveto_finish;
}
}
assert( lwr+upr>=0 );
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */
}
}else{
for(;;){
int nCell; /* Size of the pCell cell in bytes */
pCell = findCellPastPtr(pPage, idx);
for(;;){
int nCell; /* Size of the pCell cell in bytes */
pCell = findCellPastPtr(pPage, idx);
/* The maximum supported page-size is 65536 bytes. This means that
** the maximum number of record bytes stored on an index B-Tree
** page is less than 16384 bytes and may be stored as a 2-byte
** varint. This information is used to attempt to avoid parsing
** the entire cell by checking for the cases where the record is
** stored entirely within the b-tree page by inspecting the first
** 2 bytes of the cell.
*/
nCell = pCell[0];
if( nCell<=pPage->max1bytePayload ){
/* This branch runs if the record-size field of the cell is a
** single byte varint and the record fits entirely on the main
** b-tree page. */
testcase( pCell+nCell+1==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
}else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
){
/* The record-size field is a 2 byte varint and the record
** fits entirely on the main b-tree page. */
testcase( pCell+nCell+2==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
}else{
/* The record flows over onto one or more overflow pages. In
** this case the whole cell needs to be parsed, a buffer allocated
** and accessPayload() used to retrieve the record into the
** buffer before VdbeRecordCompare() can be called.
**
** If the record is corrupt, the xRecordCompare routine may read
** up to two varints past the end of the buffer. An extra 18
** bytes of padding is allocated at the end of the buffer in
** case this happens. */
void *pCellKey;
u8 * const pCellBody = pCell - pPage->childPtrSize;
pPage->xParseCell(pPage, pCellBody, &pCur->info);
nCell = (int)pCur->info.nKey;
testcase( nCell<0 ); /* True if key size is 2^32 or more */
testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
testcase( nCell==2 ); /* Minimum legal index key size */
if( nCell<2 ){
rc = SQLITE_CORRUPT_BKPT;
goto moveto_finish;
}
pCellKey = sqlite3Malloc( nCell+18 );
if( pCellKey==0 ){
rc = SQLITE_NOMEM_BKPT;
goto moveto_finish;
}
pCur->aiIdx[pCur->iPage] = (u16)idx;
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
if( rc ){
sqlite3_free(pCellKey);
goto moveto_finish;
}
c = xRecordCompare(nCell, pCellKey, pIdxKey);
sqlite3_free(pCellKey);
}
assert(
(pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
&& (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
);
if( c<0 ){
lwr = idx+1;
}else if( c>0 ){
upr = idx-1;
}else{
assert( c==0 );
*pRes = 0;
rc = SQLITE_OK;
pCur->aiIdx[pCur->iPage] = (u16)idx;
if( pIdxKey->errCode ) rc = SQLITE_CORRUPT;
/* The maximum supported page-size is 65536 bytes. This means that
** the maximum number of record bytes stored on an index B-Tree
** page is less than 16384 bytes and may be stored as a 2-byte
** varint. This information is used to attempt to avoid parsing
** the entire cell by checking for the cases where the record is
** stored entirely within the b-tree page by inspecting the first
** 2 bytes of the cell.
*/
nCell = pCell[0];
if( nCell<=pPage->max1bytePayload ){
/* This branch runs if the record-size field of the cell is a
** single byte varint and the record fits entirely on the main
** b-tree page. */
testcase( pCell+nCell+1==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
}else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
){
/* The record-size field is a 2 byte varint and the record
** fits entirely on the main b-tree page. */
testcase( pCell+nCell+2==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
}else{
/* The record flows over onto one or more overflow pages. In
** this case the whole cell needs to be parsed, a buffer allocated
** and accessPayload() used to retrieve the record into the
** buffer before VdbeRecordCompare() can be called.
**
** If the record is corrupt, the xRecordCompare routine may read
** up to two varints past the end of the buffer. An extra 18
** bytes of padding is allocated at the end of the buffer in
** case this happens. */
void *pCellKey;
u8 * const pCellBody = pCell - pPage->childPtrSize;
pPage->xParseCell(pPage, pCellBody, &pCur->info);
nCell = (int)pCur->info.nKey;
testcase( nCell<0 ); /* True if key size is 2^32 or more */
testcase( nCell==0 ); /* Invalid key size: 0x80 0x80 0x00 */
testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
testcase( nCell==2 ); /* Minimum legal index key size */
if( nCell<2 ){
rc = SQLITE_CORRUPT_BKPT;
goto moveto_finish;
}
if( lwr>upr ) break;
assert( lwr+upr>=0 );
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
pCellKey = sqlite3Malloc( nCell+18 );
if( pCellKey==0 ){
rc = SQLITE_NOMEM_BKPT;
goto moveto_finish;
}
pCur->aiIdx[pCur->iPage] = (u16)idx;
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
if( rc ){
sqlite3_free(pCellKey);
goto moveto_finish;
}
c = xRecordCompare(nCell, pCellKey, pIdxKey);
sqlite3_free(pCellKey);
}
assert(
(pIdxKey->errCode!=SQLITE_CORRUPT || c==0)
&& (pIdxKey->errCode!=SQLITE_NOMEM || pCur->pBtree->db->mallocFailed)
);
if( c<0 ){
lwr = idx+1;
}else if( c>0 ){
upr = idx-1;
}else{
assert( c==0 );
*pRes = 0;
rc = SQLITE_OK;
pCur->aiIdx[pCur->iPage] = (u16)idx;
if( pIdxKey->errCode ) rc = SQLITE_CORRUPT;
goto moveto_finish;
}
if( lwr>upr ) break;
assert( lwr+upr>=0 );
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2 */
}
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
assert( lwr==upr+1 );
assert( pPage->isInit );
if( pPage->leaf ){
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
@@ -5273,7 +5215,6 @@ int sqlite3BtreeMovetoUnpacked(
rc = SQLITE_OK;
goto moveto_finish;
}
moveto_next_layer:
if( lwr>=pPage->nCell ){
chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
}else{
@@ -5288,6 +5229,121 @@ moveto_finish:
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
return rc;
}
int sqlite3BtreeMovetoIntkey(
BtCursor *pCur, /* The cursor to be moved */
i64 intKey, /* The table key */
int biasRight, /* If true, bias the search to the high end */
int *pRes /* Write search results here */
){
int rc;
assert( cursorOwnsBtShared(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( pRes );
assert( pCur->pKeyInfo==0 );
assert( pCur->curIntKey || pCur->eState!=CURSOR_VALID );
/* If the cursor is already positioned at the point we are trying
** to move to, then just return without doing any work */
if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0 ){
if( pCur->info.nKey==intKey ){
*pRes = 0;
return SQLITE_OK;
}
if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKey<intKey ){
*pRes = -1;
return SQLITE_OK;
}
}
rc = moveToRoot(pCur);
if( rc ){
return rc;
}
assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] );
assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit );
assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 );
if( pCur->eState==CURSOR_INVALID ){
*pRes = -1;
assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
return SQLITE_OK;
}
assert( pCur->apPage[0]->intKey );
assert( pCur->curIntKey );
for(;;){
int lwr, upr, idx, c;
Pgno chldPg;
MemPage *pPage = pCur->apPage[pCur->iPage];
u8 *pCell; /* Pointer to current cell in pPage */
/* pPage->nCell must be greater than zero. If this is the root-page
** the cursor would have been INVALID above and this for(;;) loop
** not run. If this is not the root-page, then the moveToChild() routine
** would have already detected db corruption. Similarly, pPage must
** be the right kind (index or table) of b-tree page. Otherwise
** a moveToChild() or moveToRoot() call would have detected corruption. */
assert( pPage->nCell>0 );
assert( pPage->intKey );
lwr = 0;
upr = pPage->nCell-1;
assert( biasRight==0 || biasRight==1 );
idx = upr>>(1-biasRight); /* idx = biasRight ? upr : (lwr+upr)/2; */
pCur->aiIdx[pCur->iPage] = (u16)idx;
for(;;){
i64 nCellKey;
pCell = findCellPastPtr(pPage, idx);
if( pPage->intKeyLeaf ){
while( 0x80 <= *(pCell++) ){
if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
}
}
getVarint(pCell, (u64*)&nCellKey);
if( nCellKey<intKey ){
lwr = idx+1;
if( lwr>upr ){ c = -1; break; }
}else if( nCellKey>intKey ){
upr = idx-1;
if( lwr>upr ){ c = +1; break; }
}else{
assert( nCellKey==intKey );
pCur->curFlags |= BTCF_ValidNKey;
pCur->info.nKey = nCellKey;
pCur->aiIdx[pCur->iPage] = (u16)idx;
if( !pPage->leaf ){
lwr = idx;
goto intkey_moveto_next_layer;
}else{
*pRes = 0;
rc = SQLITE_OK;
goto intkey_moveto_finish;
}
}
assert( lwr+upr>=0 );
idx = (lwr+upr)>>1; /* idx = (lwr+upr)/2; */
}
assert( lwr==upr+1 || !pPage->leaf );
assert( pPage->isInit );
if( pPage->leaf ){
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
pCur->aiIdx[pCur->iPage] = (u16)idx;
*pRes = c;
rc = SQLITE_OK;
goto intkey_moveto_finish;
}
intkey_moveto_next_layer:
if( lwr>=pPage->nCell ){
chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]);
}else{
chldPg = get4byte(findCell(pPage, lwr));
}
pCur->aiIdx[pCur->iPage] = (u16)lwr;
rc = moveToChild(pCur, chldPg);
if( rc ) break;
}
intkey_moveto_finish:
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
return rc;
}
/*
@@ -7940,17 +7996,19 @@ static int balance(BtCursor *pCur){
** pX.pData,nData,nZero fields must be zero.
**
** If the seekResult parameter is non-zero, then a successful call to
** MovetoUnpacked() to seek cursor pCur to (pKey, nKey) has already
** been performed. seekResult is the search result returned (a negative
** number if pCur points at an entry that is smaller than (pKey, nKey), or
** a positive value if pCur points at an entry that is larger than
** (pKey, nKey)).
** MovetoUnpacked() to seek cursor pCur to (pKey,nKey) has already
** been performed. In other words, if seekResult!=0 then the cursor
** is currently pointing to a cell that will be adjacent to the cell
** to be inserted. If seekResult<0 then pCur points to a cell that is
** smaller then (pKey,nKey). If seekResult>0 then pCur points to a cell
** that is larger than (pKey,nKey).
**
** If the seekResult parameter is non-zero, then the caller guarantees that
** cursor pCur is pointing at the existing copy of a row that is to be
** overwritten. If the seekResult parameter is 0, then cursor pCur may
** point to any entry or to no entry at all and so this function has to seek
** the cursor before the new key can be inserted.
** If seekResult==0, that means pCur is pointing at some unknown location.
** In that case, this routine must seek the cursor to the correct insertion
** point for (pKey,nKey) before doing the insertion. For index btrees,
** if pX->nMem is non-zero, then pX->aMem contains pointers to the unpacked
** key values and pX->aMem can be used instead of pX->pKey to avoid having
** to decode the key.
*/
int sqlite3BtreeInsert(
BtCursor *pCur, /* Insert data into the table of this cursor */
@@ -8011,15 +8069,26 @@ int sqlite3BtreeInsert(
/* If the cursor is currently on the last row and we are appending a
** new row onto the end, set the "loc" to avoid an unnecessary
** btreeMoveto() call */
if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey>0
&& pCur->info.nKey==pX->nKey-1 ){
loc = -1;
if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){
loc = 0;
}else if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey>0
&& pCur->info.nKey==pX->nKey-1 ){
loc = -1;
}else if( loc==0 ){
rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, appendBias, &loc);
rc = sqlite3BtreeMovetoIntkey(pCur, pX->nKey, appendBias, &loc);
if( rc ) return rc;
}
}else if( loc==0 ){
rc = btreeMoveto(pCur, pX->pKey, pX->nKey, appendBias, &loc);
if( pX->nMem ){
UnpackedRecord r;
memset(&r, 0, sizeof(r));
r.pKeyInfo = pCur->pKeyInfo;
r.aMem = pX->aMem;
r.nField = pX->nMem;
rc = sqlite3BtreeMovetoUnpacked(pCur, &r, appendBias, &loc);
}else{
rc = btreeMoveto(pCur, pX->pKey, pX->nKey, appendBias, &loc);
}
if( rc ) return rc;
}
assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
+7
View File
@@ -241,6 +241,11 @@ int sqlite3BtreeCloseCursor(BtCursor*);
int sqlite3BtreeMovetoUnpacked(
BtCursor*,
UnpackedRecord *pUnKey,
int bias,
int *pRes
);
int sqlite3BtreeMovetoIntkey(
BtCursor*,
i64 intKey,
int bias,
int *pRes
@@ -275,6 +280,8 @@ struct BtreePayload {
const void *pKey; /* Key content for indexes. NULL for tables */
sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */
const void *pData; /* Data for tables. NULL for indexes */
struct Mem *aMem; /* First of nMem value in the unpacked pKey */
u16 nMem; /* Number of aMem[] value. Might be zero */
int nData; /* Size of pData. 0 if none. */
int nZero; /* Extra zero data appended after pData,nData */
};
+3 -1
View File
@@ -59,6 +59,8 @@ void sqlite3TableLock(
TableLock *p;
assert( iDb>=0 );
if( iDb==1 ) return;
if( !sqlite3BtreeSharable(pParse->db->aDb[iDb].pBt) ) return;
for(i=0; i<pToplevel->nTableLock; i++){
p = &pToplevel->aTableLock[i];
if( p->iDb==iDb && p->iTab==iTab ){
@@ -2816,7 +2818,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
}
sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1);
sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v);
+3
View File
@@ -155,6 +155,9 @@ static const char * const azCompileOpt[] = {
#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
"ENABLE_UPDATE_DELETE_LIMIT",
#endif
#if defined(SQLITE_ENABLE_URI_00_ERROR)
"ENABLE_URI_00_ERROR",
#endif
#if SQLITE_HAS_CODEC
"HAS_CODEC",
#endif
+1 -1
View File
@@ -449,7 +449,7 @@ void sqlite3DeleteFrom(
nKey = 0; /* Zero tells OP_Found to use a composite key */
sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, iKey,
sqlite3IndexAffinityStr(pParse->db, pPk), nPk);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iEphCur, iKey);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk);
}else{
/* Add the rowid of the row to be deleted to the RowSet */
nKey = 1; /* OP_Seek always uses a single rowid */
+5 -6
View File
@@ -2538,7 +2538,7 @@ int sqlite3CodeSubselect(
}else{
sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
sqlite3ExprCacheAffinityChange(pParse, r3, 1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pExpr->iTable, r2, r3, 1);
}
}
}
@@ -4600,11 +4600,10 @@ int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){
){
return 1;
}
if( pE2->op==TK_NOTNULL
&& sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0
&& (pE1->op!=TK_ISNULL && pE1->op!=TK_IS)
){
return 1;
if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){
Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft);
testcase( pX!=pE1->pLeft );
if( sqlite3ExprCompare(pX, pE2->pLeft, iTab)==0 ) return 1;
}
return 0;
}
+2
View File
@@ -208,6 +208,8 @@ static void instrFunc(
zHaystack = sqlite3_value_text(argv[0]);
zNeedle = sqlite3_value_text(argv[1]);
isText = 1;
if( zNeedle==0 ) return;
assert( zHaystack );
}
while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
N++;
+32 -9
View File
@@ -786,14 +786,17 @@ void sqlite3Insert(
/* If this is not a view, open the table and and all indices */
if( !isView ){
int nIdx;
Index *pIdx;
nIdx = sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, -1, 0,
&iDataCur, &iIdxCur);
aRegIdx = sqlite3DbMallocRawNN(db, sizeof(int)*(nIdx+1));
if( aRegIdx==0 ){
goto insert_cleanup;
}
for(i=0; i<nIdx; i++){
for(i=0, pIdx=pTab->pIndex; i<nIdx; pIdx=pIdx->pNext, i++){
assert( pIdx );
aRegIdx[i] = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
}
}
@@ -995,12 +998,26 @@ void sqlite3Insert(
#endif
{
int isReplace; /* Set to true if constraints may cause a replace */
int bUseSeek; /* True to use OPFLAG_SEEKRESULT */
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0
);
sqlite3FkCheck(pParse, pTab, 0, regIns, 0, 0);
/* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE
** constraints or (b) there are no triggers and this table is not a
** parent table in a foreign key constraint. It is safe to set the
** flag in the second case as if any REPLACE constraint is hit, an
** OP_Delete or OP_IdxDelete instruction will be executed on each
** cursor that is disturbed. And these instructions both clear the
** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT
** functionality. */
bUseSeek = (isReplace==0 || (pTrigger==0 &&
((db->flags & SQLITE_ForeignKeys)==0 || sqlite3FkReferences(pTab)==0)
));
sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
regIns, aRegIdx, 0, appendFlag, isReplace==0);
regIns, aRegIdx, 0, appendFlag, bUseSeek
);
}
}
@@ -1363,7 +1380,7 @@ void sqlite3GenerateConstraintChecks(
}
if( isUpdate ){
/* pkChng!=0 does not mean that the rowid has change, only that
/* pkChng!=0 does not mean that the rowid has changed, only that
** it might have changed. Skip the conflict logic below if the rowid
** is unchanged. */
sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData);
@@ -1498,7 +1515,7 @@ void sqlite3GenerateConstraintChecks(
/* Create a record for this index entry as it should appear after
** the insert or update. Store that record in the aRegIdx[ix] register
*/
regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn);
regIdx = aRegIdx[ix]+1;
for(i=0; i<pIdx->nColumn; i++){
int iField = pIdx->aiColumn[i];
int x;
@@ -1535,7 +1552,6 @@ void sqlite3GenerateConstraintChecks(
/* Find out what action to take in case there is a uniqueness conflict */
onError = pIdx->onError;
if( onError==OE_None ){
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
sqlite3VdbeResolveLabel(v, addrUniqueOk);
continue; /* pIdx is not a UNIQUE index */
}
@@ -1544,6 +1560,12 @@ void sqlite3GenerateConstraintChecks(
}else if( onError==OE_Default ){
onError = OE_Abort;
}
if( ix==0 && pPk==pIdx && onError==OE_Replace && pPk->pNext==0 ){
sqlite3VdbeResolveLabel(v, addrUniqueOk);
continue;
}
/* Check to see if the new index entry will be unique */
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
@@ -1634,7 +1656,6 @@ void sqlite3GenerateConstraintChecks(
}
}
sqlite3VdbeResolveLabel(v, addrUniqueOk);
sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn);
if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
}
if( ipkTop ){
@@ -1684,7 +1705,9 @@ void sqlite3CompleteInsertion(
sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
VdbeCoverage(v);
}
sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i],
aRegIdx[i]+1,
pIdx->uniqNotNull ? pIdx->nKeyCol: pIdx->nColumn);
pik_flags = 0;
if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT;
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
@@ -2166,8 +2189,8 @@ static int xferOptimization(
if( !HasRowid(pSrc) && pDestIdx->idxType==2 ){
idxInsFlags |= OPFLAG_NCHANGE;
}
sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
sqlite3VdbeChangeP5(v, idxInsFlags);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
+8
View File
@@ -810,6 +810,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
{ SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger },
{ SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer },
{ SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension },
{ SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose },
};
unsigned int i;
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
@@ -2615,6 +2616,7 @@ int sqlite3ParseUri(
assert( octet>=0 && octet<256 );
if( octet==0 ){
#ifndef SQLITE_ENABLE_URI_00_ERROR
/* This branch is taken when "%00" appears within the URI. In this
** case we ignore all text in the remainder of the path, name or
** value currently being parsed. So ignore the current character
@@ -2627,6 +2629,12 @@ int sqlite3ParseUri(
iIn++;
}
continue;
#else
/* If ENABLE_URI_00_ERROR is defined, "%00" in a URI is an error. */
*pzErrMsg = sqlite3_mprintf("unexpected %%00 in uri");
rc = SQLITE_ERROR;
goto parse_uri_out;
#endif
}
c = octet;
}else if( eState==1 && (c=='&' || c=='=') ){
-4
View File
@@ -1122,10 +1122,6 @@ void sqlite3Pragma(
Index *pIdx;
Table *pTab;
pIdx = sqlite3FindIndex(db, zRight, zDb);
if( pIdx==0 ){
pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab && !HasRowid(pTab) ) pIdx = sqlite3PrimaryKeyIndex(pTab);
}
if( pIdx ){
static const char *azCol[] = {
"seqno", "cid", "name", "desc", "coll", "key"
+10 -8
View File
@@ -587,7 +587,8 @@ static void pushOntoSorter(
}else{
op = OP_IdxInsert;
}
sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord,
regBase+nOBSat, nBase-nOBSat);
if( iLimit ){
int addr;
int r1 = 0;
@@ -655,7 +656,7 @@ static void codeDistinct(
r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N);
sqlite3ReleaseTempReg(pParse, r1);
}
@@ -808,7 +809,7 @@ static void selectInnerLoop(
int r1;
r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
sqlite3ReleaseTempReg(pParse, r1);
break;
}
@@ -845,7 +846,7 @@ static void selectInnerLoop(
int addr = sqlite3VdbeCurrentAddr(v) + 4;
sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0);
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,regResult,nResultCol);
assert( pSort==0 );
}
#endif
@@ -881,7 +882,7 @@ static void selectInnerLoop(
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
r1, pDest->zAffSdst, nResultCol);
sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
sqlite3ReleaseTempReg(pParse, r1);
}
break;
@@ -967,7 +968,7 @@ static void selectInnerLoop(
}
sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey);
sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2);
if( addrTest ) sqlite3VdbeJumpHere(v, addrTest);
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempRange(pParse, r2, nKey+2);
@@ -1264,7 +1265,7 @@ static void generateSortTail(
sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid,
pDest->zAffSdst, nColumn);
sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn);
break;
}
case SRT_Mem: {
@@ -2640,7 +2641,8 @@ static int generateOutputSubroutine(
sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst,
r1, pDest->zAffSdst, pIn->nSdst);
sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst);
sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
pIn->iSdst, pIn->nSdst);
sqlite3ReleaseTempReg(pParse, r1);
break;
}
+87 -1
View File
@@ -1202,7 +1202,6 @@ static int shell_callback(
}
case MODE_Quote:
case MODE_Insert: {
p->cnt++;
if( azArg==0 ) break;
if( p->cMode==MODE_Insert ){
utf8_printf(p->out,"INSERT INTO %s",p->zDestTable);
@@ -1215,7 +1214,14 @@ static int shell_callback(
raw_printf(p->out,")");
}
raw_printf(p->out," VALUES(");
}else if( p->cnt==0 && p->showHeader ){
for(i=0; i<nArg; i++){
if( i>0 ) utf8_printf(p->out, ",");
output_quoted_string(p->out, azCol[i]);
}
utf8_printf(p->out,"\n");
}
p->cnt++;
for(i=0; i<nArg; i++){
char *zSep = i>0 ? ",": "";
if( (azArg[i]==0) || (aiType && aiType[i]==SQLITE_NULL) ){
@@ -1901,6 +1907,7 @@ static int shell_exec(
continue;
}
zStmtSql = sqlite3_sql(pStmt);
if( zStmtSql==0 ) zStmtSql = "";
while( IsSpace(zStmtSql[0]) ) zStmtSql++;
/* save off the prepared statment handle and reset row count */
@@ -2163,6 +2170,9 @@ static char zHelp[] =
".headers on|off Turn display of headers on or off\n"
".help Show this message\n"
".import FILE TABLE Import data from FILE into TABLE\n"
#ifndef SQLITE_OMIT_TEST_CONTROL
".imposter INDEX TABLE Create imposter table TABLE on index INDEX\n"
#endif
".indexes ?TABLE? Show names of all indexes\n"
" If TABLE specified, only show indexes for tables\n"
" matching LIKE pattern TABLE.\n"
@@ -3845,6 +3855,79 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
#ifndef SQLITE_OMIT_BUILTIN_TEST
if( c=='i' && strncmp(azArg[0], "imposter", n)==0 ){
char *zSql;
char *zCollist = 0;
sqlite3_stmt *pStmt;
int tnum = 0;
int i;
if( nArg!=3 ){
utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n");
rc = 1;
goto meta_command_exit;
}
open_db(p, 0);
zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master"
" WHERE name='%q' AND type='index'", azArg[1]);
sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
if( sqlite3_step(pStmt)==SQLITE_ROW ){
tnum = sqlite3_column_int(pStmt, 0);
}
sqlite3_finalize(pStmt);
if( tnum==0 ){
utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
rc = 1;
goto meta_command_exit;
}
zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
i = 0;
while( sqlite3_step(pStmt)==SQLITE_ROW ){
char zLabel[20];
const char *zCol = (const char*)sqlite3_column_text(pStmt,2);
i++;
if( zCol==0 ){
if( sqlite3_column_int(pStmt,1)==-1 ){
zCol = "_ROWID_";
}else{
sqlite3_snprintf(sizeof(zLabel),zLabel,"expr%d",i);
zCol = zLabel;
}
}
if( zCollist==0 ){
zCollist = sqlite3_mprintf("\"%w\"", zCol);
}else{
zCollist = sqlite3_mprintf("%z,\"%w\"", zCollist, zCol);
}
}
sqlite3_finalize(pStmt);
zSql = sqlite3_mprintf(
"CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID",
azArg[2], zCollist, zCollist);
sqlite3_free(zCollist);
rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
if( rc==SQLITE_OK ){
rc = sqlite3_exec(p->db, zSql, 0, 0, 0);
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 0);
if( rc ){
utf8_printf(stderr, "Error in [%s]: %s\n", zSql, sqlite3_errmsg(p->db));
}else{
utf8_printf(stdout, "%s;\n", zSql);
utf8_printf(stdout,
"WARNING: writing to an imposter table will corrupt the index!\n"
);
}
}else{
utf8_printf(stderr, "SQLITE_TESTCTRL_IMPOSTER returns %d\n", rc);
rc = 1;
}
sqlite3_free(zSql);
}else
#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
#ifdef SQLITE_ENABLE_IOTRACE
if( c=='i' && strncmp(azArg[0], "iotrace", n)==0 ){
SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
@@ -3867,6 +3950,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
#endif
if( c=='l' && n>=5 && strncmp(azArg[0], "limits", n)==0 ){
static const struct {
const char *zLimitName; /* Name of a limit */
@@ -4707,6 +4791,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
#ifndef SQLITE_OMIT_BUILTIN_TEST
if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){
static const struct {
const char *zCtrlName; /* Name of a test-control option */
@@ -4882,6 +4967,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
#endif
}else
#endif /* !defined(SQLITE_OMIT_BUILTIN_TEST) */
#if SQLITE_USER_AUTHENTICATION
if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
+13
View File
@@ -1988,6 +1988,18 @@ struct sqlite3_mem_methods {
** until after the database connection closes.
** </dd>
**
** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
** <dd> Usually, when a database in wal mode is closed or detached from a
** database handle, SQLite checks if this will mean that there are now no
** connections at all to the database. If so, it performs a checkpoint
** operation before closing the connection. This option may be used to
** override this behaviour. The first parameter passed to this operation
** is an integer - non-zero to disable checkpoints-on-close, or zero (the
** default) to enable them. The second parameter is a pointer to an integer
** into which is written 0 or 1 to indicate whether checkpoints-on-close
** have been disabled - 0 if they are not disabled, 1 if they are.
** </dd>
**
** </dl>
*/
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
@@ -1996,6 +2008,7 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
/*
+1
View File
@@ -1435,6 +1435,7 @@ struct sqlite3 {
#define SQLITE_Vacuum 0x10000000 /* Currently in a VACUUM */
#define SQLITE_CellSizeCk 0x20000000 /* Check btree cell sizes on load */
#define SQLITE_Fts3Tokenizer 0x40000000 /* Enable fts3_tokenizer(2) */
#define SQLITE_NoCkptOnClose 0x80000000 /* No checkpoint on close()/DETACH */
/*
+1
View File
@@ -7221,6 +7221,7 @@ static int SQLITE_TCLAPI test_sqlite3_db_config(
{ "TRIGGER", SQLITE_DBCONFIG_ENABLE_TRIGGER },
{ "FTS3_TOKENIZER", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
{ "LOAD_EXTENSION", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
{ "NO_CKPT_ON_CLOSE",SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
};
int i;
int v;
+6
View File
@@ -714,6 +714,12 @@ Tcl_SetVar2(interp, "sqlite_options", "mergesort", "1", TCL_GLOBAL_ONLY);
Tcl_SetVar2(interp, "sqlite_options", "sqllog", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_ENABLE_URI_00_ERROR
Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "1", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "uri_00_error", "0", TCL_GLOBAL_ONLY);
#endif
#define LINKVAR(x) { \
static const int cv_ ## x = SQLITE_ ## x; \
Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \
-122
View File
@@ -68,19 +68,6 @@
#define MAX_PAGE_SIZE 0x10000
#define DEFAULT_SECTOR_SIZE 0x1000
/*
** For a build without mutexes, no-op the mutex calls.
*/
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8)
#define sqlite3_mutex_free(X)
#define sqlite3_mutex_enter(X)
#define sqlite3_mutex_try(X) SQLITE_OK
#define sqlite3_mutex_leave(X)
#define sqlite3_mutex_held(X) ((void)(X),1)
#define sqlite3_mutex_notheld(X) ((void)(X),1)
#endif /* SQLITE_THREADSAFE==0 */
/* Maximum chunk number */
#define MX_CHUNK_NUMBER 299
@@ -139,7 +126,6 @@ struct multiplexGroup {
unsigned int szChunk; /* Chunk size used for this group */
unsigned char bEnabled; /* TRUE to use Multiplex VFS for this file */
unsigned char bTruncate; /* TRUE to enable truncation of databases */
multiplexGroup *pNext, *pPrev; /* Doubly linked list of all group objects */
};
/*
@@ -187,28 +173,9 @@ static struct {
/* True when this shim has been initialized.
*/
int isInitialized;
/* For run-time access any of the other global data structures in this
** shim, the following mutex must be held. In practice, all this mutex
** protects is add/remove operations to/from the linked list of group objects
** starting at pGroups below. More specifically, it protects the value of
** pGroups itself, and the pNext/pPrev fields of each multiplexGroup
** structure. */
sqlite3_mutex *pMutex;
/* List of multiplexGroup objects.
*/
multiplexGroup *pGroups;
} gMultiplex;
/************************* Utility Routines *********************************/
/*
** Acquire and release the mutex used to serialize access to the
** list of multiplexGroups.
*/
static void multiplexEnter(void){ sqlite3_mutex_enter(gMultiplex.pMutex); }
static void multiplexLeave(void){ sqlite3_mutex_leave(gMultiplex.pMutex); }
/*
** Compute a string length that is limited to what can be stored in
** lower 30 bits of a 32-bit signed integer.
@@ -519,7 +486,6 @@ static int multiplexOpen(
/* We need to create a group structure and manage
** access to this group of files.
*/
multiplexEnter();
pMultiplexOpen = (multiplexConn*)pConn;
if( rc==SQLITE_OK ){
@@ -626,16 +592,11 @@ static int multiplexOpen(
}else{
pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV2;
}
/* place this group at the head of our list */
pGroup->pNext = gMultiplex.pGroups;
if( gMultiplex.pGroups ) gMultiplex.pGroups->pPrev = pGroup;
gMultiplex.pGroups = pGroup;
}else{
multiplexFreeComponents(pGroup);
sqlite3_free(pGroup);
}
}
multiplexLeave();
sqlite3_free(zToFree);
return rc;
}
@@ -738,17 +699,8 @@ static int multiplexClose(sqlite3_file *pConn){
multiplexConn *p = (multiplexConn*)pConn;
multiplexGroup *pGroup = p->pGroup;
int rc = SQLITE_OK;
multiplexEnter();
multiplexFreeComponents(pGroup);
/* remove from linked list */
if( pGroup->pNext ) pGroup->pNext->pPrev = pGroup->pPrev;
if( pGroup->pPrev ){
pGroup->pPrev->pNext = pGroup->pNext;
}else{
gMultiplex.pGroups = pGroup->pNext;
}
sqlite3_free(pGroup);
multiplexLeave();
return rc;
}
@@ -845,7 +797,6 @@ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){
multiplexConn *p = (multiplexConn*)pConn;
multiplexGroup *pGroup = p->pGroup;
int rc = SQLITE_OK;
multiplexEnter();
if( !pGroup->bEnabled ){
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
if( pSubOpen==0 ){
@@ -877,7 +828,6 @@ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){
}
if( rc ) rc = SQLITE_IOERR_TRUNCATE;
}
multiplexLeave();
return rc;
}
@@ -888,7 +838,6 @@ static int multiplexSync(sqlite3_file *pConn, int flags){
multiplexGroup *pGroup = p->pGroup;
int rc = SQLITE_OK;
int i;
multiplexEnter();
for(i=0; i<pGroup->nReal; i++){
sqlite3_file *pSubOpen = pGroup->aReal[i].p;
if( pSubOpen ){
@@ -896,7 +845,6 @@ static int multiplexSync(sqlite3_file *pConn, int flags){
if( rc2!=SQLITE_OK ) rc = rc2;
}
}
multiplexLeave();
return rc;
}
@@ -908,7 +856,6 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
multiplexGroup *pGroup = p->pGroup;
int rc = SQLITE_OK;
int i;
multiplexEnter();
if( !pGroup->bEnabled ){
sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
if( pSubOpen==0 ){
@@ -924,7 +871,6 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
*pSize = i*(sqlite3_int64)pGroup->szChunk + sz;
}
}
multiplexLeave();
return rc;
}
@@ -1151,11 +1097,6 @@ int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault){
pOrigVfs = sqlite3_vfs_find(zOrigVfsName);
if( pOrigVfs==0 ) return SQLITE_ERROR;
assert( pOrigVfs!=&gMultiplex.sThisVfs );
gMultiplex.pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
if( !gMultiplex.pMutex ){
return SQLITE_NOMEM;
}
gMultiplex.pGroups = NULL;
gMultiplex.isInitialized = 1;
gMultiplex.pOrigVfs = pOrigVfs;
gMultiplex.sThisVfs = *pOrigVfs;
@@ -1214,14 +1155,7 @@ int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault){
int sqlite3_multiplex_shutdown(int eForce){
int rc = SQLITE_OK;
if( gMultiplex.isInitialized==0 ) return SQLITE_MISUSE;
if( gMultiplex.pGroups ){
sqlite3_log(SQLITE_MISUSE, "sqlite3_multiplex_shutdown() called "
"while database connections are still open");
if( !eForce ) return SQLITE_MISUSE;
rc = SQLITE_MISUSE;
}
gMultiplex.isInitialized = 0;
sqlite3_mutex_free(gMultiplex.pMutex);
sqlite3_vfs_unregister(&gMultiplex.sThisVfs);
memset(&gMultiplex, 0, sizeof(gMultiplex));
return rc;
@@ -1299,61 +1233,6 @@ static int SQLITE_TCLAPI test_multiplex_shutdown(
return TCL_OK;
}
/*
** tclcmd: sqlite3_multiplex_dump
*/
static int SQLITE_TCLAPI test_multiplex_dump(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
Tcl_Obj *pResult;
Tcl_Obj *pGroupTerm;
multiplexGroup *pGroup;
int i;
int nChunks = 0;
UNUSED_PARAMETER(clientData);
UNUSED_PARAMETER(objc);
UNUSED_PARAMETER(objv);
pResult = Tcl_NewObj();
multiplexEnter();
for(pGroup=gMultiplex.pGroups; pGroup; pGroup=pGroup->pNext){
pGroupTerm = Tcl_NewObj();
if( pGroup->zName ){
pGroup->zName[pGroup->nName] = '\0';
Tcl_ListObjAppendElement(interp, pGroupTerm,
Tcl_NewStringObj(pGroup->zName, -1));
}else{
Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewObj());
}
Tcl_ListObjAppendElement(interp, pGroupTerm,
Tcl_NewIntObj(pGroup->nName));
Tcl_ListObjAppendElement(interp, pGroupTerm,
Tcl_NewIntObj(pGroup->flags));
/* count number of chunks with open handles */
for(i=0; i<pGroup->nReal; i++){
if( pGroup->aReal[i].p!=0 ) nChunks++;
}
Tcl_ListObjAppendElement(interp, pGroupTerm,
Tcl_NewIntObj(nChunks));
Tcl_ListObjAppendElement(interp, pGroupTerm,
Tcl_NewIntObj(pGroup->szChunk));
Tcl_ListObjAppendElement(interp, pGroupTerm,
Tcl_NewIntObj(pGroup->nReal));
Tcl_ListObjAppendElement(interp, pResult, pGroupTerm);
}
multiplexLeave();
Tcl_SetObjResult(interp, pResult);
return TCL_OK;
}
/*
** Tclcmd: test_multiplex_control HANDLE DBNAME SUB-COMMAND ?INT-VALUE?
*/
@@ -1428,7 +1307,6 @@ int Sqlitemultiplex_Init(Tcl_Interp *interp){
} aCmd[] = {
{ "sqlite3_multiplex_initialize", test_multiplex_initialize },
{ "sqlite3_multiplex_shutdown", test_multiplex_shutdown },
{ "sqlite3_multiplex_dump", test_multiplex_dump },
{ "sqlite3_multiplex_control", test_multiplex_control },
};
int i;
+1
View File
@@ -65,6 +65,7 @@ static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
va_start(ap, zFormat);
sqlite3VXPrintf(&acc, zFormat, ap);
va_end(ap);
assert( acc.nChar>0 );
if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1);
sqlite3StrAccumFinish(&acc);
fprintf(stdout,"%s", zBuf);
+3 -1
View File
@@ -282,12 +282,14 @@ void sqlite3Update(
int reg;
if( chngKey || hasFK || pIdx->pPartIdxWhere || pIdx==pPk ){
reg = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
}else{
reg = 0;
for(i=0; i<pIdx->nKeyCol; i++){
i16 iIdxCol = pIdx->aiColumn[i];
if( iIdxCol<0 || aXRef[iIdxCol]>=0 ){
reg = ++pParse->nMem;
pParse->nMem += pIdx->nColumn;
break;
}
}
@@ -398,7 +400,7 @@ void sqlite3Update(
}else{
sqlite3VdbeAddOp4(v, OP_MakeRecord, iPk, nPk, regKey,
sqlite3IndexAffinityStr(db, pPk), nPk);
sqlite3VdbeAddOp2(v, OP_IdxInsert, iEph, regKey);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEph, regKey, iPk, nPk);
}
sqlite3WhereEnd(pWInfo);
}
+1 -1
View File
@@ -191,7 +191,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF);
sqlite3BtreeSetPagerFlags(pTemp, PAGER_SYNCHRONOUS_OFF|PAGER_CACHESPILL);
/* Begin a transaction and take an exclusive lock on the main database
** file. This is done before the sqlite3BtreeGetPageSize(pMain) call below,
+30 -23
View File
@@ -3829,7 +3829,7 @@ case OP_SeekGT: { /* jump, in3 */
if( (oc & 0x0001)==(OP_SeekLT & 0x0001) ) oc++;
}
}
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)iKey, 0, &res);
rc = sqlite3BtreeMovetoIntkey(pC->uc.pCursor, (u64)iKey, 0, &res);
pC->movetoTarget = iKey; /* Used by OP_Delete */
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
@@ -3873,7 +3873,7 @@ case OP_SeekGT: { /* jump, in3 */
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
#endif
r.eqSeen = 0;
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, &r, 0, 0, &res);
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, &r, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
@@ -4042,7 +4042,7 @@ case OP_Found: { /* jump, in3 */
}
}
}
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, 0, &res);
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, pIdxKey, 0, &res);
sqlite3DbFree(db, pFree);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
@@ -4136,7 +4136,7 @@ case OP_NotExists: /* jump, in3 */
assert( pCrsr!=0 );
res = 0;
iKey = pIn3->u.i;
rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
rc = sqlite3BtreeMovetoIntkey(pCrsr, iKey, 0, &res);
assert( rc==SQLITE_OK || res==0 );
pC->movetoTarget = iKey; /* Used by OP_Delete */
pC->nullRow = 0;
@@ -4270,7 +4270,7 @@ case OP_NewRowid: { /* out2 */
sqlite3VdbeMemIntegerify(pMem);
assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */
if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){
rc = SQLITE_FULL; /* IMP: R-12275-61338 */
rc = SQLITE_FULL; /* IMP: R-17817-00630 */
goto abort_due_to_error;
}
if( v<pMem->u.i+1 ){
@@ -4290,7 +4290,7 @@ case OP_NewRowid: { /* out2 */
do{
sqlite3_randomness(sizeof(v), &v);
v &= (MAX_ROWID>>1); v++; /* Ensure that v is greater than zero */
}while( ((rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, 0, (u64)v,
}while( ((rc = sqlite3BtreeMovetoIntkey(pC->uc.pCursor, (u64)v,
0, &res))==SQLITE_OK)
&& (res==0)
&& (++cnt<100));
@@ -4322,15 +4322,10 @@ case OP_NewRowid: { /* out2 */
** then rowid is stored for subsequent return by the
** sqlite3_last_insert_rowid() function (otherwise it is unmodified).
**
** If the OPFLAG_USESEEKRESULT flag of P5 is set and if the result of
** the last seek operation (OP_NotExists or OP_SeekRowid) was a success,
** then this
** operation will not attempt to find the appropriate row before doing
** the insert but will instead overwrite the row that the cursor is
** currently pointing to. Presumably, the prior OP_NotExists or
** OP_SeekRowid opcode
** has already positioned the cursor correctly. This is an optimization
** that boosts performance by avoiding redundant seeks.
** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might
** run faster by avoiding an unnecessary seek on cursor P1. However,
** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior
** seeks on the cursor or if the most recent seek used a key equal to P3.
**
** If the OPFLAG_ISUPDATE flag is set, then this opcode is part of an
** UPDATE operation. Otherwise (if the flag is clear) then this opcode
@@ -4554,6 +4549,7 @@ case OP_Delete: {
rc = sqlite3BtreeDelete(pC->uc.pCursor, pOp->p5);
pC->cacheStatus = CACHE_STALE;
pC->seekResult = 0;
if( rc ) goto abort_due_to_error;
/* Invoke the update-hook if required. */
@@ -5016,23 +5012,30 @@ next_tail:
goto check_for_interrupt;
}
/* Opcode: IdxInsert P1 P2 P3 * P5
/* Opcode: IdxInsert P1 P2 P3 P4 P5
** Synopsis: key=r[P2]
**
** Register P2 holds an SQL index key made using the
** MakeRecord instructions. This opcode writes that key
** into the index P1. Data for the entry is nil.
**
** P3 is a flag that provides a hint to the b-tree layer that this
** insert is likely to be an append.
** If P4 is not zero, then it is the number of values in the unpacked
** key of reg(P2). In that case, P3 is the index of the first register
** for the unpacked key. The availability of the unpacked key can sometimes
** be an optimization.
**
** If P5 has the OPFLAG_APPEND bit set, that is a hint to the b-tree layer
** that this insert is likely to be an append.
**
** If P5 has the OPFLAG_NCHANGE bit set, then the change counter is
** incremented by this instruction. If the OPFLAG_NCHANGE bit is clear,
** then the change counter is unchanged.
**
** If P5 has the OPFLAG_USESEEKRESULT bit set, then the cursor must have
** just done a seek to the spot where the new entry is to be inserted.
** This flag avoids doing an extra seek.
** If the OPFLAG_USESEEKRESULT flag of P5 is set, the implementation might
** run faster by avoiding an unnecessary seek on cursor P1. However,
** the OPFLAG_USESEEKRESULT flag must only be set if there have been no prior
** seeks on the cursor or if the most recent seek used a key equivalent
** to P2.
**
** This instruction only works for indices. The equivalent instruction
** for tables is OP_Insert.
@@ -5065,7 +5068,10 @@ case OP_IdxInsert: { /* in2 */
}else{
x.nKey = pIn2->n;
x.pKey = pIn2->z;
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, pOp->p3,
x.aMem = aMem + pOp->p3;
x.nMem = (u16)pOp->p4.i;
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
(pOp->p5 & OPFLAG_APPEND)!=0,
((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
);
assert( pC->deferredMoveto==0 );
@@ -5101,7 +5107,7 @@ case OP_IdxDelete: {
r.nField = (u16)pOp->p3;
r.default_rc = 0;
r.aMem = &aMem[pOp->p2];
rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, &res);
if( rc ) goto abort_due_to_error;
if( res==0 ){
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
@@ -5109,6 +5115,7 @@ case OP_IdxDelete: {
}
assert( pC->deferredMoveto==0 );
pC->cacheStatus = CACHE_STALE;
pC->seekResult = 0;
break;
}
+4 -1
View File
@@ -96,7 +96,10 @@ struct VdbeCursor {
} uc;
Btree *pBt; /* Separate file holding temporary table */
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
int seekResult; /* Result of previous sqlite3BtreeMoveto() */
int seekResult; /* Result of previous sqlite3BtreeMoveto() or 0
** if there have been no prior seeks on the cursor. */
/* NB: seekResult does not distinguish between "no seeks have ever occurred
** on this cursor" and "the most recent seek was an exact match". */
i64 seqCount; /* Sequence counter */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
VdbeCursor *pAltCursor; /* Associated index cursor from which to read */
+1 -1
View File
@@ -3008,7 +3008,7 @@ static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){
assert( p->deferredMoveto );
assert( p->isTable );
assert( p->eCurType==CURTYPE_BTREE );
rc = sqlite3BtreeMovetoUnpacked(p->uc.pCursor, 0, p->movetoTarget, 0, &res);
rc = sqlite3BtreeMovetoIntkey(p->uc.pCursor, p->movetoTarget, 0, &res);
if( rc ) return rc;
if( res!=0 ) return SQLITE_CORRUPT_BKPT;
#ifdef SQLITE_TEST
+3 -2
View File
@@ -1943,8 +1943,9 @@ int sqlite3WalClose(
**
** The EXCLUSIVE lock is not released before returning.
*/
rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
if( rc==SQLITE_OK ){
if( (db->flags & SQLITE_NoCkptOnClose)==0
&& SQLITE_OK==(rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE))
){
if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
}
+30 -24
View File
@@ -198,11 +198,13 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
WhereTerm *pTerm; /* The term being tested */
int k = pScan->k; /* Where to start scanning */
while( pScan->iEquiv<=pScan->nEquiv ){
iCur = pScan->aiCur[pScan->iEquiv-1];
assert( pScan->iEquiv<=pScan->nEquiv );
pWC = pScan->pWC;
while(1){
iColumn = pScan->aiColumn[pScan->iEquiv-1];
if( iColumn==XN_EXPR && pScan->pIdxExpr==0 ) return 0;
while( (pWC = pScan->pWC)!=0 ){
iCur = pScan->aiCur[pScan->iEquiv-1];
assert( pWC!=0 );
do{
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
if( pTerm->leftCursor==iCur
&& pTerm->u.leftColumn==iColumn
@@ -252,15 +254,17 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
testcase( pTerm->eOperator & WO_IS );
continue;
}
pScan->pWC = pWC;
pScan->k = k+1;
return pTerm;
}
}
}
pScan->pWC = pScan->pWC->pOuter;
pWC = pWC->pOuter;
k = 0;
}
pScan->pWC = pScan->pOrigWC;
}while( pWC!=0 );
if( pScan->iEquiv>=pScan->nEquiv ) break;
pWC = pScan->pOrigWC;
k = 0;
pScan->iEquiv++;
}
@@ -294,24 +298,24 @@ static WhereTerm *whereScanInit(
u32 opMask, /* Operator(s) to scan for */
Index *pIdx /* Must be compatible with this index */
){
int j = 0;
/* memset(pScan, 0, sizeof(*pScan)); */
pScan->pOrigWC = pWC;
pScan->pWC = pWC;
pScan->pIdxExpr = 0;
pScan->idxaff = 0;
pScan->zCollName = 0;
if( pIdx ){
j = iColumn;
int j = iColumn;
iColumn = pIdx->aiColumn[j];
if( iColumn==XN_EXPR ) pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
if( iColumn==pIdx->pTable->iPKey ) iColumn = XN_ROWID;
}
if( pIdx && iColumn>=0 ){
pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
pScan->zCollName = pIdx->azColl[j];
}else{
pScan->idxaff = 0;
pScan->zCollName = 0;
if( iColumn==XN_EXPR ){
pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr;
}else if( iColumn==pIdx->pTable->iPKey ){
iColumn = XN_ROWID;
}else if( iColumn>=0 ){
pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity;
pScan->zCollName = pIdx->azColl[j];
}
}else if( iColumn==XN_EXPR ){
return 0;
}
pScan->opMask = opMask;
pScan->k = 0;
@@ -4860,13 +4864,15 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
}
#endif
if( pLevel->iLeftJoin ){
int ws = pLoop->wsFlags;
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
|| (pLoop->wsFlags & WHERE_INDEXED)!=0 );
if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){
assert( (ws & WHERE_IDX_ONLY)==0 || (ws & WHERE_INDEXED)!=0 );
if( (ws & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor);
}
if( pLoop->wsFlags & WHERE_INDEXED ){
if( (ws & WHERE_INDEXED)
|| ((ws & WHERE_MULTI_OR) && pLevel->u.pCovidx)
){
sqlite3VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur);
}
if( pLevel->op==OP_Return ){
+2 -1
View File
@@ -1844,7 +1844,8 @@ Bitmask sqlite3WhereCodeOneLoopStart(
}
if( iSet>=0 ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid);
sqlite3VdbeAddOp3(v, OP_IdxInsert, regRowset, regRowid, 0);
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, regRowset, regRowid,
r, nPk);
if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
}
+1
View File
@@ -1198,6 +1198,7 @@ static void exprAnalyze(
Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0);
transferJoinMarkings(pNew, pExpr);
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
exprAnalyze(pSrc, pWC, idxNew);
}
+8 -6
View File
@@ -164,17 +164,19 @@ do_extract_hints_test 2.10 {
x2 {AND(EQ(c1,ADD(32,32)),EQ(c0,r[2]))}
}
do_extract_hints_test 2.11 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE x2.b LIKE 'abc%'
} {
x2 {AND(expr,EQ(c0,r[2]))}
ifcapable !icu {
# This test only works using the built-in LIKE, not the ICU LIKE extension.
do_extract_hints_test 2.11 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE x2.b LIKE 'abc%'
} {
x2 {AND(expr,EQ(c0,r[2]))}
}
}
do_extract_hints_test 2.11 {
do_extract_hints_test 2.12 {
SELECT * FROM x1 LEFT JOIN x2 ON (a=x) WHERE coalesce(x2.b, 1)
} {
x2 {EQ(c0,r[2])}
}
finish_test
+68
View File
@@ -0,0 +1,68 @@
# 2016 November 4
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing OOM error handling within the built-in
# INSTR() function.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix instrfault
# Use big NEEDLE and HAYSTACK strings. Strings so large they cannot
# use lookaside buffers.
#
set ::NEEDLE [string repeat "abcdefghijklmnopqrstuvwxyz" 10]
set ::HAYSTACK "[string repeat 123 10]$NEEDLE[string repeat 456 10]"
foreach {enc} {
utf8
utf16
} {
reset_db
execsql "PRAGMA encoding = $enc"
do_execsql_test 1.$enc.1 {
CREATE TABLE t1(n, h);
INSERT INTO t1 VALUES($::NEEDLE, $::HAYSTACK);
} {}
do_faultsim_test 1.$enc.1 -faults oom-t* -prep {
execsql { SELECT instr(h, n) FROM t1 }
} -body {
execsql { SELECT instr(h, n) FROM t1 }
} -test {
faultsim_test_result {0 31}
}
do_faultsim_test 1.$enc.2 -faults oom-t* -prep {
execsql { SELECT instr($::HAYSTACK, $::NEEDLE) FROM t1 }
} -body {
execsql { SELECT instr($::HAYSTACK, $::NEEDLE) FROM t1 }
} -test {
faultsim_test_result {0 31}
}
do_faultsim_test 1.$enc.3 -faults oom-t* -prep {
set ::stmt [sqlite3_prepare_v2 db "SELECT instr(?, ?)" -1 dummy]
sqlite3_bind_text $::stmt 1 $::HAYSTACK [string length $::HAYSTACK]
sqlite3_bind_text $::stmt 2 $::NEEDLE [string length $::NEEDLE]
} -body {
set rc [sqlite3_step $::stmt]
if {$rc=="SQLITE_NOMEM"} { error "out of memory" }
sqlite3_column_int $::stmt 0
} -test {
faultsim_test_result {0 31}
sqlite3_finalize $::stmt
}
}
finish_test
+305 -2
View File
@@ -382,8 +382,311 @@ do_catchsql_test json-9.7 {
SELECT json_quote()
} {1 {wrong number of arguments to function json_quote()}}
# Make sure only valid backslash-escapes are accepted.
#
do_execsql_test json-10.1 {
SELECT json_valid('" \ "');
} {0}
do_execsql_test json-10.2 {
SELECT json_valid('" \! "');
} {0}
do_execsql_test json-10.3 {
SELECT json_valid('" \" "');
} {1}
do_execsql_test json-10.4 {
SELECT json_valid('" \# "');
} {0}
do_execsql_test json-10.5 {
SELECT json_valid('" \$ "');
} {0}
do_execsql_test json-10.6 {
SELECT json_valid('" \% "');
} {0}
do_execsql_test json-10.7 {
SELECT json_valid('" \& "');
} {0}
do_execsql_test json-10.8 {
SELECT json_valid('" \'' "');
} {0}
do_execsql_test json-10.9 {
SELECT json_valid('" \( "');
} {0}
do_execsql_test json-10.10 {
SELECT json_valid('" \) "');
} {0}
do_execsql_test json-10.11 {
SELECT json_valid('" \* "');
} {0}
do_execsql_test json-10.12 {
SELECT json_valid('" \+ "');
} {0}
do_execsql_test json-10.13 {
SELECT json_valid('" \, "');
} {0}
do_execsql_test json-10.14 {
SELECT json_valid('" \- "');
} {0}
do_execsql_test json-10.15 {
SELECT json_valid('" \. "');
} {0}
do_execsql_test json-10.16 {
SELECT json_valid('" \/ "');
} {1}
do_execsql_test json-10.17 {
SELECT json_valid('" \0 "');
} {0}
do_execsql_test json-10.18 {
SELECT json_valid('" \1 "');
} {0}
do_execsql_test json-10.19 {
SELECT json_valid('" \2 "');
} {0}
do_execsql_test json-10.20 {
SELECT json_valid('" \3 "');
} {0}
do_execsql_test json-10.21 {
SELECT json_valid('" \4 "');
} {0}
do_execsql_test json-10.22 {
SELECT json_valid('" \5 "');
} {0}
do_execsql_test json-10.23 {
SELECT json_valid('" \6 "');
} {0}
do_execsql_test json-10.24 {
SELECT json_valid('" \7 "');
} {0}
do_execsql_test json-10.25 {
SELECT json_valid('" \8 "');
} {0}
do_execsql_test json-10.26 {
SELECT json_valid('" \9 "');
} {0}
do_execsql_test json-10.27 {
SELECT json_valid('" \: "');
} {0}
do_execsql_test json-10.28 {
SELECT json_valid('" \; "');
} {0}
do_execsql_test json-10.29 {
SELECT json_valid('" \< "');
} {0}
do_execsql_test json-10.30 {
SELECT json_valid('" \= "');
} {0}
do_execsql_test json-10.31 {
SELECT json_valid('" \> "');
} {0}
do_execsql_test json-10.32 {
SELECT json_valid('" \? "');
} {0}
do_execsql_test json-10.33 {
SELECT json_valid('" \@ "');
} {0}
do_execsql_test json-10.34 {
SELECT json_valid('" \A "');
} {0}
do_execsql_test json-10.35 {
SELECT json_valid('" \B "');
} {0}
do_execsql_test json-10.36 {
SELECT json_valid('" \C "');
} {0}
do_execsql_test json-10.37 {
SELECT json_valid('" \D "');
} {0}
do_execsql_test json-10.38 {
SELECT json_valid('" \E "');
} {0}
do_execsql_test json-10.39 {
SELECT json_valid('" \F "');
} {0}
do_execsql_test json-10.40 {
SELECT json_valid('" \G "');
} {0}
do_execsql_test json-10.41 {
SELECT json_valid('" \H "');
} {0}
do_execsql_test json-10.42 {
SELECT json_valid('" \I "');
} {0}
do_execsql_test json-10.43 {
SELECT json_valid('" \J "');
} {0}
do_execsql_test json-10.44 {
SELECT json_valid('" \K "');
} {0}
do_execsql_test json-10.45 {
SELECT json_valid('" \L "');
} {0}
do_execsql_test json-10.46 {
SELECT json_valid('" \M "');
} {0}
do_execsql_test json-10.47 {
SELECT json_valid('" \N "');
} {0}
do_execsql_test json-10.48 {
SELECT json_valid('" \O "');
} {0}
do_execsql_test json-10.49 {
SELECT json_valid('" \P "');
} {0}
do_execsql_test json-10.50 {
SELECT json_valid('" \Q "');
} {0}
do_execsql_test json-10.51 {
SELECT json_valid('" \R "');
} {0}
do_execsql_test json-10.52 {
SELECT json_valid('" \S "');
} {0}
do_execsql_test json-10.53 {
SELECT json_valid('" \T "');
} {0}
do_execsql_test json-10.54 {
SELECT json_valid('" \U "');
} {0}
do_execsql_test json-10.55 {
SELECT json_valid('" \V "');
} {0}
do_execsql_test json-10.56 {
SELECT json_valid('" \W "');
} {0}
do_execsql_test json-10.57 {
SELECT json_valid('" \X "');
} {0}
do_execsql_test json-10.58 {
SELECT json_valid('" \Y "');
} {0}
do_execsql_test json-10.59 {
SELECT json_valid('" \Z "');
} {0}
do_execsql_test json-10.60 {
SELECT json_valid('" \[ "');
} {0}
do_execsql_test json-10.61 {
SELECT json_valid('" \\ "');
} {1}
do_execsql_test json-10.62 {
SELECT json_valid('" \] "');
} {0}
do_execsql_test json-10.63 {
SELECT json_valid('" \^ "');
} {0}
do_execsql_test json-10.64 {
SELECT json_valid('" \_ "');
} {0}
do_execsql_test json-10.65 {
SELECT json_valid('" \` "');
} {0}
do_execsql_test json-10.66 {
SELECT json_valid('" \a "');
} {0}
do_execsql_test json-10.67 {
SELECT json_valid('" \b "');
} {1}
do_execsql_test json-10.68 {
SELECT json_valid('" \c "');
} {0}
do_execsql_test json-10.69 {
SELECT json_valid('" \d "');
} {0}
do_execsql_test json-10.70 {
SELECT json_valid('" \e "');
} {0}
do_execsql_test json-10.71 {
SELECT json_valid('" \f "');
} {1}
do_execsql_test json-10.72 {
SELECT json_valid('" \g "');
} {0}
do_execsql_test json-10.73 {
SELECT json_valid('" \h "');
} {0}
do_execsql_test json-10.74 {
SELECT json_valid('" \i "');
} {0}
do_execsql_test json-10.75 {
SELECT json_valid('" \j "');
} {0}
do_execsql_test json-10.76 {
SELECT json_valid('" \k "');
} {0}
do_execsql_test json-10.77 {
SELECT json_valid('" \l "');
} {0}
do_execsql_test json-10.78 {
SELECT json_valid('" \m "');
} {0}
do_execsql_test json-10.79 {
SELECT json_valid('" \n "');
} {1}
do_execsql_test json-10.80 {
SELECT json_valid('" \o "');
} {0}
do_execsql_test json-10.81 {
SELECT json_valid('" \p "');
} {0}
do_execsql_test json-10.82 {
SELECT json_valid('" \q "');
} {0}
do_execsql_test json-10.83 {
SELECT json_valid('" \r "');
} {1}
do_execsql_test json-10.84 {
SELECT json_valid('" \s "');
} {0}
do_execsql_test json-10.85 {
SELECT json_valid('" \t "');
} {1}
do_execsql_test json-10.86.0 {
SELECT json_valid('" \u "');
} {0}
do_execsql_test json-10.86.1 {
SELECT json_valid('" \ua "');
} {0}
do_execsql_test json-10.86.2 {
SELECT json_valid('" \uab "');
} {0}
do_execsql_test json-10.86.3 {
SELECT json_valid('" \uabc "');
} {0}
do_execsql_test json-10.86.4 {
SELECT json_valid('" \uabcd "');
} {1}
do_execsql_test json-10.86.5 {
SELECT json_valid('" \uFEDC "');
} {1}
do_execsql_test json-10.86.6 {
SELECT json_valid('" \u1234 "');
} {1}
do_execsql_test json-10.87 {
SELECT json_valid('" \v "');
} {0}
do_execsql_test json-10.88 {
SELECT json_valid('" \w "');
} {0}
do_execsql_test json-10.89 {
SELECT json_valid('" \x "');
} {0}
do_execsql_test json-10.90 {
SELECT json_valid('" \y "');
} {0}
do_execsql_test json-10.91 {
SELECT json_valid('" \z "');
} {0}
do_execsql_test json-10.92 {
SELECT json_valid('" \{ "');
} {0}
do_execsql_test json-10.93 {
SELECT json_valid('" \| "');
} {0}
do_execsql_test json-10.94 {
SELECT json_valid('" \} "');
} {0}
do_execsql_test json-10.95 {
SELECT json_valid('" \~ "');
} {0}
finish_test
+9 -12
View File
@@ -195,15 +195,16 @@ do_test multiplex-2.3.1 {
unset -nocomplain ::log
do_test multiplex-2.4.1 {
sqlite3_multiplex_shutdown
} {SQLITE_MISUSE}
#do_test multiplex-2.4.1 {
# sqlite3_multiplex_shutdown
#} {SQLITE_MISUSE}
do_test multiplex-2.4.2 {
execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
} {}
do_test multiplex-2.4.3 {
set ::log
} {SQLITE_MISUSE {sqlite3_multiplex_shutdown() called while database connections are still open}}
#do_test multiplex-2.4.3 {
# set ::log
#} {SQLITE_MISUSE {sqlite3_multiplex_shutdown() called while database connections are still open}}
do_test multiplex-2.4.4 { file size [multiplex_name test.x 0] } {7168}
do_test multiplex-2.4.5 {
db close
@@ -445,11 +446,7 @@ multiplex_set db main 32768 16
# Return a list of all currently defined multiplexs.
proc multiplex_list {} {
set allq {}
foreach q [sqlite3_multiplex_dump] {
lappend allq [lindex $q 0]
}
return [lsort $allq]
glob -nocomplain test2.db*
}
do_test multiplex-4.1.6 {
@@ -494,7 +491,7 @@ do_test multiplex-4.1.11 {
do_test multiplex-4.1.12 {
db close
multiplex_list
} {}
} {test2.db}
#-------------------------------------------------------------------------
+55
View File
@@ -0,0 +1,55 @@
# 2016 October 31
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE
# option.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl
ifcapable !wal {finish_test ; return }
set testprefix nockpt
do_execsql_test 1.0 {
PRAGMA page_size = 1024;
PRAGMA journal_mode = wal;
CREATE TABLE c1(x, y, z);
INSERT INTO c1 VALUES(1, 2, 3);
} {wal}
do_test 1.1 { file exists test.db-wal } 1
do_test 1.2 { file size test.db-wal } [wal_file_size 3 1024]
do_test 1.3 { db close } {}
do_test 1.4 { file exists test.db-wal } 0
sqlite3 db test.db
do_execsql_test 1.5 {
INSERT INTO c1 VALUES(4, 5, 6);
INSERT INTO c1 VALUES(7, 8, 9);
}
do_test 1.6 { file exists test.db-wal } 1
do_test 1.7 { sqlite3_db_config db NO_CKPT_ON_CLOSE 1 } {1}
do_test 1.8 { file size test.db-wal } [wal_file_size 2 1024]
do_test 1.9 { db close } {}
do_test 1.10 { file exists test.db-wal } 1
do_test 1.11 { file size test.db-wal } [wal_file_size 2 1024]
sqlite3 db test.db
do_execsql_test 1.12 {
SELECT * FROM c1
} {1 2 3 4 5 6 7 8 9}
finish_test
+10
View File
@@ -255,5 +255,15 @@ do_catchsql_test 11.8 {
SELECT * FROM t11 WHERE (a,a) IS NOT 1;
} {1 {row value misused}}
# 2016-10-27: https://www.sqlite.org/src/tktview/fef4bb4bd9185ec8f
# Incorrect result from a LEFT JOIN with a row-value constraint
#
do_execsql_test 12.1 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,2);
DROP TABLE IF EXISTS t2;
CREATE TABLE t2(x,y); INSERT INTO t2 VALUES(3,4);
SELECT *,'x' FROM t1 LEFT JOIN t2 ON (a,b)=(x,y);
} {1 2 {} {} x}
finish_test
+63 -8
View File
@@ -529,7 +529,7 @@ void testset_main(void){
speedtest1_begin_test(130, "%d SELECTS, numeric BETWEEN, unindexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)) FROM t1\n"
"SELECT count(*), avg(b), sum(length(c)), group_concat(c) FROM t1\n"
" WHERE b BETWEEN ?1 AND ?2; -- %d times", n
);
for(i=1; i<=n; i++){
@@ -549,7 +549,7 @@ void testset_main(void){
speedtest1_begin_test(140, "%d SELECTS, LIKE, unindexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)) FROM t1\n"
"SELECT count(*), avg(b), sum(length(c)), group_concat(c) FROM t1\n"
" WHERE c LIKE ?1; -- %d times", n
);
for(i=1; i<=n; i++){
@@ -560,7 +560,7 @@ void testset_main(void){
zNum[len] = '%';
zNum[len+1] = 0;
}
sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC);
sqlite3_bind_text(g.pStmt, 1, zNum, len+1, SQLITE_STATIC);
speedtest1_run();
}
speedtest1_exec("COMMIT");
@@ -582,7 +582,7 @@ void testset_main(void){
zNum[len] = '%';
zNum[len+1] = 0;
}
sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC);
sqlite3_bind_text(g.pStmt, 1, zNum, len+1, SQLITE_STATIC);
speedtest1_run();
}
speedtest1_exec("COMMIT");
@@ -603,7 +603,7 @@ void testset_main(void){
zNum[len] = '%';
zNum[len+1] = 0;
}
sqlite3_bind_text(g.pStmt, 1, zNum, len, SQLITE_STATIC);
sqlite3_bind_text(g.pStmt, 1, zNum, len+1, SQLITE_STATIC);
speedtest1_run();
}
speedtest1_exec("COMMIT");
@@ -625,7 +625,7 @@ void testset_main(void){
speedtest1_begin_test(160, "%d SELECTS, numeric BETWEEN, indexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)) FROM t1\n"
"SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM t1\n"
" WHERE b BETWEEN ?1 AND ?2; -- %d times", n
);
for(i=1; i<=n; i++){
@@ -645,7 +645,7 @@ void testset_main(void){
speedtest1_begin_test(161, "%d SELECTS, numeric BETWEEN, PK", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)) FROM t2\n"
"SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM t2\n"
" WHERE a BETWEEN ?1 AND ?2; -- %d times", n
);
for(i=1; i<=n; i++){
@@ -665,7 +665,7 @@ void testset_main(void){
speedtest1_begin_test(170, "%d SELECTS, text BETWEEN, indexed", n);
speedtest1_exec("BEGIN");
speedtest1_prepare(
"SELECT count(*), avg(b), sum(length(c)) FROM t1\n"
"SELECT count(*), avg(b), sum(length(c)), group_concat(a) FROM t1\n"
" WHERE c BETWEEN ?1 AND (?1||'~'); -- %d times", n
);
for(i=1; i<=n; i++){
@@ -831,6 +831,61 @@ void testset_main(void){
speedtest1_run();
speedtest1_end_test();
sz = n = g.szTest*700;
zNum[0] = 0;
maxb = roundup_allones(sz/3);
speedtest1_begin_test(400, "%d INSERT OR REPLACE ops on an IPK", n);
speedtest1_exec("BEGIN");
speedtest1_exec("CREATE%s TABLE t5(a INTEGER PRIMARY KEY, b %s);",
isTemp(9), g.zNN);
speedtest1_prepare("INSERT OR REPLACE INTO t5 VALUES(?1,?2); -- %d times",n);
for(i=1; i<=n; i++){
x1 = swizzle(i,maxb);
speedtest1_numbername(i, zNum, sizeof(zNum));
sqlite3_bind_int(g.pStmt, 1, (sqlite3_int64)x1);
sqlite3_bind_text(g.pStmt, 2, zNum, -1, SQLITE_STATIC);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
speedtest1_begin_test(410, "%d SELECTS on an IPK", n);
speedtest1_prepare("SELECT b FROM t5 WHERE a=?1; -- %d times",n);
for(i=1; i<=n; i++){
x1 = swizzle(i,maxb);
sqlite3_bind_int(g.pStmt, 1, (sqlite3_int64)x1);
speedtest1_run();
}
speedtest1_end_test();
sz = n = g.szTest*700;
zNum[0] = 0;
maxb = roundup_allones(sz/3);
speedtest1_begin_test(500, "%d INSERT OR REPLACE ops on TEXT PK", n);
speedtest1_exec("BEGIN");
speedtest1_exec("CREATE%s TABLE t6(a TEXT PRIMARY KEY, b %s)%s;",
isTemp(9), g.zNN,
sqlite3_libversion_number()>=3008002 ? "WITHOUT ROWID" : "");
speedtest1_prepare("INSERT OR REPLACE INTO t6 VALUES(?1,?2); -- %d times",n);
for(i=1; i<=n; i++){
x1 = swizzle(i,maxb);
speedtest1_numbername(x1, zNum, sizeof(zNum));
sqlite3_bind_int(g.pStmt, 2, i);
sqlite3_bind_text(g.pStmt, 1, zNum, -1, SQLITE_STATIC);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
speedtest1_begin_test(510, "%d SELECTS on an IPK", n);
speedtest1_prepare("SELECT b FROM t6 WHERE a=?1; -- %d times",n);
for(i=1; i<=n; i++){
x1 = swizzle(i,maxb);
speedtest1_numbername(x1, zNum, sizeof(zNum));
sqlite3_bind_text(g.pStmt, 1, zNum, -1, SQLITE_STATIC);
speedtest1_run();
}
speedtest1_end_test();
speedtest1_begin_test(980, "PRAGMA integrity_check");
speedtest1_exec("PRAGMA integrity_check");
speedtest1_end_test();
+8
View File
@@ -55,6 +55,10 @@ foreach {tn uri file} {
ifcapable !curdir { if {$tn==3} break }
ifcapable uri_00_error {
if {[string first %00 $uri]>=0} continue
}
if {$tcl_platform(platform)=="windows"} {
#
# NOTE: Due to limits on legal characters for file names imposed by
@@ -124,6 +128,10 @@ foreach {tn uri kvlist} {
14 http:test.db?hello&world {}
} {
ifcapable uri_00_error {
if {[string first %00 $uri]>=0} continue
}
if {$tcl_platform(platform) == "windows" && $tn>12} {
continue
}
+63
View File
@@ -0,0 +1,63 @@
# 2016 October 26
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Tests for SQLITE_ENABLE_URI_00_ERROR builds.
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable !uri_00_error {
finish_test
return
}
set testprefix uri2
db close
sqlite3_shutdown
sqlite3_config_uri 1
foreach {tn uri} {
1 file:test.db%00trailing
2 file:test.db?%00trailing=1
3 file:test.db?trailing=1%00
4 file:test.db?trailing=1&abc%00def
5 file:test.db?trailing=1&abc%00def
} {
do_test 1.$tn.1 {
set rc [catch { sqlite3 db $uri } msg]
list $rc $msg
} {1 {unexpected %00 in uri}}
do_test 1.$tn.2 {
set DB2 [sqlite3_open $uri]
sqlite3_errcode $DB2
} {SQLITE_ERROR}
catch { sqlite3_close $DB2 }
do_test 1.$tn.2 {
sqlite3 db ""
catchsql { ATTACH $uri AS aux }
} {1 {unexpected %00 in uri}}
do_test 1.$tn.3 {
sqlite3_errcode db
} {SQLITE_ERROR}
catch { db close }
}
reset_db
do_test 2.0 {
expr {[lsearch [execsql {PRAGMA compile_options}] ENABLE_URI_00_ERROR] >= 0}
} 1
finish_test
+39
View File
@@ -14,6 +14,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix vacuum5
# If the VACUUM statement is disabled in the current build, skip all
# the tests in this file.
@@ -111,4 +112,42 @@ do_catchsql_test vacuum5-2.0 {
VACUUM olaf;
} {1 {unknown database olaf}}
#-------------------------------------------------------------------------
# Test that a temp file is opened as part of VACUUM.
#
if {$::TEMP_STORE<3 && [permutation]!="inmemory_journal"} {
db close
testvfs tvfs
tvfs filter xOpen
tvfs script open_cb
forcedelete test.db
set ::openfiles [list]
proc open_cb {method args} {
lappend ::openfiles [file tail [lindex $args 0]]
}
sqlite3 db test.db -vfs tvfs
do_execsql_test 3.0 {
PRAGMA temp_store = file;
PRAGMA page_size = 1024;
PRAGMA cache_size = 50;
CREATE TABLE t1(i INTEGER PRIMARY KEY, j UNIQUE);
WITH s(i) AS (
VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1000
)
INSERT INTO t1 SELECT NULL, randomblob(100) FROM s;
}
do_execsql_test 3.1 { VACUUM }
db close
tvfs delete
do_test 3.2 {
lrange $::openfiles 0 4
} {test.db test.db-journal test.db-journal {} test.db-journal}
}
finish_test
+2
View File
@@ -238,6 +238,8 @@ do_test 4.4.2 {
# Confirm that it is possible to get an SQLITE_BUSY_SNAPSHOT error from
# "BEGIN EXCLUSIVE" if the connection already has an open read-transaction.
#
db close
db2 close
reset_db
sqlite3 db2 test.db
do_execsql_test 5.1 {
+77
View File
@@ -337,4 +337,81 @@ do_searchcount_test 6.6.4 {
SELECT c FROM x1 WHERE b=6 OR c=11 OR a=1
} {7 11 3 search 7}
#-------------------------------------------------------------------------
#
do_execsql_test 7.0 {
CREATE TABLE y1(a, b);
CREATE TABLE y2(x, y);
CREATE INDEX y2xy ON y2(x, y);
INSERT INTO y1 VALUES(1, 1);
INSERT INTO y2 VALUES(3, 3);
}
do_execsql_test 7.1 {
SELECT * FROM y1 LEFT JOIN y2 ON ((x=1 AND y=b) OR (x=2 AND y=b))
} {1 1 {} {}}
do_execsql_test 7.3 {
CREATE TABLE foo (Id INTEGER PRIMARY KEY, fa INTEGER, fb INTEGER);
CREATE TABLE bar (Id INTEGER PRIMARY KEY, ba INTEGER, bb INTEGER);
INSERT INTO foo VALUES(1, 1, 1);
INSERT INTO foo VALUES(2, 1, 2);
INSERT INTO foo VALUES(3, 1, 3);
INSERT INTO foo VALUES(4, 1, 4);
INSERT INTO foo VALUES(5, 1, 5);
INSERT INTO foo VALUES(6, 1, 6);
INSERT INTO foo VALUES(7, 1, 7);
INSERT INTO foo VALUES(8, 1, 8);
INSERT INTO foo VALUES(9, 1, 9);
INSERT INTO bar VALUES(NULL, 1, 1);
INSERT INTO bar VALUES(NULL, 2, 2);
INSERT INTO bar VALUES(NULL, 3, 3);
INSERT INTO bar VALUES(NULL, 1, 4);
INSERT INTO bar VALUES(NULL, 2, 5);
INSERT INTO bar VALUES(NULL, 3, 6);
INSERT INTO bar VALUES(NULL, 1, 7);
INSERT INTO bar VALUES(NULL, 2, 8);
INSERT INTO bar VALUES(NULL, 3, 9);
}
do_execsql_test 7.4 {
SELECT
bar.Id, bar.ba, bar.bb, foo.fb
FROM foo LEFT JOIN bar
ON (bar.ba = 1 AND bar.bb = foo.fb)
OR (bar.ba = 5 AND bar.bb = foo.fb);
} {
1 1 1 1
{} {} {} 2
{} {} {} 3
4 1 4 4
{} {} {} 5
{} {} {} 6
7 1 7 7
{} {} {} 8
{} {} {} 9
}
do_execsql_test 7.5 {
CREATE INDEX idx_bar ON bar(ba, bb);
SELECT
bar.Id, bar.ba, bar.bb, foo.fb
FROM foo LEFT JOIN bar
ON (bar.ba = 1 AND bar.bb = foo.fb)
OR (bar.ba = 5 AND bar.bb = foo.fb);
} {
1 1 1 1
{} {} {} 2
{} {} {} 3
4 1 4 4
{} {} {} 5
{} {} {} 6
7 1 7 7
{} {} {} 8
{} {} {} 9
}
finish_test
-19
View File
@@ -328,24 +328,5 @@ do_catchsql_test 7.3 {
) WITHOUT ROWID;
} {1 {no such column: rowid}}
# The PRAGMA index_info and index_xinfo pragmas work on
# WITHOUT ROWID tables too, but not on rowid tables.
#
do_execsql_test 8.1 {
CREATE TABLE t80a(a TEXT, b INT, c BLOB, PRIMARY KEY(c,b));
PRAGMA index_info(t80a);
} {}
do_execsql_test 8.2 {
PRAGMA index_xinfo(t80a);
} {}
do_execsql_test 8.3 {
CREATE TABLE t80b(a TEXT, b INT, c BLOB, PRIMARY KEY(c,b)) WITHOUT ROWID;
PRAGMA index_info(t80b);
} {0 2 c 1 1 b}
do_execsql_test 8.4 {
PRAGMA index_xinfo(t80b);
} {0 2 c 0 BINARY 1 1 1 b 0 BINARY 1 2 0 a 0 BINARY 0}
finish_test
+1 -1
View File
@@ -268,7 +268,7 @@ REM
IF DEFINED TCLSH_CMD (
SET TCLSH_FILE=%TCLSH_CMD%
) ELSE (
SET TCLSH_FILE=tclsh85.exe
SET TCLSH_FILE=tclsh.exe
)
FOR %%T IN (%TCLSH_FILE%) DO (
+1 -1
View File
@@ -77,7 +77,7 @@
# command prompt:
#
# CD /D C:\dev\sqlite\core
# tclsh85 tool\mkvsix.tcl C:\Temp
# tclsh tool\mkvsix.tcl C:\Temp
#
# In the example above, "C:\dev\sqlite\core" represents the root of the source
# tree for SQLite and "C:\Temp" represents the top-level directory containing