Merge all recent changes from trunk,

including the fix for the OP_SCopy-vs-OP_Copy problem.

FossilOrigin-Name: 9515c8344a6743bbb0c6a6e49fb79fb3139090df
This commit is contained in:
drh 2014-04-03 16:35:33 +00:00
commit 652cc4b6dc
16 changed files with 152 additions and 73 deletions

View File

@ -1,5 +1,5 @@
C Merge\sin\sfixes\s(including\sthe\scorrupt-database\scrash\sfix)\sand\nperformance\senhancements\sfrom\strunk. C Merge\sall\srecent\schanges\sfrom\strunk,\nincluding\sthe\sfix\sfor\sthe\sOP_SCopy-vs-OP_Copy\sproblem.
D 2014-03-26T19:43:30.427 D 2014-04-03T16:35:33.203
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a F Makefile.in e4ee6d36cdf6136aee0158675a3b24dd3bf31a5a
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -178,7 +178,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53 F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 8d7e432bdd27d63182865c708ea0e7606489b6d1 F src/btree.c a59a199f21338ae1847d69f5db87c3e8ef1b1578
F src/btree.h 232836cb51753f2e96aa8ce0f052c6df850f76ba F src/btree.h 232836cb51753f2e96aa8ce0f052c6df850f76ba
F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4 F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4
F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0 F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0
@ -206,7 +206,7 @@ F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534 F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
F src/mem5.c aeb019f271ea53de83d651ec526877e6ba863450 F src/mem5.c 74670012946c4adc8a6ad84d03acc80959c3e529
F src/memjournal.c 0683aac6cab6ec2b5374c0db37c0deb2436a3785 F src/memjournal.c 0683aac6cab6ec2b5374c0db37c0deb2436a3785
F src/mutex.c d3b66a569368015e0fcb1ac15f81c119f504d3bc F src/mutex.c d3b66a569368015e0fcb1ac15f81c119f504d3bc
F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea
@ -232,11 +232,11 @@ F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66 F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
F src/select.c 269c3e31a450fce642a10569221a49180348c88e F src/select.c 269c3e31a450fce642a10569221a49180348c88e
F src/shell.c cee9f46f2688a261601b1fd3d7f4b3cddf9b5cdf F src/shell.c 5260f2ada8dd06e9f5ae0a448c8c01e7a75dd881
F src/sqlite.h.in a31c8b7782a0388b4bd823ed3a3a3e4b93b0cf42 F src/sqlite.h.in a31c8b7782a0388b4bd823ed3a3a3e4b93b0cf42
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h b0fa7a8b72fceda6bf989fba2699b5208c861cbc F src/sqliteInt.h 2ce2e12bc5a4cf8e5511ee11ee4778a1911be7e9
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@ -292,11 +292,11 @@ F src/update.c 7bb549d61efc6853f5cc708c1de6931179f8a12d
F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c
F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
F src/vdbe.c 99f878d003314340d6a1e8a8bb185b60ced628df F src/vdbe.c 47bdf5f82fa23548bc0ee720c54e3b2b8802babe
F src/vdbe.h e8e1219a7fd7395deb7a9824f9b7757d642fcf1a F src/vdbe.h d03fcf47890ae1c79a335ca994cb878b302697ca
F src/vdbeInt.h faadf45c5a0c32a251228222fed380ab1389202e F src/vdbeInt.h c05d4572211384c560b7579e7a299248cf31d6bd
F src/vdbeapi.c d3c662762b62e330a03f29de8e2ac7098ef78030 F src/vdbeapi.c d3c662762b62e330a03f29de8e2ac7098ef78030
F src/vdbeaux.c 74aa0e2e9c87b2e9c9cdea501dbf9243d7b7759b F src/vdbeaux.c f9c225c26b4cab6239a7790b4bd14a6cd96ba19e
F src/vdbeblob.c 2d1f0fdb0f5b72118520980360a594b1c30cbdd8 F src/vdbeblob.c 2d1f0fdb0f5b72118520980360a594b1c30cbdd8
F src/vdbemem.c 6fc77594c60f6155404f3f8d71bf36d1fdeb4447 F src/vdbemem.c 6fc77594c60f6155404f3f8d71bf36d1fdeb4447
F src/vdbesort.c 4abb7c0f8f19b7d7d82f4558d5da1a30fdf9ea38 F src/vdbesort.c 4abb7c0f8f19b7d7d82f4558d5da1a30fdf9ea38
@ -305,7 +305,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8 F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45 F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
F src/where.c da8ec216f14af617505799b0b4e52c73dda7a5ca F src/where.c ebad891b7494d0c5f925cf7ab135380bd958cba3
F src/whereInt.h 2564055b440e44ebec8b47f237bbccae6719b7af F src/whereInt.h 2564055b440e44ebec8b47f237bbccae6719b7af
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@ -417,9 +417,9 @@ F test/corruptC.test 02405cf7ed0c1e989060e1aab6d02ffbc3906fbb
F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040 F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4 F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
F test/corruptG.test 58ec333a01997fe655e34e5bea52b7a2a6b9704d F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804
F test/corruptH.test 88ed71a086e13591c917aac6de32750e7c7281cb F test/corruptH.test 88ed71a086e13591c917aac6de32750e7c7281cb
F test/corruptI.test 1b796461e5b635e0a74e3c4ecb1121c82d319dff F test/corruptI.test b3e4203d420490fc3d3062711597bc1dea06a789
F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5 F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5
F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62 F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
@ -1071,7 +1071,7 @@ F test/wal3.test b22eb662bcbc148c5f6d956eaf94b047f7afe9c0
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
F test/wal5.test 8f888b50f66b78821e61ed0e233ded5de378224b F test/wal5.test 8f888b50f66b78821e61ed0e233ded5de378224b
F test/wal6.test 527581f5527bf9c24394991e2be83000aace5f9e F test/wal6.test 527581f5527bf9c24394991e2be83000aace5f9e
F test/wal64k.test 63828c2161ad76ddd4109dee0a096b6ef6895698 F test/wal64k.test 163655ecd2cb8afef4737cac2a40fdd2eeaf20b8
F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd F test/wal7.test 2ae8f427d240099cc4b2dfef63cff44e2a68a1bd
F test/wal8.test 75c42e1bc4545c277fed212f8fc9b7723cd02216 F test/wal8.test 75c42e1bc4545c277fed212f8fc9b7723cd02216
F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750 F test/wal9.test 378e76a9ad09cd9bee06c172ad3547b0129a6750
@ -1107,7 +1107,7 @@ F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a
F test/whereD.test 6c2feb79ef1f68381b07f39017fe5f9b96da8d62 F test/whereD.test 6c2feb79ef1f68381b07f39017fe5f9b96da8d62
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7 F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
F test/whereG.test eb3a46b3eaf38e25e3013433b2db8a25a866c215 F test/whereG.test 2533b72ed4a31fd1687230a499b557b911525344
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
@ -1136,7 +1136,7 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/lemon.c 07aba6270d5a5016ba8107b09e431eea4ecdc123 F tool/lemon.c 07aba6270d5a5016ba8107b09e431eea4ecdc123
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
F tool/logest.c 7ad625cac3d54012b27d468b7af6612f78b9ba75 F tool/logest.c 388c318c7ac8b52b7c08ca1e2de0f4ca9a8f7e81
F tool/mkautoconfamal.sh f8d8dbf7d62f409ebed5134998bf5b51d7266383 F tool/mkautoconfamal.sh f8d8dbf7d62f409ebed5134998bf5b51d7266383
F tool/mkkeywordhash.c c9e05e4a7bcab8fab9f583d5b321fb72f565ad97 F tool/mkkeywordhash.c c9e05e4a7bcab8fab9f583d5b321fb72f565ad97
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
@ -1174,7 +1174,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
P 42c9d8fc5fe4f0250bfa1f977c7cc63e5741408f f585f5d7a0f9bf8c590388654a3638231eba8892 P fc8ca1a87e7127bd28f32fd809aec3e24355fbfa d5513dfa23baa0b0a095aaf17d19aacd30dcef61
R fc3fab040eeffed1a38e67c3557fec70 R 507e4fb477cf51261d2563e52f7cfa77
U drh U drh
Z 657de079eefd6dd1d0e2ef048fcceef3 Z a91c37323943563a6d3bfb60a104e003

