mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Merge all recent trunk enhancements into the sessions branch.
FossilOrigin-Name: 5f14f34f072921e229bc20a5185c0cdb3f464c04
This commit is contained in:
@ -545,6 +545,9 @@ sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h
|
||||
-o $@ $(TOP)/src/shell.c libsqlite3.la \
|
||||
$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
|
||||
|
||||
sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS)
|
||||
|
||||
mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
|
||||
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
|
||||
$(TLIBS) -rpath "$(libdir)"
|
||||
|
@ -42,8 +42,8 @@ DYNAMIC_SHELL = 0
|
||||
#
|
||||
!IFNDEF NO_WARN
|
||||
!IF $(USE_FULLWARN)!=0
|
||||
NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4152 -wd4189 -wd4206 -wd4210
|
||||
NO_WARN = $(NO_WARN) -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706
|
||||
NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206
|
||||
NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
@ -455,11 +455,13 @@ RCC = $(RCC) -I$(TOP)\ext\session
|
||||
# options are necessary in order to allow debugging symbols to
|
||||
# work correctly with Visual Studio when using the amalgamation.
|
||||
#
|
||||
!IFNDEF MKSQLITE3C_ARGS
|
||||
!IF $(DEBUG)>1
|
||||
MKSQLITE3C_ARGS = --linemacros
|
||||
!ELSE
|
||||
MKSQLITE3C_ARGS =
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
# Define -DNDEBUG to compile without debugging (i.e., for production usage)
|
||||
# Omitting the define will cause extra debugging code to be inserted and
|
||||
@ -1178,6 +1180,9 @@ sqlite3.exe: $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
|
||||
$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c \
|
||||
/link /pdb:sqlite3sh.pdb $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
|
||||
sqldiff.exe: $(TOP)\tool\sqldiff.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) $(TOP)\tool\sqldiff.c sqlite3.c
|
||||
|
||||
mptester.exe: $(TOP)\mptest\mptest.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
|
||||
$(LTLINK) $(SHELL_COMPILE_OPTS) $(TOP)\mptest\mptest.c \
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) $(SHELL_LINK_OPTS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
|
@ -1019,7 +1019,8 @@ static int fts3ContentColumns(
|
||||
const char *zTbl, /* Name of content table */
|
||||
const char ***pazCol, /* OUT: Malloc'd array of column names */
|
||||
int *pnCol, /* OUT: Size of array *pazCol */
|
||||
int *pnStr /* OUT: Bytes of string content */
|
||||
int *pnStr, /* OUT: Bytes of string content */
|
||||
char **pzErr /* OUT: error message */
|
||||
){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
char *zSql; /* "SELECT *" statement on zTbl */
|
||||
@ -1030,6 +1031,9 @@ static int fts3ContentColumns(
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
}
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
|
||||
@ -1281,7 +1285,7 @@ static int fts3InitVtab(
|
||||
if( nCol==0 ){
|
||||
sqlite3_free((void*)aCol);
|
||||
aCol = 0;
|
||||
rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString);
|
||||
rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr);
|
||||
|
||||
/* If a languageid= option was specified, remove the language id
|
||||
** column from the aCol[] array. */
|
||||
|
@ -779,7 +779,6 @@ static int sessionPreupdateEqual(
|
||||
SessionChange *pChange, /* Change to compare to */
|
||||
int op /* Current pre-update operation */
|
||||
){
|
||||
sqlite3 *db = pSession->db;
|
||||
int iCol; /* Used to iterate through columns */
|
||||
u8 *a = pChange->aRecord; /* Cursor used to scan change record */
|
||||
|
||||
|
4
main.mk
4
main.mk
@ -412,6 +412,10 @@ sqlite3$(EXE): $(TOP)/src/shell.c libsqlite3.a sqlite3.h
|
||||
$(TOP)/src/shell.c \
|
||||
libsqlite3.a $(LIBREADLINE) $(TLIBS) $(THREADLIB)
|
||||
|
||||
sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
|
||||
$(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \
|
||||
$(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB)
|
||||
|
||||
mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
|
||||
$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
|
||||
$(TLIBS) $(THREADLIB)
|
||||
|
63
manifest
63
manifest
@ -1,9 +1,9 @@
|
||||
C Merge\sthe\ssessions-diff\sbranch\swith\sthis\sone.
|
||||
D 2015-04-11T17:09:36.697
|
||||
C Merge\sall\srecent\strunk\senhancements\sinto\sthe\ssessions\sbranch.
|
||||
D 2015-04-12T01:33:37.792
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 3083cf0c2bc6618e532b9478ce735bb512322985
|
||||
F Makefile.in 7e23076b9c9dd5c1901c78cf6cdd64d616e5a539
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc ffb3a33f21fcc6f7d4b0cc76a981f62f17c62b24
|
||||
F Makefile.msc 5b2ac9066d9d67427eb98d7e4bf3790c4db51810
|
||||
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
|
||||
F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866
|
||||
F VERSION 319eb1ced4b4d17a67730f2b7b85f15c1346cb60
|
||||
@ -78,7 +78,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c 23bd9d37a777342f5c22a648e9b4b005dde9e58f
|
||||
F ext/fts3/fts3.c 57d863c3bd360e575ecc293570af7c9b0bdd2209
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 394858c12a17740f7a1f6bd372c4606d4425a8d1
|
||||
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
|
||||
@ -161,7 +161,7 @@ F ext/session/sessionC.test 3982f8577b0744c5ce3aaef7cfeb5bd903f17fe4
|
||||
F ext/session/sessionD.test 95903bd6a23dadbda7e192f730dd7dedd2d369ef
|
||||
F ext/session/session_common.tcl 9de0451b6a47218fc16b9ed8876b6238a0a3d88d
|
||||
F ext/session/sessionfault.test bef044d0952c0d62c31c8d2400be72c8684545cc
|
||||
F ext/session/sqlite3session.c 7876b6e614f089158722b66bb05e269ab6bf0f61
|
||||
F ext/session/sqlite3session.c 2266fca2cb730f3c88423725453bb31c7e820583
|
||||
F ext/session/sqlite3session.h d9ebd8d4c5791aafdf18165575c7f2223c09279b
|
||||
F ext/session/test_session.c 037fc25340a918eb2195972fed439d7adf7b5db9
|
||||
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
|
||||
@ -170,7 +170,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 3876195fb0d4a873f643a3ee8ae4dc29b7bbb96b
|
||||
F main.mk 3ffc109d70c73c8c1149d7f9c880e22edb8d6c43
|
||||
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
||||
F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
@ -194,21 +194,21 @@ F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||
F src/btree.c 2caf598165f3608fde8abac2b243826616ce54b7
|
||||
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
|
||||
F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
|
||||
F src/build.c 0419bba592c22f6d00e6d57a2ca7136720d02c1a
|
||||
F src/build.c fa4795bc795077388aa4e746e1b25ef97bc10489
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
F src/complete.c 198a0066ba60ab06fc00fba1998d870a4d575463
|
||||
F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575
|
||||
F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887
|
||||
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
|
||||
F src/delete.c 5075d88557eb4e2a7fdb2b61a96142830d8589b8
|
||||
F src/expr.c d09dac67d53c78880ba31d56e8ba2be3a6490553
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c e0444b61bed271a76840cbe6182df93a9baa3f12
|
||||
F src/fkey.c 3343d551a8d810782257244fb33f2ce191493c39
|
||||
F src/func.c 1414c24c873c48796ad45942257a179a423ba42f
|
||||
F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 4f6df86bbed2d7b59e4601730407876825dd7b71
|
||||
F src/insert.c 7d953730a7b8e6ff5db0d5a372ebc303f85488b7
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
|
||||
@ -221,7 +221,7 @@ F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
|
||||
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
|
||||
F src/mem5.c 61eeb90134f9a5be6c2e68d8daae7628b25953fb
|
||||
F src/memjournal.c 3eb2c0b51adbd869cb6a44780323f05fa904dc85
|
||||
F src/msvc.h e78002098966e39b2fd9915bd70b7bc3ec8398b7
|
||||
F src/msvc.h d9ba56c6851227ab44b3f228a35f3f5772296495
|
||||
F src/mutex.c 19bf9acba69ca2f367c3761080f8a9f0cf4670a8
|
||||
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
|
||||
F src/mutex_noop.c 529bab0743c3321c940f32c3464de494fd38cfa9
|
||||
@ -253,7 +253,7 @@ F src/shell.c c4d839ad62f4986891601a21ce629a760f226682
|
||||
F src/sqlite.h.in 64287a2b3432550264a743addbf4162a692fdd1c
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
|
||||
F src/sqliteInt.h 19c0a189e57a68ae1d971346cb9ac9383fe29692
|
||||
F src/sqliteInt.h f415bc20c6ac85a255f03aa145476655da6f4098
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
|
||||
F src/table.c e7a09215315a978057fb42c640f890160dbcc45e
|
||||
@ -306,26 +306,26 @@ F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
|
||||
F src/tokenize.c a8d270b06e5f709930f7b67cf70a847969cb5bf3
|
||||
F src/trigger.c 25571661fdeae8c7f975ff40ffec205520a3f92f
|
||||
F src/trigger.c 69a91bed7c94e46223e37ffccfeeb35e34b999ac
|
||||
F src/update.c d207deb7a031f698104bee879de0632b611e72dd
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e
|
||||
F src/vacuum.c 9460b9de7b2d4e34b0d374894aa6c8a0632be8ec
|
||||
F src/vdbe.c 503f4f9396e1109bc9ff0fa6ee01c58e12bc782b
|
||||
F src/vdbe.h b434bb75fbec973d18d49225a59833ae39ee2afc
|
||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||
F src/vdbe.c e09d0a7738b0bc469c573d43af501835afa47956
|
||||
F src/vdbe.h 01d8c35cb877faca74331bb690f0327493c2cb50
|
||||
F src/vdbeInt.h 96e4303a96c6f983e36e1fe32657b2c547f5c8f1
|
||||
F src/vdbeapi.c d95f2bb43d01a91d93231cde181811b38182202e
|
||||
F src/vdbeaux.c 3f36b184dbb5ca87b30c7c616d7cef6eb9e74ed6
|
||||
F src/vdbeaux.c 70d414ecc1a345f71a52c7e5e4e1bdfa184081ca
|
||||
F src/vdbeblob.c ab33f9b57cfce7dddb23853090186da614be4846
|
||||
F src/vdbemem.c 149e585645c3f3ef063f2b7251646388cfe3d47d
|
||||
F src/vdbesort.c 919717d7599fa31d343ec28bffd0f9e91a4ff5f6
|
||||
F src/vdbesort.c 5a729a15fb46b1759e13be49a10441172628e593
|
||||
F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010
|
||||
F src/vtab.c 62d49237bd8f3be4863815a39387b0f9897fa5e1
|
||||
F src/vtab.c 9ca557215e8591ceb66e0b7c0a579c6df1e54b2d
|
||||
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
|
||||
F src/wal.c 878c8e1a51cb2ec45c395d26b7d5cd9e1a098e4a
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
|
||||
F src/where.c 85d832efa5ef57de542db7f430b72fecd3af8b38
|
||||
F src/where.c 9952e4749f481707595692f2f13d3ce3b64ffdc8
|
||||
F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@ -523,7 +523,7 @@ F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
|
||||
F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a
|
||||
F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146
|
||||
F test/fkey1.test e1d1fa84cde579185ea01358436839703e415a5b
|
||||
F test/fkey2.test 1db212cda86b0d3ce72714001f7b6381c321341c
|
||||
F test/fkey2.test 223c624e7eccee21e89c98d4d127ac88d774b940
|
||||
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
|
||||
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
|
||||
F test/fkey5.test 56bcb5a6e8b725b17febc267fb041a6695e86853
|
||||
@ -624,7 +624,7 @@ F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
|
||||
F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e
|
||||
F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb
|
||||
F test/fts4check.test 74d77f6cdb768ac49df5afda575cef14ae3d239a
|
||||
F test/fts4content.test 2e7252557d6d24afa101d9ba1de710d6140e6d06
|
||||
F test/fts4content.test abb0c77bc3da3df64fec72e00844d2257a90025d
|
||||
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
|
||||
F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53
|
||||
F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d
|
||||
@ -786,10 +786,10 @@ F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
|
||||
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
|
||||
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
|
||||
F test/notnull.test f8fcf58669ddba79274daa2770d61dfad8274f62
|
||||
F test/null.test a8b09b8ed87852742343b33441a9240022108993
|
||||
F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3
|
||||
F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
|
||||
F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
|
||||
F test/orderby1.test eb246e377612b21a418fbea57047ba8ea88aaa6b
|
||||
F test/orderby1.test 870e150450437d3980badbde3d0166b81d9e33f6
|
||||
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
|
||||
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
|
||||
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
|
||||
@ -1190,7 +1190,7 @@ F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2
|
||||
F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
|
||||
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
|
||||
F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a
|
||||
F test/whereD.test fd9120e262f9da3c45940f52aefeef4d15b904e5
|
||||
F test/whereD.test 9eba1f9b18e5b19a0b0bcaae5e8c037260195f2b
|
||||
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
|
||||
F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
|
||||
F test/whereG.test 69f5ec4b15760a8c860f80e2d55525669390aab3
|
||||
@ -1213,7 +1213,7 @@ F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
|
||||
F test/without_rowid5.test 61256715b686359df48ca1742db50cc7e3e7b862
|
||||
F test/without_rowid6.test db0dbf03c49030aa3c1ba5f618620334bd2baf5f
|
||||
F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda
|
||||
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
|
||||
F test/zeroblob.test fb3c0e4ab172d386954deda24c03f500e121d80d
|
||||
F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
|
||||
F tool/build-all-msvc.bat 72e05bc8deca39a547884485c086b915f50a91ed x
|
||||
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
|
||||
@ -1258,6 +1258,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
||||
F tool/sqldiff.c 51c05cc1435507736b8b5a41a0498016041b3e48
|
||||
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
||||
F tool/symbols.sh c5a617b8c61a0926747a56c65f5671ef8ac0e148
|
||||
@ -1268,7 +1269,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 5342f721e878b52f207731ea57411f3669ae3f3f c4340b2ea2115ad97dcac036f9034e132ab789e5
|
||||
R 93733f2c3fd75be901f1056d40d1b2f2
|
||||
U dan
|
||||
Z 4fa2ba77648737a16f5365f796a8dd77
|
||||
P 805baa57e5d2e97dccddc08eb72f2564df4802e8 e527d96a1e098ade4e9d124b630a8c2ea2ac9b36
|
||||
R 730bdca262b89d29bd7fd3c2449cd70e
|
||||
U drh
|
||||
Z 0af95f43348b30e9069146170d9a1be7
|
||||
|
@ -1 +1 @@
|
||||
805baa57e5d2e97dccddc08eb72f2564df4802e8
|
||||
5f14f34f072921e229bc20a5185c0cdb3f464c04
|
@ -2763,7 +2763,8 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
addr2 = sqlite3VdbeCurrentAddr(v);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
|
||||
sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
|
||||
sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1);
|
||||
sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
|
||||
sqlite3ReleaseTempReg(pParse, regRecord);
|
||||
sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v);
|
||||
@ -3776,7 +3777,6 @@ void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
|
||||
void sqlite3SrcListShiftJoinType(SrcList *p){
|
||||
if( p ){
|
||||
int i;
|
||||
assert( p->a || p->nSrc==0 );
|
||||
for(i=p->nSrc-1; i>0; i--){
|
||||
p->a[i].jointype = p->a[i-1].jointype;
|
||||
}
|
||||
|
@ -269,7 +269,7 @@ int sqlite3_complete(const char *zSql){
|
||||
int sqlite3_complete16(const void *zSql){
|
||||
sqlite3_value *pVal;
|
||||
char const *zSql8;
|
||||
int rc = SQLITE_NOMEM;
|
||||
int rc;
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
rc = sqlite3_initialize();
|
||||
|
@ -1184,7 +1184,8 @@ static Trigger *fkActionTrigger(
|
||||
|
||||
iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
|
||||
assert( iFromCol>=0 );
|
||||
tToCol.z = pIdx ? pTab->aCol[pIdx->aiColumn[i]].zName : "oid";
|
||||
assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) );
|
||||
tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName;
|
||||
tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName;
|
||||
|
||||
tToCol.n = sqlite3Strlen30(tToCol.z);
|
||||
|
48
src/insert.c
48
src/insert.c
@ -1777,6 +1777,7 @@ static int xferOptimization(
|
||||
int onError, /* How to handle constraint errors */
|
||||
int iDbDest /* The database of pDest */
|
||||
){
|
||||
sqlite3 *db = pParse->db;
|
||||
ExprList *pEList; /* The result set of the SELECT */
|
||||
Table *pSrc; /* The table in the FROM clause of SELECT */
|
||||
Index *pSrcIdx, *pDestIdx; /* Source and destination indices */
|
||||
@ -1924,11 +1925,11 @@ static int xferOptimization(
|
||||
** the extra complication to make this rule less restrictive is probably
|
||||
** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
|
||||
*/
|
||||
if( (pParse->db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
|
||||
if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if( (pParse->db->flags & SQLITE_CountRows)!=0 ){
|
||||
if( (db->flags & SQLITE_CountRows)!=0 ){
|
||||
return 0; /* xfer opt does not play well with PRAGMA count_changes */
|
||||
}
|
||||
|
||||
@ -1939,7 +1940,7 @@ static int xferOptimization(
|
||||
#ifdef SQLITE_TEST
|
||||
sqlite3_xferopt_count++;
|
||||
#endif
|
||||
iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema);
|
||||
iDbSrc = sqlite3SchemaToIndex(db, pSrc->pSchema);
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
sqlite3CodeVerifySchema(pParse, iDbSrc);
|
||||
iSrc = pParse->nTab++;
|
||||
@ -1949,14 +1950,18 @@ static int xferOptimization(
|
||||
regRowid = sqlite3GetTempReg(pParse);
|
||||
sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
|
||||
assert( HasRowid(pDest) || destHasUniqueIdx );
|
||||
if( (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */
|
||||
if( (db->flags & SQLITE_Vacuum)==0 && (
|
||||
(pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */
|
||||
|| destHasUniqueIdx /* (2) */
|
||||
|| (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */
|
||||
){
|
||||
)){
|
||||
/* In some circumstances, we are able to run the xfer optimization
|
||||
** only if the destination table is initially empty. This code makes
|
||||
** that determination. Conditions under which the destination must
|
||||
** be empty:
|
||||
** only if the destination table is initially empty. Unless the
|
||||
** SQLITE_Vacuum flag is set, this block generates code to make
|
||||
** that determination. If SQLITE_Vacuum is set, then the destination
|
||||
** table is always empty.
|
||||
**
|
||||
** Conditions under which the destination must be empty:
|
||||
**
|
||||
** (1) There is no INTEGER PRIMARY KEY but there are indices.
|
||||
** (If the destination is not initially empty, the rowid fields
|
||||
@ -1999,6 +2004,7 @@ static int xferOptimization(
|
||||
sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName);
|
||||
}
|
||||
for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
|
||||
u8 useSeekResult = 0;
|
||||
for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){
|
||||
if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
|
||||
}
|
||||
@ -2012,7 +2018,33 @@ static int xferOptimization(
|
||||
VdbeComment((v, "%s", pDestIdx->zName));
|
||||
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
|
||||
if( db->flags & SQLITE_Vacuum ){
|
||||
/* This INSERT command is part of a VACUUM operation, which guarantees
|
||||
** that the destination table is empty. If all indexed columns use
|
||||
** collation sequence BINARY, then it can also be assumed that the
|
||||
** index will be populated by inserting keys in strictly sorted
|
||||
** order. In this case, instead of seeking within the b-tree as part
|
||||
** of every OP_IdxInsert opcode, an OP_Last is added before the
|
||||
** OP_IdxInsert to seek to the point within the b-tree where each key
|
||||
** should be inserted. This is faster.
|
||||
**
|
||||
** If any of the indexed columns use a collation sequence other than
|
||||
** BINARY, this optimization is disabled. This is because the user
|
||||
** might change the definition of a collation sequence and then run
|
||||
** a VACUUM command. In that case keys may not be written in strictly
|
||||
** sorted order. */
|
||||
int i;
|
||||
for(i=0; i<pSrcIdx->nColumn; i++){
|
||||
char *zColl = pSrcIdx->azColl[i];
|
||||
if( zColl && sqlite3_stricmp("BINARY", zColl) ) break;
|
||||
}
|
||||
if( i==pSrcIdx->nColumn ){
|
||||
useSeekResult = OPFLAG_USESEEKRESULT;
|
||||
sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1);
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
|
||||
sqlite3VdbeChangeP5(v, useSeekResult);
|
||||
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#pragma warning(disable : 4055)
|
||||
#pragma warning(disable : 4100)
|
||||
#pragma warning(disable : 4127)
|
||||
#pragma warning(disable : 4130)
|
||||
#pragma warning(disable : 4152)
|
||||
#pragma warning(disable : 4189)
|
||||
#pragma warning(disable : 4206)
|
||||
|
@ -1234,6 +1234,7 @@ struct sqlite3 {
|
||||
#define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */
|
||||
#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */
|
||||
#define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */
|
||||
#define SQLITE_Vacuum 0x08000000 /* Currently in a VACUUM */
|
||||
|
||||
|
||||
/*
|
||||
|
@ -680,7 +680,6 @@ static SrcList *targetSrcList(
|
||||
pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0);
|
||||
if( pSrc ){
|
||||
assert( pSrc->nSrc>0 );
|
||||
assert( pSrc->a!=0 );
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema);
|
||||
if( iDb==0 || iDb>=2 ){
|
||||
sqlite3 *db = pParse->db;
|
||||
|
@ -250,6 +250,8 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
|
||||
** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy
|
||||
** the contents to the temporary database.
|
||||
*/
|
||||
assert( (db->flags & SQLITE_Vacuum)==0 );
|
||||
db->flags |= SQLITE_Vacuum;
|
||||
rc = execExecSql(db, pzErrMsg,
|
||||
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
|
||||
"|| ' SELECT * FROM main.' || quote(name) || ';'"
|
||||
@ -257,6 +259,8 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
|
||||
"WHERE type = 'table' AND name!='sqlite_sequence' "
|
||||
" AND coalesce(rootpage,1)>0"
|
||||
);
|
||||
assert( (db->flags & SQLITE_Vacuum)!=0 );
|
||||
db->flags &= ~SQLITE_Vacuum;
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
|
||||
/* Copy over the sequence table
|
||||
|
@ -2588,7 +2588,7 @@ case OP_MakeRecord: {
|
||||
u64 nData; /* Number of bytes of data space */
|
||||
int nHdr; /* Number of bytes of header space */
|
||||
i64 nByte; /* Data space required for this record */
|
||||
int nZero; /* Number of zero bytes at the end of the record */
|
||||
i64 nZero; /* Number of zero bytes at the end of the record */
|
||||
int nVarint; /* Number of bytes in a varint */
|
||||
u32 serial_type; /* Type field */
|
||||
Mem *pData0; /* First field to be combined into the record */
|
||||
@ -2680,7 +2680,7 @@ case OP_MakeRecord: {
|
||||
if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++;
|
||||
}
|
||||
nByte = nHdr+nData;
|
||||
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
||||
goto too_big;
|
||||
}
|
||||
|
||||
@ -4546,7 +4546,7 @@ case OP_NullRow: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Last P1 P2 * * *
|
||||
/* Opcode: Last P1 P2 P3 * *
|
||||
**
|
||||
** The next use of the Rowid or Column or Prev instruction for P1
|
||||
** will refer to the last entry in the database table or index.
|
||||
@ -4573,6 +4573,7 @@ case OP_Last: { /* jump */
|
||||
pC->nullRow = (u8)res;
|
||||
pC->deferredMoveto = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
pC->seekResult = pOp->p3;
|
||||
#ifdef SQLITE_DEBUG
|
||||
pC->seekOp = OP_Last;
|
||||
#endif
|
||||
|
@ -215,6 +215,7 @@ int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
|
||||
|
||||
void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
|
||||
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
|
||||
int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
|
||||
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
|
||||
|
||||
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
|
||||
|
@ -3587,7 +3587,7 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
|
||||
** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the
|
||||
** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db).
|
||||
*/
|
||||
static int vdbeRecordCompareWithSkip(
|
||||
int sqlite3VdbeRecordCompareWithSkip(
|
||||
int nKey1, const void *pKey1, /* Left key */
|
||||
UnpackedRecord *pPKey2, /* Right key */
|
||||
int bSkip /* If true, skip the first field */
|
||||
@ -3773,7 +3773,7 @@ int sqlite3VdbeRecordCompare(
|
||||
int nKey1, const void *pKey1, /* Left key */
|
||||
UnpackedRecord *pPKey2 /* Right key */
|
||||
){
|
||||
return vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0);
|
||||
return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -3861,7 +3861,7 @@ static int vdbeRecordCompareInt(
|
||||
}else if( pPKey2->nField>1 ){
|
||||
/* The first fields of the two keys are equal. Compare the trailing
|
||||
** fields. */
|
||||
res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
|
||||
res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
|
||||
}else{
|
||||
/* The first fields of the two keys are equal and there are no trailing
|
||||
** fields. Return pPKey2->default_rc in this case. */
|
||||
@ -3909,7 +3909,7 @@ static int vdbeRecordCompareString(
|
||||
res = nStr - pPKey2->aMem[0].n;
|
||||
if( res==0 ){
|
||||
if( pPKey2->nField>1 ){
|
||||
res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
|
||||
res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
|
||||
}else{
|
||||
res = pPKey2->default_rc;
|
||||
}
|
||||
|
231
src/vdbesort.c
231
src/vdbesort.c
@ -291,6 +291,7 @@ struct MergeEngine {
|
||||
** after the thread has finished are not dire. So we don't worry about
|
||||
** memory barriers and such here.
|
||||
*/
|
||||
typedef int (*SorterCompare)(SortSubtask*,int*,const void*,int,const void*,int);
|
||||
struct SortSubtask {
|
||||
SQLiteThread *pThread; /* Background thread, if any */
|
||||
int bDone; /* Set if thread is finished but not joined */
|
||||
@ -298,10 +299,12 @@ struct SortSubtask {
|
||||
UnpackedRecord *pUnpacked; /* Space to unpack a record */
|
||||
SorterList list; /* List for thread to write to a PMA */
|
||||
int nPMA; /* Number of PMAs currently in file */
|
||||
SorterCompare xCompare; /* Compare function to use */
|
||||
SorterFile file; /* Temp file for level-0 PMAs */
|
||||
SorterFile file2; /* Space for other PMAs */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Main sorter structure. A single instance of this is allocated for each
|
||||
** sorter cursor created by the VDBE.
|
||||
@ -328,9 +331,13 @@ struct VdbeSorter {
|
||||
u8 bUseThreads; /* True to use background threads */
|
||||
u8 iPrev; /* Previous thread used to flush PMA */
|
||||
u8 nTask; /* Size of aTask[] array */
|
||||
u8 typeMask;
|
||||
SortSubtask aTask[1]; /* One or more subtasks */
|
||||
};
|
||||
|
||||
#define SORTER_TYPE_INTEGER 0x01
|
||||
#define SORTER_TYPE_TEXT 0x02
|
||||
|
||||
/*
|
||||
** An instance of the following object is used to read records out of a
|
||||
** PMA, in sorted order. The next key to be read is cached in nKey/aKey.
|
||||
@ -742,32 +749,161 @@ static int vdbePmaReaderInit(
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** A version of vdbeSorterCompare() that assumes that it has already been
|
||||
** determined that the first field of key1 is equal to the first field of
|
||||
** key2.
|
||||
*/
|
||||
static int vdbeSorterCompareTail(
|
||||
SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
|
||||
int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
|
||||
const void *pKey1, int nKey1, /* Left side of comparison */
|
||||
const void *pKey2, int nKey2 /* Right side of comparison */
|
||||
){
|
||||
UnpackedRecord *r2 = pTask->pUnpacked;
|
||||
if( *pbKey2Cached==0 ){
|
||||
sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
|
||||
*pbKey2Cached = 1;
|
||||
}
|
||||
return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2,
|
||||
** size nKey2 bytes). Use (pTask->pKeyInfo) for the collation sequences
|
||||
** used by the comparison. Return the result of the comparison.
|
||||
**
|
||||
** Before returning, object (pTask->pUnpacked) is populated with the
|
||||
** unpacked version of key2. Or, if pKey2 is passed a NULL pointer, then it
|
||||
** is assumed that the (pTask->pUnpacked) structure already contains the
|
||||
** unpacked key to use as key2.
|
||||
** If IN/OUT parameter *pbKey2Cached is true when this function is called,
|
||||
** it is assumed that (pTask->pUnpacked) contains the unpacked version
|
||||
** of key2. If it is false, (pTask->pUnpacked) is populated with the unpacked
|
||||
** version of key2 and *pbKey2Cached set to true before returning.
|
||||
**
|
||||
** If an OOM error is encountered, (pTask->pUnpacked->error_rc) is set
|
||||
** to SQLITE_NOMEM.
|
||||
*/
|
||||
static int vdbeSorterCompare(
|
||||
SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
|
||||
int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
|
||||
const void *pKey1, int nKey1, /* Left side of comparison */
|
||||
const void *pKey2, int nKey2 /* Right side of comparison */
|
||||
){
|
||||
UnpackedRecord *r2 = pTask->pUnpacked;
|
||||
if( pKey2 ){
|
||||
if( !*pbKey2Cached ){
|
||||
sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
|
||||
*pbKey2Cached = 1;
|
||||
}
|
||||
return sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
|
||||
}
|
||||
|
||||
/*
|
||||
** A specially optimized version of vdbeSorterCompare() that assumes that
|
||||
** the first field of each key is a TEXT value and that the collation
|
||||
** sequence to compare them with is BINARY.
|
||||
*/
|
||||
static int vdbeSorterCompareText(
|
||||
SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
|
||||
int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
|
||||
const void *pKey1, int nKey1, /* Left side of comparison */
|
||||
const void *pKey2, int nKey2 /* Right side of comparison */
|
||||
){
|
||||
const u8 * const p1 = (const u8 * const)pKey1;
|
||||
const u8 * const p2 = (const u8 * const)pKey2;
|
||||
const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */
|
||||
const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */
|
||||
|
||||
int n1;
|
||||
int n2;
|
||||
int res;
|
||||
|
||||
getVarint32(&p1[1], n1); n1 = (n1 - 13) / 2;
|
||||
getVarint32(&p2[1], n2); n2 = (n2 - 13) / 2;
|
||||
res = memcmp(v1, v2, MIN(n1, n2));
|
||||
if( res==0 ){
|
||||
res = n1 - n2;
|
||||
}
|
||||
|
||||
if( res==0 ){
|
||||
if( pTask->pSorter->pKeyInfo->nField>1 ){
|
||||
res = vdbeSorterCompareTail(
|
||||
pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
|
||||
);
|
||||
}
|
||||
}else{
|
||||
if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
|
||||
res = res * -1;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
** A specially optimized version of vdbeSorterCompare() that assumes that
|
||||
** the first field of each key is an INTEGER value.
|
||||
*/
|
||||
static int vdbeSorterCompareInt(
|
||||
SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
|
||||
int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
|
||||
const void *pKey1, int nKey1, /* Left side of comparison */
|
||||
const void *pKey2, int nKey2 /* Right side of comparison */
|
||||
){
|
||||
const u8 * const p1 = (const u8 * const)pKey1;
|
||||
const u8 * const p2 = (const u8 * const)pKey2;
|
||||
const int s1 = p1[1]; /* Left hand serial type */
|
||||
const int s2 = p2[1]; /* Right hand serial type */
|
||||
const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */
|
||||
const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */
|
||||
int res; /* Return value */
|
||||
|
||||
assert( (s1>0 && s1<7) || s1==8 || s1==9 );
|
||||
assert( (s2>0 && s2<7) || s2==8 || s2==9 );
|
||||
|
||||
if( s1>7 && s2>7 ){
|
||||
res = s1 - s2;
|
||||
}else{
|
||||
if( s1==s2 ){
|
||||
if( (*v1 ^ *v2) & 0x80 ){
|
||||
/* The two values have different signs */
|
||||
res = (*v1 & 0x80) ? -1 : +1;
|
||||
}else{
|
||||
/* The two values have the same sign. Compare using memcmp(). */
|
||||
static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8 };
|
||||
int i;
|
||||
res = 0;
|
||||
for(i=0; i<aLen[s1]; i++){
|
||||
if( (res = v1[i] - v2[i]) ) break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if( s2>7 ){
|
||||
res = +1;
|
||||
}else if( s1>7 ){
|
||||
res = -1;
|
||||
}else{
|
||||
res = s1 - s2;
|
||||
}
|
||||
|
||||
if( res>0 ){
|
||||
if( *v1 & 0x80 ) res = -1;
|
||||
}else if( res<0 ){
|
||||
if( *v2 & 0x80 ) res = +1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( res==0 ){
|
||||
if( pTask->pSorter->pKeyInfo->nField>1 ){
|
||||
res = vdbeSorterCompareTail(
|
||||
pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
|
||||
);
|
||||
}
|
||||
}else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
|
||||
res = res * -1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
** Initialize the temporary index cursor just opened as a sorter cursor.
|
||||
**
|
||||
@ -835,9 +971,13 @@ int sqlite3VdbeSorterInit(
|
||||
pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz);
|
||||
memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo);
|
||||
pKeyInfo->db = 0;
|
||||
if( nField && nWorker==0 ) pKeyInfo->nField = nField;
|
||||
if( nField && nWorker==0 ){
|
||||
pKeyInfo->nXField += (pKeyInfo->nField - nField);
|
||||
pKeyInfo->nField = nField;
|
||||
}
|
||||
pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
|
||||
pSorter->nTask = nWorker + 1;
|
||||
pSorter->iPrev = nWorker-1;
|
||||
pSorter->bUseThreads = (pSorter->nTask>1);
|
||||
pSorter->db = db;
|
||||
for(i=0; i<pSorter->nTask; i++){
|
||||
@ -863,6 +1003,12 @@ int sqlite3VdbeSorterInit(
|
||||
if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if( (pKeyInfo->nField+pKeyInfo->nXField)<13
|
||||
&& (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl)
|
||||
){
|
||||
pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
@ -887,30 +1033,24 @@ static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){
|
||||
*/
|
||||
static void vdbeSortSubtaskCleanup(sqlite3 *db, SortSubtask *pTask){
|
||||
sqlite3DbFree(db, pTask->pUnpacked);
|
||||
pTask->pUnpacked = 0;
|
||||
#if SQLITE_MAX_WORKER_THREADS>0
|
||||
/* pTask->list.aMemory can only be non-zero if it was handed memory
|
||||
** from the main thread. That only occurs SQLITE_MAX_WORKER_THREADS>0 */
|
||||
if( pTask->list.aMemory ){
|
||||
sqlite3_free(pTask->list.aMemory);
|
||||
pTask->list.aMemory = 0;
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
assert( pTask->list.aMemory==0 );
|
||||
vdbeSorterRecordFree(0, pTask->list.pList);
|
||||
}
|
||||
pTask->list.pList = 0;
|
||||
if( pTask->file.pFd ){
|
||||
sqlite3OsCloseFree(pTask->file.pFd);
|
||||
pTask->file.pFd = 0;
|
||||
pTask->file.iEof = 0;
|
||||
}
|
||||
if( pTask->file2.pFd ){
|
||||
sqlite3OsCloseFree(pTask->file2.pFd);
|
||||
pTask->file2.pFd = 0;
|
||||
pTask->file2.iEof = 0;
|
||||
}
|
||||
memset(pTask, 0, sizeof(SortSubtask));
|
||||
}
|
||||
|
||||
#ifdef SQLITE_DEBUG_SORTER_THREADS
|
||||
@ -1090,6 +1230,7 @@ void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){
|
||||
for(i=0; i<pSorter->nTask; i++){
|
||||
SortSubtask *pTask = &pSorter->aTask[i];
|
||||
vdbeSortSubtaskCleanup(db, pTask);
|
||||
pTask->pSorter = pSorter;
|
||||
}
|
||||
if( pSorter->list.aMemory==0 ){
|
||||
vdbeSorterRecordFree(0, pSorter->list.pList);
|
||||
@ -1199,28 +1340,42 @@ static void vdbeSorterMerge(
|
||||
){
|
||||
SorterRecord *pFinal = 0;
|
||||
SorterRecord **pp = &pFinal;
|
||||
void *pVal2 = p2 ? SRVAL(p2) : 0;
|
||||
int bCached = 0;
|
||||
|
||||
while( p1 && p2 ){
|
||||
int res;
|
||||
res = vdbeSorterCompare(pTask, SRVAL(p1), p1->nVal, pVal2, p2->nVal);
|
||||
res = pTask->xCompare(
|
||||
pTask, &bCached, SRVAL(p1), p1->nVal, SRVAL(p2), p2->nVal
|
||||
);
|
||||
|
||||
if( res<=0 ){
|
||||
*pp = p1;
|
||||
pp = &p1->u.pNext;
|
||||
p1 = p1->u.pNext;
|
||||
pVal2 = 0;
|
||||
}else{
|
||||
*pp = p2;
|
||||
pp = &p2->u.pNext;
|
||||
pp = &p2->u.pNext;
|
||||
p2 = p2->u.pNext;
|
||||
if( p2==0 ) break;
|
||||
pVal2 = SRVAL(p2);
|
||||
bCached = 0;
|
||||
}
|
||||
}
|
||||
*pp = p1 ? p1 : p2;
|
||||
*ppOut = pFinal;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the SorterCompare function to compare values collected by the
|
||||
** sorter object passed as the only argument.
|
||||
*/
|
||||
static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){
|
||||
if( p->typeMask==SORTER_TYPE_INTEGER ){
|
||||
return vdbeSorterCompareInt;
|
||||
}else if( p->typeMask==SORTER_TYPE_TEXT ){
|
||||
return vdbeSorterCompareText;
|
||||
}
|
||||
return vdbeSorterCompare;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sort the linked list of records headed at pTask->pList. Return
|
||||
** SQLITE_OK if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if
|
||||
@ -1235,12 +1390,14 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){
|
||||
rc = vdbeSortAllocUnpacked(pTask);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
|
||||
p = pList->pList;
|
||||
pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter);
|
||||
|
||||
aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
|
||||
if( !aSlot ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
p = pList->pList;
|
||||
while( p ){
|
||||
SorterRecord *pNext;
|
||||
if( pList->aMemory ){
|
||||
@ -1454,13 +1611,12 @@ static int vdbeMergeEngineStep(
|
||||
int i; /* Index of aTree[] to recalculate */
|
||||
PmaReader *pReadr1; /* First PmaReader to compare */
|
||||
PmaReader *pReadr2; /* Second PmaReader to compare */
|
||||
u8 *pKey2; /* To pReadr2->aKey, or 0 if record cached */
|
||||
int bCached = 0;
|
||||
|
||||
/* Find the first two PmaReaders to compare. The one that was just
|
||||
** advanced (iPrev) and the one next to it in the array. */
|
||||
pReadr1 = &pMerger->aReadr[(iPrev & 0xFFFE)];
|
||||
pReadr2 = &pMerger->aReadr[(iPrev | 0x0001)];
|
||||
pKey2 = pReadr2->aKey;
|
||||
|
||||
for(i=(pMerger->nTree+iPrev)/2; i>0; i=i/2){
|
||||
/* Compare pReadr1 and pReadr2. Store the result in variable iRes. */
|
||||
@ -1470,8 +1626,8 @@ static int vdbeMergeEngineStep(
|
||||
}else if( pReadr2->pFd==0 ){
|
||||
iRes = -1;
|
||||
}else{
|
||||
iRes = vdbeSorterCompare(pTask,
|
||||
pReadr1->aKey, pReadr1->nKey, pKey2, pReadr2->nKey
|
||||
iRes = pTask->xCompare(pTask, &bCached,
|
||||
pReadr1->aKey, pReadr1->nKey, pReadr2->aKey, pReadr2->nKey
|
||||
);
|
||||
}
|
||||
|
||||
@ -1493,9 +1649,9 @@ static int vdbeMergeEngineStep(
|
||||
if( iRes<0 || (iRes==0 && pReadr1<pReadr2) ){
|
||||
pMerger->aTree[i] = (int)(pReadr1 - pMerger->aReadr);
|
||||
pReadr2 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ];
|
||||
pKey2 = pReadr2->aKey;
|
||||
bCached = 0;
|
||||
}else{
|
||||
if( pReadr1->pFd ) pKey2 = 0;
|
||||
if( pReadr1->pFd ) bCached = 0;
|
||||
pMerger->aTree[i] = (int)(pReadr2 - pMerger->aReadr);
|
||||
pReadr1 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ];
|
||||
}
|
||||
@ -1602,6 +1758,16 @@ int sqlite3VdbeSorterWrite(
|
||||
int bFlush; /* True to flush contents of memory to PMA */
|
||||
int nReq; /* Bytes of memory required */
|
||||
int nPMA; /* Bytes of PMA space required */
|
||||
int t; /* serial type of first record field */
|
||||
|
||||
getVarint32((const u8*)&pVal->z[1], t);
|
||||
if( t>0 && t<10 && t!=7 ){
|
||||
pSorter->typeMask &= SORTER_TYPE_INTEGER;
|
||||
}else if( t>10 && (t & 0x01) ){
|
||||
pSorter->typeMask &= SORTER_TYPE_TEXT;
|
||||
}else{
|
||||
pSorter->typeMask = 0;
|
||||
}
|
||||
|
||||
assert( pSorter );
|
||||
|
||||
@ -1867,10 +2033,12 @@ static void vdbeMergeEngineCompare(
|
||||
}else if( p2->pFd==0 ){
|
||||
iRes = i1;
|
||||
}else{
|
||||
SortSubtask *pTask = pMerger->pTask;
|
||||
int bCached = 0;
|
||||
int res;
|
||||
assert( pMerger->pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */
|
||||
res = vdbeSorterCompare(
|
||||
pMerger->pTask, p1->aKey, p1->nKey, p2->aKey, p2->nKey
|
||||
assert( pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */
|
||||
res = pTask->xCompare(
|
||||
pTask, &bCached, p1->aKey, p1->nKey, p2->aKey, p2->nKey
|
||||
);
|
||||
if( res<=0 ){
|
||||
iRes = i1;
|
||||
@ -2288,6 +2456,11 @@ static int vdbeSorterSetupMerge(VdbeSorter *pSorter){
|
||||
MergeEngine *pMain = 0;
|
||||
#if SQLITE_MAX_WORKER_THREADS
|
||||
sqlite3 *db = pTask0->pSorter->db;
|
||||
int i;
|
||||
SorterCompare xCompare = vdbeSorterGetCompare(pSorter);
|
||||
for(i=0; i<pSorter->nTask; i++){
|
||||
pSorter->aTask[i].xCompare = xCompare;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = vdbeSorterMergeTreeBuild(pSorter, &pMain);
|
||||
|
34
src/vtab.c
34
src/vtab.c
@ -24,6 +24,8 @@
|
||||
struct VtabCtx {
|
||||
VTable *pVTable; /* The virtual table being constructed */
|
||||
Table *pTab; /* The Table object to which the virtual table belongs */
|
||||
VtabCtx *pPrior; /* Parent context (if any) */
|
||||
int bDeclared; /* True after sqlite3_declare_vtab() is called */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -487,15 +489,27 @@ static int vtabCallConstructor(
|
||||
int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
|
||||
char **pzErr
|
||||
){
|
||||
VtabCtx sCtx, *pPriorCtx;
|
||||
VtabCtx sCtx;
|
||||
VTable *pVTable;
|
||||
int rc;
|
||||
const char *const*azArg = (const char *const*)pTab->azModuleArg;
|
||||
int nArg = pTab->nModuleArg;
|
||||
char *zErr = 0;
|
||||
char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
|
||||
char *zModuleName;
|
||||
int iDb;
|
||||
VtabCtx *pCtx;
|
||||
|
||||
/* Check that the virtual-table is not already being initialized */
|
||||
for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){
|
||||
if( pCtx->pTab==pTab ){
|
||||
*pzErr = sqlite3MPrintf(db,
|
||||
"vtable constructor called recursively: %s", pTab->zName
|
||||
);
|
||||
return SQLITE_LOCKED;
|
||||
}
|
||||
}
|
||||
|
||||
zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
|
||||
if( !zModuleName ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@ -516,11 +530,13 @@ static int vtabCallConstructor(
|
||||
assert( xConstruct );
|
||||
sCtx.pTab = pTab;
|
||||
sCtx.pVTable = pVTable;
|
||||
pPriorCtx = db->pVtabCtx;
|
||||
sCtx.pPrior = db->pVtabCtx;
|
||||
sCtx.bDeclared = 0;
|
||||
db->pVtabCtx = &sCtx;
|
||||
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
|
||||
db->pVtabCtx = pPriorCtx;
|
||||
db->pVtabCtx = sCtx.pPrior;
|
||||
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
|
||||
assert( sCtx.pTab==pTab );
|
||||
|
||||
if( SQLITE_OK!=rc ){
|
||||
if( zErr==0 ){
|
||||
@ -536,7 +552,7 @@ static int vtabCallConstructor(
|
||||
memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0]));
|
||||
pVTable->pVtab->pModule = pMod->pModule;
|
||||
pVTable->nRef = 1;
|
||||
if( sCtx.pTab ){
|
||||
if( sCtx.bDeclared==0 ){
|
||||
const char *zFormat = "vtable constructor did not declare schema: %s";
|
||||
*pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
|
||||
sqlite3VtabUnlock(pVTable);
|
||||
@ -706,8 +722,8 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
|
||||
** virtual table module.
|
||||
*/
|
||||
int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
VtabCtx *pCtx;
|
||||
Parse *pParse;
|
||||
|
||||
int rc = SQLITE_OK;
|
||||
Table *pTab;
|
||||
char *zErr = 0;
|
||||
@ -718,11 +734,13 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){
|
||||
pCtx = db->pVtabCtx;
|
||||
if( !pCtx || pCtx->bDeclared ){
|
||||
sqlite3Error(db, SQLITE_MISUSE);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return SQLITE_MISUSE_BKPT;
|
||||
}
|
||||
pTab = pCtx->pTab;
|
||||
assert( (pTab->tabFlags & TF_Virtual)!=0 );
|
||||
|
||||
pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
|
||||
@ -745,7 +763,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||
pParse->pNewTable->nCol = 0;
|
||||
pParse->pNewTable->aCol = 0;
|
||||
}
|
||||
db->pVtabCtx->pTab = 0;
|
||||
pCtx->bDeclared = 1;
|
||||
}else{
|
||||
sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
|
||||
sqlite3DbFree(db, zErr);
|
||||
|
@ -4781,7 +4781,7 @@ static int whereLoopAddBtreeIndex(
|
||||
}else if( eOp & (WO_EQ) ){
|
||||
pNew->wsFlags |= WHERE_COLUMN_EQ;
|
||||
if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1) ){
|
||||
if( iCol>=0 && !IsUniqueIndex(pProbe) ){
|
||||
if( iCol>=0 && pProbe->uniqNotNull==0 ){
|
||||
pNew->wsFlags |= WHERE_UNQ_WANTED;
|
||||
}else{
|
||||
pNew->wsFlags |= WHERE_ONEROW;
|
||||
@ -6241,7 +6241,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
pWInfo->revMask = pFrom->revLoop;
|
||||
}
|
||||
if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
|
||||
&& pWInfo->nOBSat==pWInfo->pOrderBy->nExpr
|
||||
&& pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0
|
||||
){
|
||||
Bitmask revMask = 0;
|
||||
int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy,
|
||||
|
@ -746,10 +746,10 @@ do_test fkey2-10.2.2 {
|
||||
drop_all_tables
|
||||
do_test fkey2-11.1.1 {
|
||||
execsql {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, rowid, _rowid_, oid);
|
||||
CREATE TABLE t2(c, d, FOREIGN KEY(c) REFERENCES t1(a) ON UPDATE CASCADE);
|
||||
|
||||
INSERT INTO t1 VALUES(10, 100);
|
||||
INSERT INTO t1 VALUES(10, 100, 'abc', 'def', 'ghi');
|
||||
INSERT INTO t2 VALUES(10, 100);
|
||||
UPDATE t1 SET a = 15;
|
||||
SELECT * FROM t2;
|
||||
|
@ -48,6 +48,9 @@ ifcapable !fts3 {
|
||||
#
|
||||
# 9.* - Test using content=xxx where xxx is a virtual table.
|
||||
#
|
||||
# 11.* - Test that circular references (e.g. "t1(content=t1)") are
|
||||
# detected.
|
||||
#
|
||||
|
||||
do_execsql_test 1.1.1 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
@ -406,7 +409,7 @@ do_execsql_test 5.1.7 {
|
||||
#
|
||||
do_catchsql_test 6.1.1 {
|
||||
CREATE VIRTUAL TABLE ft7 USING fts4(content=t7);
|
||||
} {1 {vtable constructor failed: ft7}}
|
||||
} {1 {no such table: main.t7}}
|
||||
|
||||
do_execsql_test 6.2.1 {
|
||||
CREATE TABLE t7(one, two);
|
||||
@ -433,7 +436,7 @@ do_execsql_test 6.2.3 {
|
||||
}
|
||||
do_catchsql_test 6.2.4 {
|
||||
SELECT * FROM ft7;
|
||||
} {1 {vtable constructor failed: ft7}}
|
||||
} {1 {no such table: main.t7}}
|
||||
do_execsql_test 6.2.5 {
|
||||
CREATE TABLE t7(x, y);
|
||||
INSERT INTO t7 VALUES('A B', 'B A');
|
||||
@ -622,4 +625,15 @@ do_execsql_test 10.7 {
|
||||
{...c d [e] f g...}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test cases 11.*
|
||||
#
|
||||
reset_db
|
||||
|
||||
do_catchsql_test 11.1 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts4(content=x1);
|
||||
} {1 {vtable constructor called recursively: x1}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
@ -278,6 +278,23 @@ do_test null-8.15 {
|
||||
}
|
||||
} {1}
|
||||
|
||||
do_execsql_test null-9.1 {
|
||||
CREATE TABLE t5(a, b, c);
|
||||
CREATE UNIQUE INDEX t5ab ON t5(a, b);
|
||||
|
||||
INSERT INTO t5 VALUES(1, NULL, 'one');
|
||||
INSERT INTO t5 VALUES(1, NULL, 'i');
|
||||
INSERT INTO t5 VALUES(NULL, 'x', 'two');
|
||||
INSERT INTO t5 VALUES(NULL, 'x', 'ii');
|
||||
}
|
||||
|
||||
do_execsql_test null-9.2 {
|
||||
SELECT * FROM t5 WHERE a = 1 AND b IS NULL;
|
||||
} {1 {} one 1 {} i}
|
||||
|
||||
do_execsql_test null-9.3 {
|
||||
SELECT * FROM t5 WHERE a IS NULL AND b = 'x';
|
||||
} {{} x two {} x ii}
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -463,6 +463,9 @@ do_execsql_test 5.1 {
|
||||
do_execsql_test 5.2 {
|
||||
SELECT 5 UNION ALL SELECT 3 ORDER BY 1
|
||||
} {3 5}
|
||||
do_execsql_test 5.3 {
|
||||
SELECT 986 AS x GROUP BY X ORDER BY X
|
||||
} {986}
|
||||
|
||||
# The following test (originally derived from a single test within fuzz.test)
|
||||
# verifies that a PseudoTable cursor is not closed prematurely in a deeply
|
||||
@ -495,5 +498,34 @@ do_execsql_test 7.0 {
|
||||
SELECT * FROM t7 WHERE a=?1 ORDER BY rowid;
|
||||
} {~/ORDER BY/}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test a partial sort large enough to cause the sorter to spill data
|
||||
# to disk.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 8.0 {
|
||||
PRAGMA cache_size = 5;
|
||||
CREATE TABLE t1(a, b);
|
||||
CREATE INDEX i1 ON t1(a);
|
||||
}
|
||||
|
||||
do_eqp_test 8.1 {
|
||||
SELECT * FROM t1 ORDER BY a, b;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 USING INDEX i1}
|
||||
0 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
|
||||
}
|
||||
|
||||
do_execsql_test 8.2 {
|
||||
WITH cnt(i) AS (
|
||||
SELECT 1 UNION ALL SELECT i+1 FROM cnt WHERE i<10000
|
||||
)
|
||||
INSERT INTO t1 SELECT i%2, randomblob(500) FROM cnt;
|
||||
}
|
||||
|
||||
do_test 8.3 {
|
||||
db eval { SELECT * FROM t1 ORDER BY a, b } { incr res $a }
|
||||
set res
|
||||
} 5000
|
||||
|
||||
finish_test
|
||||
|
@ -129,11 +129,11 @@ do_execsql_test 3.0 {
|
||||
|
||||
do_searchcount_test 3.1 {
|
||||
SELECT a, b FROM t3 WHERE (a=1 AND b='one') OR (a=2 AND b='two')
|
||||
} {1 one 2 two search 2}
|
||||
} {1 one 2 two search 4}
|
||||
|
||||
do_searchcount_test 3.2 {
|
||||
SELECT a, c FROM t3 WHERE (a=1 AND b='one') OR (a=2 AND b='two')
|
||||
} {1 i 2 ii search 4}
|
||||
} {1 i 2 ii search 6}
|
||||
|
||||
do_searchcount_test 3.4.1 {
|
||||
SELECT y FROM t4 WHERE x='a'
|
||||
@ -142,24 +142,24 @@ do_searchcount_test 3.4.2 {
|
||||
SELECT a, b FROM t3 WHERE
|
||||
(a=1 AND b=(SELECT y FROM t4 WHERE x='a'))
|
||||
OR (a=2 AND b='two')
|
||||
} {1 one 2 two search 4}
|
||||
} {1 one 2 two search 6}
|
||||
do_searchcount_test 3.4.3 {
|
||||
SELECT a, b FROM t3 WHERE
|
||||
(a=2 AND b='two')
|
||||
OR (a=1 AND b=(SELECT y FROM t4 WHERE x='a'))
|
||||
} {2 two 1 one search 4}
|
||||
} {2 two 1 one search 6}
|
||||
do_searchcount_test 3.4.4 {
|
||||
SELECT a, b FROM t3 WHERE
|
||||
(a=2 AND b=(SELECT y FROM t4 WHERE x='b'))
|
||||
OR (a=1 AND b=(SELECT y FROM t4 WHERE x='a'))
|
||||
} {2 two 1 one search 6}
|
||||
} {2 two 1 one search 8}
|
||||
|
||||
do_searchcount_test 3.5.1 {
|
||||
SELECT a, b FROM t3 WHERE (a=1 AND b='one') OR rowid=4
|
||||
} {1 one 2 two search 2}
|
||||
} {1 one 2 two search 3}
|
||||
do_searchcount_test 3.5.2 {
|
||||
SELECT a, c FROM t3 WHERE (a=1 AND b='one') OR rowid=4
|
||||
} {1 i 2 ii search 2}
|
||||
} {1 i 2 ii search 3}
|
||||
|
||||
# Ticket [d02e1406a58ea02d] (2012-10-04)
|
||||
# LEFT JOIN with an OR in the ON clause causes segfault
|
||||
|
@ -255,5 +255,14 @@ do_test zeroblob-9.8 {
|
||||
db eval {SELECT zeroblob(2) IN (zeroblob(2))}
|
||||
} {1}
|
||||
|
||||
# Oversized zeroblob records
|
||||
#
|
||||
do_test zeroblob-10.1 {
|
||||
db eval {
|
||||
CREATE TABLE t10(a,b,c);
|
||||
}
|
||||
catchsql {INSERT INTO t10 VALUES(zeroblob(1e9),zeroblob(1e9),zeroblob(1e9))}
|
||||
} {1 {string or blob too big}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
1085
tool/sqldiff.c
Normal file
1085
tool/sqldiff.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user