View File

@ -1 +1 @@
fc8ca1a87e7127bd28f32fd809aec3e24355fbfa 9515c8344a6743bbb0c6a6e49fb79fb3139090df

View File

@ -4588,6 +4588,7 @@ int sqlite3BtreeMovetoUnpacked(
if( pIdxKey ){ if( pIdxKey ){
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey); xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
pIdxKey->isCorrupt = 0;
assert( pIdxKey->default_rc==1 assert( pIdxKey->default_rc==1
|| pIdxKey->default_rc==0 || pIdxKey->default_rc==0
|| pIdxKey->default_rc==-1 || pIdxKey->default_rc==-1
@ -4711,6 +4712,7 @@ int sqlite3BtreeMovetoUnpacked(
c = xRecordCompare(nCell, pCellKey, pIdxKey, 0); c = xRecordCompare(nCell, pCellKey, pIdxKey, 0);
sqlite3_free(pCellKey); sqlite3_free(pCellKey);
} }
assert( pIdxKey->isCorrupt==0 || c==0 );
if( c<0 ){ if( c<0 ){
lwr = idx+1; lwr = idx+1;
}else if( c>0 ){ }else if( c>0 ){
@ -4720,6 +4722,7 @@ int sqlite3BtreeMovetoUnpacked(
*pRes = 0; *pRes = 0;
rc = SQLITE_OK; rc = SQLITE_OK;
pCur->aiIdx[pCur->iPage] = (u16)idx; pCur->aiIdx[pCur->iPage] = (u16)idx;
if( pIdxKey->isCorrupt ) rc = SQLITE_CORRUPT;
goto moveto_finish; goto moveto_finish;
} }
if( lwr>upr ) break; if( lwr>upr ) break;

View File

@ -248,7 +248,7 @@ static void *memsys5MallocUnsafe(int nByte){
** block. If not, then split a block of the next larger power of ** block. If not, then split a block of the next larger power of
** two in order to create a new free block of size iLogsize. ** two in order to create a new free block of size iLogsize.
*/ */
for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){} for(iBin=iLogsize; iBin<=LOGMAX && mem5.aiFreelist[iBin]<0; iBin++){}
if( iBin>LOGMAX ){ if( iBin>LOGMAX ){
testcase( sqlite3GlobalConfig.xLog!=0 ); testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte); sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);

View File

@ -2130,10 +2130,12 @@ static void tryToClone(struct callback_data *p, const char *zNewDb){
fprintf(stderr, "Cannot create output database: %s\n", fprintf(stderr, "Cannot create output database: %s\n",
sqlite3_errmsg(newDb)); sqlite3_errmsg(newDb));
}else{ }else{
sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0); sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
tryToCloneSchema(p, newDb, "type='table'", tryToCloneData); tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
tryToCloneSchema(p, newDb, "type!='table'", 0); tryToCloneSchema(p, newDb, "type!='table'", 0);
sqlite3_exec(newDb, "COMMIT;", 0, 0, 0); sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
} }
sqlite3_close(newDb); sqlite3_close(newDb);
} }

View File

@ -1635,6 +1635,7 @@ struct UnpackedRecord {
KeyInfo *pKeyInfo; /* Collation and sort-order information */ KeyInfo *pKeyInfo; /* Collation and sort-order information */
u16 nField; /* Number of entries in apMem[] */ u16 nField; /* Number of entries in apMem[] */
i8 default_rc; /* Comparison result if keys are equal */ i8 default_rc; /* Comparison result if keys are equal */
u8 isCorrupt; /* Corruption detected by xRecordCompare() */
Mem *aMem; /* Values */ Mem *aMem; /* Values */
int r1; /* Value to return if (lhs > rhs) */ int r1; /* Value to return if (lhs > rhs) */
int r2; /* Value to return if (rhs < lhs) */ int r2; /* Value to return if (rhs < lhs) */

View File

@ -5990,7 +5990,7 @@ case OP_VOpen: {
#ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VFilter P1 P2 P3 P4 * /* Opcode: VFilter P1 P2 P3 P4 *
** Synopsis: iPlan=r[P3] zPlan='P4' ** Synopsis: iplan=r[P3] zplan='P4'
** **
** P1 is a cursor opened using VOpen. P2 is an address to jump to if ** P1 is a cursor opened using VOpen. P2 is an address to jump to if
** the filtered result set is empty. ** the filtered result set is empty.

View File

@ -213,10 +213,10 @@ void sqlite3VdbeSetVarmask(Vdbe*, int);
#endif #endif
void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*); void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompare(int,const void*,const UnpackedRecord*,int); int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*,int);
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **); UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
typedef int (*RecordCompare)(int,const void*,const UnpackedRecord*,int); typedef int (*RecordCompare)(int,const void*,UnpackedRecord*,int);
RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*); RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
#ifndef SQLITE_OMIT_TRIGGER #ifndef SQLITE_OMIT_TRIGGER

View File

@ -411,7 +411,7 @@ u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
void sqlite3VdbeDeleteAuxData(Vdbe*, int, int); void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *); int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(VdbeCursor*,const UnpackedRecord*,int*); int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *); int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*); int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
int sqlite3VdbeExec(Vdbe*); int sqlite3VdbeExec(Vdbe*);

View File

@ -3407,10 +3407,13 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
** Key1 and Key2 do not have to contain the same number of fields. If all ** Key1 and Key2 do not have to contain the same number of fields. If all
** fields that appear in both keys are equal, then pPKey2->default_rc is ** fields that appear in both keys are equal, then pPKey2->default_rc is
** returned. ** returned.
**
** If database corruption is discovered, set pPKey2->isCorrupt to non-zero
** and return 0.
*/ */
int sqlite3VdbeRecordCompare( int sqlite3VdbeRecordCompare(
int nKey1, const void *pKey1, /* Left key */ int nKey1, const void *pKey1, /* Left key */
const UnpackedRecord *pPKey2, /* Right key */ UnpackedRecord *pPKey2, /* Right key */
int bSkip /* If true, skip the first field */ int bSkip /* If true, skip the first field */
){ ){
u32 d1; /* Offset into aKey[] of next data element */ u32 d1; /* Offset into aKey[] of next data element */
@ -3436,7 +3439,10 @@ int sqlite3VdbeRecordCompare(
}else{ }else{
idx1 = getVarint32(aKey1, szHdr1); idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1; d1 = szHdr1;
if( d1>(unsigned)nKey1 ) return 1; /* Corruption */ if( d1>(unsigned)nKey1 ){
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}
i = 0; i = 0;
} }
@ -3513,7 +3519,8 @@ int sqlite3VdbeRecordCompare(
testcase( (d1+mem1.n)==(unsigned)nKey1 ); testcase( (d1+mem1.n)==(unsigned)nKey1 );
testcase( (d1+mem1.n+1)==(unsigned)nKey1 ); testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
if( (d1+mem1.n) > (unsigned)nKey1 ){ if( (d1+mem1.n) > (unsigned)nKey1 ){
rc = 1; /* Corruption */ pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}else if( pKeyInfo->aColl[i] ){ }else if( pKeyInfo->aColl[i] ){
mem1.enc = pKeyInfo->enc; mem1.enc = pKeyInfo->enc;
mem1.db = pKeyInfo->db; mem1.db = pKeyInfo->db;
@ -3539,7 +3546,8 @@ int sqlite3VdbeRecordCompare(
testcase( (d1+nStr)==(unsigned)nKey1 ); testcase( (d1+nStr)==(unsigned)nKey1 );
testcase( (d1+nStr+1)==(unsigned)nKey1 ); testcase( (d1+nStr+1)==(unsigned)nKey1 );
if( (d1+nStr) > (unsigned)nKey1 ){ if( (d1+nStr) > (unsigned)nKey1 ){
rc = 1; /* Corruption */ pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}else{ }else{
int nCmp = MIN(nStr, pRhs->n); int nCmp = MIN(nStr, pRhs->n);
rc = memcmp(&aKey1[d1], pRhs->z, nCmp); rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
@ -3598,7 +3606,7 @@ int sqlite3VdbeRecordCompare(
*/ */
static int vdbeRecordCompareInt( static int vdbeRecordCompareInt(
int nKey1, const void *pKey1, /* Left key */ int nKey1, const void *pKey1, /* Left key */
const UnpackedRecord *pPKey2, /* Right key */ UnpackedRecord *pPKey2, /* Right key */
int bSkip /* Ignored */ int bSkip /* Ignored */
){ ){
const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F]; const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
@ -3696,7 +3704,7 @@ static int vdbeRecordCompareInt(
*/ */
static int vdbeRecordCompareString( static int vdbeRecordCompareString(
int nKey1, const void *pKey1, /* Left key */ int nKey1, const void *pKey1, /* Left key */
const UnpackedRecord *pPKey2, /* Right key */ UnpackedRecord *pPKey2, /* Right key */
int bSkip int bSkip
){ ){
const u8 *aKey1 = (const u8*)pKey1; const u8 *aKey1 = (const u8*)pKey1;
@ -3717,7 +3725,10 @@ static int vdbeRecordCompareString(
int szHdr = aKey1[0]; int szHdr = aKey1[0];
nStr = (serial_type-12) / 2; nStr = (serial_type-12) / 2;
if( (szHdr + nStr) > nKey1 ) return 0; /* Corruption */ if( (szHdr + nStr) > nKey1 ){
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}
nCmp = MIN( pPKey2->aMem[0].n, nStr ); nCmp = MIN( pPKey2->aMem[0].n, nStr );
res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp); res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
@ -3882,7 +3893,7 @@ idx_rowid_corruption:
*/ */
int sqlite3VdbeIdxKeyCompare( int sqlite3VdbeIdxKeyCompare(
VdbeCursor *pC, /* The cursor to compare against */ VdbeCursor *pC, /* The cursor to compare against */
const UnpackedRecord *pUnpacked, /* Unpacked version of key */ UnpackedRecord *pUnpacked, /* Unpacked version of key */
int *res /* Write the comparison result here */ int *res /* Write the comparison result here */
){ ){
i64 nCellKey = 0; i64 nCellKey = 0;

View File

@ -4328,18 +4328,34 @@ static int whereLoopAddBtree(
) )
){ ){
pNew->iSortIdx = b ? iSortIdx : 0; pNew->iSortIdx = b ? iSortIdx : 0;
/* TUNING: The base cost of an index scan is N + log2(N).
** The log2(N) is for the initial seek to the beginning and the N
** is for the scan itself. */
pNew->rRun = sqlite3LogEstAdd(rSize, rLogSize);
if( m==0 ){ if( m==0 ){
/* TUNING: Cost of a covering index scan is K*(N + log2(N)). /* TUNING: Cost of a covering index scan is K*(N + log2(N)).
** + The extra factor K of between 1.1 and 3.0 that depends ** + The extra factor K of between 1.1 and 3.0 that depends
** on the relative sizes of the table and the index. K ** on the relative sizes of the table and the index. K
** is smaller for smaller indices, thus favoring them. ** is smaller for smaller indices, thus favoring them.
** The upper bound on K (3.0) matches the penalty factor
** on a full table scan that tries to encourage the use of
** indexed lookups over full scans.
*/ */
pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 1 + pNew->rRun += 1 + (15*pProbe->szIdxRow)/pTab->szTabRow;
(15*pProbe->szIdxRow)/pTab->szTabRow;
}else{ }else{
/* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N) /* TUNING: The cost of scanning a non-covering index is multiplied
** which we will simplify to just N*log2(N) */ ** by log2(N) to account for the binary search of the main table
pNew->rRun = rSize + rLogSize; ** that must happen for each row of the index.
** TODO: Should there be a multiplier here, analogous to the 3x
** multiplier for a fulltable scan or covering index scan, to
** further discourage the use of an index scan? Or is the log2(N)
** term sufficient discouragement?
** TODO: What if some or all of the WHERE clause terms can be
** computed without reference to the original table. Then the
** penality should reduce to logK where K is the number of output
** rows.
*/
pNew->rRun += rLogSize;
} }
whereLoopOutputAdjust(pWC, pNew); whereLoopOutputAdjust(pWC, pNew);
rc = whereLoopInsert(pBuilder, pNew); rc = whereLoopInsert(pBuilder, pNew);
@ -4920,7 +4936,7 @@ static i8 wherePathSatisfiesOrderBy(
} }
} }
} /* End the loop over all WhereLoops from outer-most down to inner-most */ } /* End the loop over all WhereLoops from outer-most down to inner-most */
if( obSat==obDone ) return nOrderBy; if( obSat==obDone ) return (i8)nOrderBy;
if( !isOrderDistinct ){ if( !isOrderDistinct ){
for(i=nOrderBy-1; i>0; i--){ for(i=nOrderBy-1; i>0; i--){
Bitmask m = MASKBIT(i) - 1; Bitmask m = MASKBIT(i) - 1;
@ -5041,11 +5057,19 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags, pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
iLoop, pWLoop, &revMask); iLoop, pWLoop, &revMask);
if( isOrdered>=0 && isOrdered<nOrderBy ){ if( isOrdered>=0 && isOrdered<nOrderBy ){
/* TUNING: Estimated cost of sorting cost as roughly N*log(N). /* TUNING: Estimated cost of sorting is N*log(N).
** If some but not all of the columns are in sorted order, then ** If the order-by clause has X terms but only the last Y terms
** scale down the log(N) term. */ ** are out of order, then block-sorting will reduce the sorting
LogEst rScale = sqlite3LogEst((nOrderBy-isOrdered)*100/nOrderBy); ** cost to N*log(N)*log(Y/X). The log(Y/X) term is computed
LogEst rSortCost = nRowEst + estLog(nRowEst) + rScale - 66; ** by rScale.
** TODO: Should the sorting cost get a small multiplier to help
** discourage the use of sorting and encourage the use of index
** scans instead?
*/
LogEst rScale, rSortCost;
assert( nOrderBy>0 );
rScale = sqlite3LogEst((nOrderBy-isOrdered)*100/nOrderBy) - 66;
rSortCost = nRowEst + estLog(nRowEst) + rScale;
/* TUNING: The cost of implementing DISTINCT using a B-TREE is /* TUNING: The cost of implementing DISTINCT using a B-TREE is
** also N*log(N) but it has a larger constant of proportionality. ** also N*log(N) but it has a larger constant of proportionality.
** Multiply by 3.0. */ ** Multiply by 3.0. */
@ -5900,7 +5924,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
for(; k<last; k++, pOp++){ for(; k<last; k++, pOp++){
if( pOp->p1!=pLevel->iTabCur ) continue; if( pOp->p1!=pLevel->iTabCur ) continue;
if( pOp->opcode==OP_Column ){ if( pOp->opcode==OP_Column ){
pOp->opcode = OP_SCopy; pOp->opcode = OP_Copy;
pOp->p1 = pOp->p2 + pTabItem->regResult; pOp->p1 = pOp->p2 + pTabItem->regResult;
pOp->p2 = pOp->p3; pOp->p2 = pOp->p3;
pOp->p3 = 0; pOp->p3 = 0;

View File

@ -47,12 +47,12 @@ do_test 1.2 {
catchsql { catchsql {
SELECT c FROM t1 WHERE a>'abc'; SELECT c FROM t1 WHERE a>'abc';
} }
} {0 {}} } {1 {database disk image is malformed}}
do_test 1.3 { do_test 1.3 {
catchsql { catchsql {
PRAGMA integrity_check PRAGMA integrity_check
} }
} {0 ok} } {1 {database disk image is malformed}}
do_test 1.4 { do_test 1.4 {
catchsql { catchsql {
SELECT c FROM t1 ORDER BY a; SELECT c FROM t1 ORDER BY a;
@ -71,11 +71,6 @@ do_test 2.1 {
catchsql { catchsql {
SELECT rowid FROM t1 WHERE a='abc' and b='xyz123456789XYZ'; SELECT rowid FROM t1 WHERE a='abc' and b='xyz123456789XYZ';
} }
# The following test result is brittle. The point above is to try to } {1 {database disk image is malformed}}
# force a buffer overread by a corrupt database file. If we get an
# incorrect answer from a corrupt database file, that is OK. If the
# result below changes, that just means that "undefined behavior" has
# changed.
} {/0 .*/}
finish_test finish_test

View File

@ -51,7 +51,7 @@ do_test 1.3 {
hexio_write test.db $off FFFF7f02 hexio_write test.db $off FFFF7f02
sqlite3 db test.db sqlite3 db test.db
catchsql { SELECT * FROM t1 WHERE a = 10 } catchsql { SELECT * FROM t1 WHERE a = 10 }
} {0 {}} } {1 {database disk image is malformed}}
do_test 2.0 { do_test 2.0 {
execsql { execsql {

View File

@ -19,6 +19,11 @@ set testprefix wal64k
ifcapable !wal {finish_test ; return } ifcapable !wal {finish_test ; return }
if {$tcl_platform(platform) != "unix"} {
finish_test
return
}
db close db close
test_syscall pagesize 65536 test_syscall pagesize 65536
sqlite3 db test.db sqlite3 db test.db
@ -44,4 +49,3 @@ integrity_check 1.3
db close db close
test_syscall pagesize -1 test_syscall pagesize -1
finish_test finish_test

View File

@ -166,5 +166,18 @@ do_eqp_test whereG-3.4 {
SELECT * FROM a, b WHERE a2=5 AND a1=b1; SELECT * FROM a, b WHERE a2=5 AND a1=b1;
} {/.*SCAN TABLE a.*SEARCH TABLE b USING INDEX .*b_1 .b1=..*/} } {/.*SCAN TABLE a.*SEARCH TABLE b USING INDEX .*b_1 .b1=..*/}
# Ticket [1e64dd782a126f48d78c43a664844a41d0e6334e]:
# Incorrect result in a nested GROUP BY/DISTINCT due to the use of an OP_SCopy
# where an OP_Copy was needed.
#
do_execsql_test whereG-4.0 {
CREATE TABLE t4(x);
INSERT INTO t4 VALUES('right'),('wrong');
SELECT DISTINCT x
FROM (SELECT x FROM t4 GROUP BY x)
WHERE x='right'
ORDER BY x;
} {right}
finish_test finish_test

View File

@ -17,13 +17,7 @@
** **
** ./LogEst ARGS ** ./LogEst ARGS
** **
** Arguments: ** See the showHelp() routine for a description of valid arguments.
**
** 'x' Multiple the top two elements of the stack
** '+' Add the top two elements of the stack
** NUM Convert NUM from integer to LogEst and push onto the stack
** ^NUM Interpret NUM as a LogEst and push onto stack.
**
** Examples: ** Examples:
** **
** To convert 123 from LogEst to integer: ** To convert 123 from LogEst to integer:
@ -97,12 +91,31 @@ static LogEst logEstFromDouble(double x){
return e*10; return e*10;
} }
int isInteger(const char *z){
while( z[0]>='0' && z[0]<='9' ) z++;
return z[0]==0;
}
int isFloat(const char *z){ int isFloat(const char *z){
while( z[0] ){ char c;
if( z[0]=='.' || z[0]=='E' || z[0]=='e' ) return 1; while( ((c=z[0])>='0' && c<='9') || c=='.' || c=='E' || c=='e'
z++; || c=='+' || c=='-' ) z++;
} return z[0]==0;
return 0; }
static void showHelp(const char *zArgv0){
printf("Usage: %s ARGS...\n", zArgv0);
printf("Arguments:\n"
" NUM Convert NUM from integer to LogEst and push onto the stack\n"
" ^NUM Interpret NUM as a LogEst and push onto stack\n"
" x Multiple the top two elements of the stack\n"
" + Add the top two elements of the stack\n"
" dup Dupliate the top element on the stack\n"
" inv Take the reciprocal of the top of stack. N = 1/N.\n"
" log Find the LogEst of the number on top of stack\n"
" nlogn Compute NlogN where N is the top of stack\n"
);
exit(1);
} }
int main(int argc, char **argv){ int main(int argc, char **argv){
@ -111,30 +124,43 @@ int main(int argc, char **argv){
LogEst a[100]; LogEst a[100];
for(i=1; i<argc; i++){ for(i=1; i<argc; i++){
const char *z = argv[i]; const char *z = argv[i];
if( z[0]=='+' ){ if( strcmp(z,"+")==0 ){
if( n>=2 ){ if( n>=2 ){
a[n-2] = logEstAdd(a[n-2],a[n-1]); a[n-2] = logEstAdd(a[n-2],a[n-1]);
n--; n--;
} }
}else if( z[0]=='x' ){ }else if( strcmp(z,"x")==0 ){
if( n>=2 ){ if( n>=2 ){
a[n-2] = logEstMultiply(a[n-2],a[n-1]); a[n-2] = logEstMultiply(a[n-2],a[n-1]);
n--; n--;
} }
}else if( strcmp(z,"dup")==0 ){
if( n>0 ){
a[n] = a[n-1];
n++;
}
}else if( strcmp(z,"log")==0 ){
if( n>0 ) a[n-1] = logEstFromInteger(a[n-1]) - 33;
}else if( strcmp(z,"nlogn")==0 ){
if( n>0 ) a[n-1] += logEstFromInteger(a[n-1]) - 33;
}else if( strcmp(z,"inv")==0 ){
if( n>0 ) a[n-1] = -a[n-1];
}else if( z[0]=='^' ){ }else if( z[0]=='^' ){
a[n++] = atoi(z+1); a[n++] = atoi(z+1);
}else if( isFloat(z) ){ }else if( isInteger(z) ){
a[n++] = logEstFromInteger(atoi(z));
}else if( isFloat(z) && z[0]!='-' ){
a[n++] = logEstFromDouble(atof(z)); a[n++] = logEstFromDouble(atof(z));
}else{ }else{
a[n++] = logEstFromInteger(atoi(z)); showHelp(argv[0]);
} }
} }
for(i=n-1; i>=0; i--){ for(i=n-1; i>=0; i--){
if( a[i]<0 ){ if( a[i]<0 ){
printf("%d (%f)\n", a[i], 1.0/(double)logEstToInt(-a[i])); printf("%5d (%f)\n", a[i], 1.0/(double)logEstToInt(-a[i]));
}else{ }else{
sqlite3_uint64 x = logEstToInt(a[i]+100)*100/1024; sqlite3_uint64 x = logEstToInt(a[i]+100)*100/1024;
printf("%d (%lld.%02lld)\n", a[i], x/100, x%100); printf("%5d (%lld.%02lld)\n", a[i], x/100, x%100);
} }
} }
return 0; return 0;