Merge the latest trunk changes into the sessions branch.

FossilOrigin-Name: aa62d6881b5aae64e15dbae70ce8e77bcc2a9f0b
This commit is contained in:
drh 2012-08-25 01:21:36 +00:00
commit 310874ca00
36 changed files with 772 additions and 198 deletions

View File

@ -39,6 +39,14 @@ NO_TCL = 0
#
SYMBOLS = 1
# Set this to non-0 to use the SQLite debugging heap subsystem.
#
MEMDEBUG = 0
# Set this to non-0 to use the Win32 native heap subsystem.
#
WIN32HEAP = 0
# Set this to one of the following values to enable various debugging
# features. Each level includes the debugging options from the previous
# levels. Currently, the recognized values for DEBUG are:
@ -76,7 +84,7 @@ LD = link.exe
# For example, to use the x86 compiler when cross-compiling for x64, a command
# line similar to the following could be used (all on one line):
#
# nmake /f Makefile.msc
# nmake /f Makefile.msc sqlite3.dll
# "NCC=""%VCINSTALLDIR%\bin\cl.exe"""
# USE_NATIVE_LIBPATHS=1
#
@ -200,9 +208,16 @@ TCC = $(TCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
BCC = $(BCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
#
# Use native Win32 heap instead of malloc/free?
# Use the SQLite debugging heap subsystem?
#
# TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
!IF $(MEMDEBUG)!=0
TCC = $(TCC) -DSQLITE_MEMDEBUG=1
#
# Use native Win32 heap subsystem instead of malloc/free?
#
!ELSEIF $(WIN32HEAP)!=0
TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
#
# Validate the heap on every call into the native Win32 heap subsystem?
@ -210,6 +225,7 @@ BCC = $(BCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
!IF $(DEBUG)>2
TCC = $(TCC) -DSQLITE_WIN32_MALLOC_VALIDATE=1
!ENDIF
!ENDIF
# The locations of the Tcl header and library files. Also, the library that
# non-stubs enabled programs using Tcl must link against. These variables

View File

@ -4436,6 +4436,7 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc);
/* Determine which, if any, tokens in the expression should be deferred. */
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){
Fts3TokenAndCost *aTC;
Fts3Expr **apOr;
@ -4466,6 +4467,7 @@ static int fts3EvalStart(Fts3Cursor *pCsr){
sqlite3_free(aTC);
}
}
#endif
fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc);
return rc;
@ -4849,6 +4851,7 @@ static int fts3EvalTestExpr(
break;
default: {
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
if( pCsr->pDeferred
&& (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred)
){
@ -4860,7 +4863,9 @@ static int fts3EvalTestExpr(
*pRc = fts3EvalDeferredPhrase(pCsr, pPhrase);
bHit = (pPhrase->doclist.pList!=0);
pExpr->iDocid = pCsr->iPrevId;
}else{
}else
#endif
{
bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
}
break;

View File

@ -427,10 +427,20 @@ int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*);
int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **);
int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **);
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *);
int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int);
int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *);
void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *);
int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
#else
# define sqlite3Fts3FreeDeferredTokens(x)
# define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK
# define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK
# define sqlite3Fts3FreeDeferredDoclists(x)
# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK
#endif
void sqlite3Fts3SegmentsClose(Fts3Table *);
int sqlite3Fts3MaxLevel(Fts3Table *, int *);
@ -539,8 +549,6 @@ int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **);
int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *);
int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr);
int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *);
/* fts3_unicode2.c (functions generated by parsing unicode text files) */
#ifdef SQLITE_ENABLE_FTS4_UNICODE61
int sqlite3FtsUnicodeFold(int, int);

View File

@ -5046,6 +5046,7 @@ static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
return rc;
}
#ifndef SQLITE_DISABLE_FTS4_DEFERRED
/*
** Delete all cached deferred doclists. Deferred doclists are cached
** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function.
@ -5183,6 +5184,7 @@ int sqlite3Fts3DeferToken(
return SQLITE_OK;
}
#endif
/*
** SQLite value pRowid contains the rowid of a row that may or may not be

View File

@ -1,9 +1,9 @@
C Merge\sall\sthe\slatest\strunk\schanges\sinto\sthe\ssessions\sbranch.
D 2012-08-15T16:21:55.837
C Merge\sthe\slatest\strunk\schanges\sinto\sthe\ssessions\sbranch.
D 2012-08-25T01:21:36.221
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in abd5c10d21d1395f140d9e50ea999df8fa4d6376
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc 49411436c99bf768dcd1cc749a52d7b071803e05
F Makefile.msc 938096d88105a3d102a04186cd5470a4e34a021d
F Makefile.vxworks 879f034a64062a364b21000266bbd5bc6e0c19b9
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
F VERSION a71848df48082f1d6585d4b0819d530fc455485d
@ -55,9 +55,9 @@ 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 bb3107c0e420ea2e26e57050e84cdf0aeaafcd4f
F ext/fts3/fts3.c ab90126ee0163539d21d0618d22afa2eb645f7e2
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 81115435f79248ac09017bc665aae27b410d651f
F ext/fts3/fts3Int.h 1e58825246b56259267382d2f9902774c049460a
F ext/fts3/fts3_aux.c 5205182bd8f372782597888156404766edf5781e
F ext/fts3/fts3_expr.c dbc7ba4c3a6061adde0f38ed8e9b349568299551
F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914
@ -72,7 +72,7 @@ F ext/fts3/fts3_tokenizer.h 66dec98e365854b6cd2d54f1a96bb6d428fc5a68
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
F ext/fts3/fts3_unicode.c 49e36e6ba59f79e6bd6a8bfe434570fe48d20559
F ext/fts3/fts3_unicode2.c a863f05f758af36777dffc2facc898bc73fec896
F ext/fts3/fts3_write.c 794438f904cdf4516b258e530c0065efadb7b9b5
F ext/fts3/fts3_write.c f40042ba5602c58bdd94bd1b9e00205fb73d37cd
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3view.c 6cfc5b67a5f0e09c0d698f9fd012c784bfaa9197
@ -135,18 +135,18 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 5b31b24d6814b11de763debf342c8cd0a15a4910
F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 82b6fcbec3101ff951f47797f407d5eb5d06fa44
F src/btree.c 32dc63ef18c6a8d448c37c030ced70cf23ccad75
F src/btree.h 4aee02e879211bfcfd3f551769578d2e940ab6c2
F src/btreeInt.h 4e5c2bd0f9b36b2a815a6d84f771a61a65830621
F src/build.c 0f6b40ad6211dcaba6159d0f9a297f0704f22142
F src/build.c 196734374128023e414a818f2051d836badb3526
F src/callback.c 0cb4228cdcd827dcc5def98fb099edcc9142dbcd
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 500d019da966631ad957c37705642be87524463b
F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4
F src/delete.c 32041c65dc05a94914cf979fad7b82bc8a963fe9
F src/expr.c e2927abf9c69ce4ff9a931bd201946961c34819a
F src/delete.c 38f7517f76c61b971a51c91cc343e77897ef6a12
F src/expr.c 217840a107dcc1e5dbb57cea311daad04bedbb9a
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 657212460bf5cfd3ae607d12ea62092844c227b5
F src/fkey.c 9c77d842dc9961d92a06a65abb80c64ef1750296
F src/func.c 18dfedfb857e100b05755a1b12e88b389f957879
F src/global.c 4cfdca5cb0edd33c4d021baec4ede958cb2c793b
F src/hash.c a4031441741932da9e7a65bee2b36b5d0e81c073
@ -160,7 +160,7 @@ F src/loadext.c f20382fbaeec832438a1ba7797bee3d3c8a6d51d
F src/main.c 1f15146d32b183d45fd0d41e8370a326c5d647ac
F src/malloc.c fe085aa851b666b7c375c1ff957643dc20a04bf6
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c b3677415e69603d6a0e7c5410a1b3731d55beda1
F src/mem1.c 437c7c4af964895d4650f29881df63535caaa1fa
F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
F src/mem5.c c2c63b7067570b00bf33d751c39af24182316f7f
@ -174,8 +174,8 @@ F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
F src/os.c e1acdc09ff3ac2412945cca9766e2dcf4675f31c
F src/os.h 027491c77d2404c0a678bb3fb06286f331eb9b57
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_unix.c d7c96b5d140f550f07345870112fae5d7ef99757
F src/os_win.c 370c6f3399e3cd9f14343fb7dc4b2bbe8619d3bf
F src/os_unix.c b5149a3343a6acd6c9df4e3acf5085a6501c1f68
F src/os_win.c 88f8cc4ffdbb47e0f8f8b60110fcf90e461c5fb4
F src/pager.c e381c118b77dc22021a1a59d3fec24815e91df78
F src/pager.h 8b8c9bc065a3c66769df8724dfdf492ee1aab3c5
F src/parse.y f29df90bd3adc64b33114ab1de9fb7768fcf2099
@ -186,18 +186,18 @@ F src/pragma.c 97f9357f0e7e5fb46a2519f14539550aa07db49f
F src/prepare.c 33291b83cca285718048d219c67b8298501fa3a5
F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c b3c70ab28cac60de33684c9aa9e5138dcf71d6dd
F src/resolve.c 9e28280ec98035f31900fdd1db01f86f68ca6c32
F src/rowset.c f6a49f3e9579428024662f6e2931832511f831a1
F src/select.c a365da6d7a6d7d8a10ad60ca71837ab5e9369466
F src/select.c a9d68e04f07348038ac279f3316ee8f8e146f59a
F src/shell.c 076e1c90d594644f36027c8ecff9a392cf2d3a06
F src/sqlite.h.in f0bc4a3e082cda4e52ce74e96dc47043ec3c3e9b
F src/sqlite.h.in 6bd48b850e66652823e0f0bdac857a3a3afbfb16
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
F src/sqliteInt.h 23284c2be677c1fb3c14051cd67427077825e8ee
F src/sqliteInt.h 15ae668e04d1f39aa40a45a14a33084435d984d7
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 35939e7e03abf1b7577ce311f48f682c40de3208
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c e4feb5698ee09f8b32ee40baa1d3577871125042
F src/test1.c fc2acf0a2db517c8d19e5e55bda8e1237db77378
F src/test1.c 3d70f7c5987f186884cfebbfa7151a7d3d67d86e
F src/test2.c 4178056dd1e7d70f954ad8a1e3edb71a2a784daf
F src/test3.c 3c3c2407fa6ec7a19e24ae23f7cb439d0275a60d
F src/test4.c d1e5a5e904d4b444cf572391fdcb017638e36ff7
@ -210,7 +210,7 @@ F src/test_async.c 0612a752896fad42d55c3999a5122af10dcf22ad
F src/test_autoext.c 30e7bd98ab6d70a62bb9ba572e4c7df347fe645e
F src/test_backup.c c129c91127e9b46e335715ae2e75756e25ba27de
F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16
F src/test_config.c aa0f42add3ea63920a8b7d1869be4c9b4106bdaa
F src/test_config.c 1ffddfdfa5a73e7fb497e8c89c22754bbc949c81
F src/test_demovfs.c 20a4975127993f4959890016ae9ce5535a880094
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_func.c 3a8dd37c08ab43b76d38eea2836e34a3897bf170
@ -222,7 +222,7 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
F src/test_journal.c f5c0a05b7b3d5930db769b5ee6c3766dc2221a64
F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
F src/test_malloc.c 3f5903a1528fd32fe4c472a3bd0259128d8faaef
F src/test_multiplex.c 66dcfca001ee22f04ef31ad353772ed05a017e53
F src/test_multiplex.c ac0fbc1748e5b86a41a1d7a84654fae0d53a881d
F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d
F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
F src/test_onefile.c 0396f220561f3b4eedc450cef26d40c593c69a25
@ -233,7 +233,7 @@ F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb
F src/test_rtree.c aba603c949766c4193f1068b91c787f57274e0d9
F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
F src/test_server.c 2f99eb2837dfa06a4aacf24af24c6affdf66a84f
F src/test_spellfix.c 3a260d237fabbf5884389aa8c0e516b4e61ab98a
F src/test_spellfix.c fa83c9b4c4bdd1d41be4ad1e9241bf5a4fc9190f
F src/test_stat.c d1569c7a4839f13e80187e2c26b2ab4da2d03935
F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
F src/test_syscall.c a992d8c80ea91fbf21fb2dd570db40e77dd7e6ae
@ -245,7 +245,7 @@ F src/test_wholenumber.c 3d2b9ed1505c40ad5c5ca2ad16ae7a289d6cc251
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c 1e86210d3976717a19238ea7b047fac481fe8c12
F src/trigger.c ee7e178fb9188f44b532cebd449a7c1df90fb684
F src/update.c 89de085a0bf4da448472029d0420a2b1cf1824ee
F src/update.c abb0fcabe551dae0a133fd2a4370b5a8c23b1831
F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
F src/util.c 0af2e515dc0dabacec931bca39525f6c3f1c5455
F src/vacuum.c 587a52bb8833d7ac15af8916f25437e2575028bd
@ -261,10 +261,11 @@ F src/vdbetrace.c 8bd5da325fc90f28464335e4cc4ad1407fe30835
F src/vtab.c bb8ea3a26608bb1357538a5d2fc72beba6638998
F src/wal.c 9294df6f96aae5909ae1a9b733fd1e1b4736978b
F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c 24c7494d8875ead994b4dfe5461340c27fd424ca
F src/walker.c 3d75ba73de15e0f8cd0737643badbeb0e002f07b
F src/where.c 9a28820fb0ead5674d5b45dfdb32aef913fe40c3
F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 0be144b453e0622a085fae8665c32f5676708e00
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 52fc8dee494092031a556911d404ca30a749a30b
F test/alter.test 57d96ec9b320bd07af77567034488dcb6642c748
@ -476,7 +477,7 @@ F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8
F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
F test/fts3ao.test e7b80272efcced57d1d087a9da5c690dd7c21fd9
F test/fts3atoken.test fb398ab50aa232489e2a17f9b29d7ad3a3885f36
F test/fts3auto.test b39f3f51227aea145eae6638690355dbdf9abf18
F test/fts3auto.test 74315a7377403a57ba82a652a33704197fe1e4be
F test/fts3aux1.test 0b02743955d56fc0d4d66236a26177bd1b726de0
F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
@ -486,8 +487,8 @@ F test/fts3corrupt.test 7b0f91780ca36118d73324ec803187208ad33b32
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
F test/fts3d.test bf640d79722b720fa1c81834c48cdaa45d531b1a
F test/fts3defer.test 6c2707be1b05b9790ba8ff91d3391d5fb425269e
F test/fts3defer2.test 35867d33ba6db03f6c73bd6f5fc333ae14f68c81
F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
F test/fts3defer2.test 83f8744407b7663e36716a9066302d53d49ddf8b
F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
F test/fts3expr.test 5e745b2b6348499d9ef8d59015de3182072c564c
@ -496,7 +497,7 @@ F test/fts3fault.test cb72dccb0a3b9f730f16c5240f3fcb9303eb1660
F test/fts3fault2.test 3198eef2804deea7cac8403e771d9cbcb752d887
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
F test/fts3malloc.test b86ea33db9e8c58c0c2f8027a9fcadaf6a1568be
F test/fts3matchinfo.test 6507fe1c342e542300d65ea637d4110eccf894e6
F test/fts3matchinfo.test 15edde2c4d373d60449658176af7164d622a62f0
F test/fts3near.test 2e318ee434d32babd27c167142e2b94ddbab4844
F test/fts3prefix.test b36d4f00b128a51e7b386cc013a874246d9d7dc1
F test/fts3prefix2.test 477ca96e67f60745b7ac931cfa6e9b080c562da5
@ -505,7 +506,7 @@ F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
F test/fts3shared.test 8bb266521d7c5495c0ae522bb4d376ad5387d4a2
F test/fts3snippet.test 8e956051221a34c7daeb504f023cb54d5fa5a8b2
F test/fts3sort.test 95be0b19d7e41c44b29014f13ea8bddd495fd659
F test/fts4aa.test 6e7f90420b837b2c685f3bcbe84c868492d40a68
F test/fts4aa.test 95f448fb02c4a976968b08d1b4ce134e720946ae
F test/fts4check.test 66fa274cab2b615f2fb338b257713aba8fad88a8
F test/fts4content.test 17b2360f7d1a9a7e5aa8022783f5c5731b6dfd4f
F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7
@ -670,7 +671,7 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rdonly.test c267d050a1d9a6a321de502b737daf28821a518d
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a
F test/releasetest.tcl 4014e2bfb93f276d82a604e7a5eda62c129916c9
F test/releasetest.tcl e48fd8e0e8abad89f30e08620790533ae4e02010
F test/rollback.test a1b4784b864331eae8b2a98c189efa2a8b11ff07
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test e58e0acef38b527ed1b0b70d3ada588f804af287
@ -731,7 +732,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/spellfix.test 8bdb52dc612711660cfb64540b11830f21827983
F test/spellfix.test 4e339920585e7555660bd3b11cf338af82c656ae
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
F test/stat.test 08e8185b3fd5b010c90d7ad82b9dd4ea1cbf14b0
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
@ -977,19 +978,21 @@ F test/where9.test ae98dc22ef9b6f2bc81e9f164e41b38faa9bda06
F test/whereA.test 24c234263c8fe358f079d5e57d884fb569d2da0a
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test 13ff5ec0dba407c0e0c075980c75b3275a6774e5
F test/whereD.test 304ccbe3c77e0d0764f37c91d43b8c4792a5e02f
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
F test/win32lock.test b2a539e85ae6b2d78475e016a9636b4451dc7fb9
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
F test/zerodamage.test 0de750389990b1078bab203c712dc3fefd1d8b82
F tool/build-all-msvc.bat 1a18aa39983ae7354d834bc55a850a54fc007576 x
F tool/build-shell.sh b64a481901fc9ffe5ca8812a2a9255b6cfb77381
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/lemon.c 8b7afc12a6671e3a932a5209a9e64abbfbd0f025
F tool/lemon.c 680980c7935bfa1edec20c804c9e5ba4b1dd96f5
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
F tool/mkkeywordhash.c bb52064aa614e1426445e4b2b9b00eeecd23cc79
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
@ -1023,7 +1026,7 @@ F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
F tool/win/sqlite.vsix 67d8a99aceb56384a81b3f30d6c71743146d2cc9
P 47f8f0711d63ef4166db9115db44b166959df14c 772d0de3f311f2035f8a42f01371c96c9fa587ce
R e864d66a36e838c2faa41d39d7a05218
P fc07a4795e027108674d1d41eb4350df629ddc8b 62678be3df35cdcb09172ba8c860f7b73517f1ea
R 664d1e095b40f8d8d9f8fe9cfeed9474
U drh
Z abda2788c852df70f4e42cf73ff52089
Z 3f5ea055e7eaa711939d3a78f8dfab8c

View File

@ -1 +1 @@
fc07a4795e027108674d1d41eb4350df629ddc8b
aa62d6881b5aae64e15dbae70ce8e77bcc2a9f0b

View File

@ -1461,7 +1461,7 @@ static int btreeInitPage(MemPage *pPage){
size = get2byte(&data[pc+2]);
if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){
/* Free blocks must be in ascending order. And the last byte of
** the free-block must lie on the database page. */
** the free-block must lie on the database page. */
return SQLITE_CORRUPT_BKPT;
}
nFree = nFree + size;
@ -2635,7 +2635,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
pBt->nTransaction++;
#ifndef SQLITE_OMIT_SHARED_CACHE
if( p->sharable ){
assert( p->lock.pBtree==p && p->lock.iTable==1 );
assert( p->lock.pBtree==p && p->lock.iTable==1 );
p->lock.eLock = READ_LOCK;
p->lock.pNext = pBt->pLock;
pBt->pLock = &p->lock;

View File

@ -534,7 +534,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
if( !db || db->pnBytesFreed==0 ){
char *zName = pIndex->zName;
TESTONLY ( Index *pOld = ) sqlite3HashInsert(
&pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0
&pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0
);
assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) );
assert( pOld==pIndex || pOld==0 );

View File

@ -378,7 +378,7 @@ void sqlite3DeleteFrom(
*/
sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
pWInfo = sqlite3WhereBegin(
pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK
pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK, 0
);
if( pWInfo==0 ) goto delete_from_cleanup;
regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, 0);

View File

@ -3123,9 +3123,12 @@ void sqlite3ExplainExpr(Vdbe *pOut, Expr *pExpr){
}else{
pFarg = pExpr->x.pList;
}
sqlite3ExplainPrintf(pOut, "%sFUNCTION:%s(",
op==TK_AGG_FUNCTION ? "AGG_" : "",
pExpr->u.zToken);
if( op==TK_AGG_FUNCTION ){
sqlite3ExplainPrintf(pOut, "AGG_FUNCTION%d:%s(",
pExpr->op2, pExpr->u.zToken);
}else{
sqlite3ExplainPrintf(pOut, "FUNCTION:%s(", pExpr->u.zToken);
}
if( pFarg ){
sqlite3ExplainExprList(pOut, pFarg);
}
@ -3816,38 +3819,60 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB){
}
/*
** This is the expression callback for sqlite3FunctionUsesOtherSrc().
**
** Determine if an expression references any table other than one of the
** tables in pWalker->u.pSrcList and abort if it does.
** An instance of the following structure is used by the tree walker
** to count references to table columns in the arguments of an
** aggregate function, in order to implement the
** sqlite3FunctionThisSrc() routine.
*/
static int exprUsesOtherSrc(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){
struct SrcCount {
SrcList *pSrc; /* One particular FROM clause in a nested query */
int nThis; /* Number of references to columns in pSrcList */
int nOther; /* Number of references to columns in other FROM clauses */
};
/*
** Count the number of references to columns.
*/
static int exprSrcCount(Walker *pWalker, Expr *pExpr){
/* The NEVER() on the second term is because sqlite3FunctionUsesThisSrc()
** is always called before sqlite3ExprAnalyzeAggregates() and so the
** TK_COLUMNs have not yet been converted into TK_AGG_COLUMN. If
** sqlite3FunctionUsesThisSrc() is used differently in the future, the
** NEVER() will need to be removed. */
if( pExpr->op==TK_COLUMN || NEVER(pExpr->op==TK_AGG_COLUMN) ){
int i;
SrcList *pSrc = pWalker->u.pSrcList;
struct SrcCount *p = pWalker->u.pSrcCount;
SrcList *pSrc = p->pSrc;
for(i=0; i<pSrc->nSrc; i++){
if( pExpr->iTable==pSrc->a[i].iCursor ) return WRC_Continue;
if( pExpr->iTable==pSrc->a[i].iCursor ) break;
}
if( i<pSrc->nSrc ){
p->nThis++;
}else{
p->nOther++;
}
return WRC_Abort;
}else{
return WRC_Continue;
}
return WRC_Continue;
}
/*
** Determine if any of the arguments to the pExpr Function references
** any SrcList other than pSrcList. Return true if they do. Return
** false if pExpr has no argument or has only constant arguments or
** only references tables named in pSrcList.
** Determine if any of the arguments to the pExpr Function reference
** pSrcList. Return true if they do. Also return true if the function
** has no arguments or has only constant arguments. Return false if pExpr
** references columns but not columns of tables found in pSrcList.
*/
static int sqlite3FunctionUsesOtherSrc(Expr *pExpr, SrcList *pSrcList){
int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
Walker w;
struct SrcCount cnt;
assert( pExpr->op==TK_AGG_FUNCTION );
memset(&w, 0, sizeof(w));
w.xExprCallback = exprUsesOtherSrc;
w.u.pSrcList = pSrcList;
if( sqlite3WalkExprList(&w, pExpr->x.pList)!=WRC_Continue ) return 1;
return 0;
w.xExprCallback = exprSrcCount;
w.u.pSrcCount = &cnt;
cnt.pSrc = pSrcList;
cnt.nThis = 0;
cnt.nOther = 0;
sqlite3WalkExprList(&w, pExpr->x.pList);
return cnt.nThis>0 || cnt.nOther==0;
}
/*
@ -3966,7 +3991,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
}
case TK_AGG_FUNCTION: {
if( (pNC->ncFlags & NC_InAggFunc)==0
&& !sqlite3FunctionUsesOtherSrc(pExpr, pSrcList)
&& pWalker->walkerDepth==pExpr->op2
){
/* Check to see if pExpr is a duplicate of another aggregate
** function that is already in the pAggInfo structure

View File

@ -560,7 +560,7 @@ static void fkScanChildren(
** clause. If the constraint is not deferred, throw an exception for
** each row found. Otherwise, for deferred constraints, increment the
** deferred constraint counter by nIncr for each row selected. */
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0);
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
if( nIncr>0 && pFKey->isDeferred==0 ){
sqlite3ParseToplevel(pParse)->mayAbort = 1;
}

View File

@ -231,14 +231,14 @@ static int sqlite3MemInit(void *NotUsed){
}else{
/* only 1 core, use our own zone to contention over global locks,
** e.g. we have our own dedicated locks */
bool success;
bool success;
malloc_zone_t* newzone = malloc_create_zone(4096, 0);
malloc_set_zone_name(newzone, "Sqlite_Heap");
do{
success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone,
(void * volatile *)&_sqliteZone_);
}while(!_sqliteZone_);
if( !success ){
if( !success ){
/* somebody registered a zone first */
malloc_destroy_zone(newzone);
}

View File

@ -715,9 +715,9 @@ static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
case EACCES:
/* EACCES is like EAGAIN during locking operations, but not any other time*/
if( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
(sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
(sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){
return SQLITE_BUSY;
}
/* else fall through */
@ -1764,7 +1764,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
pInode->eFileLock = NO_LOCK;
}else{
rc = SQLITE_IOERR_UNLOCK;
pFile->lastErrno = errno;
pFile->lastErrno = errno;
pInode->eFileLock = NO_LOCK;
pFile->eFileLock = NO_LOCK;
}
@ -1780,7 +1780,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
closePendingFds(pFile);
}
}
end_unlock:
unixLeaveMutex();
if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;
@ -2047,7 +2047,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
assert( pFile );
OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
pFile->eFileLock, getpid()));
pFile->eFileLock, getpid()));
assert( eFileLock<=SHARED_LOCK );
/* no-op if possible */
@ -2434,7 +2434,7 @@ static int semUnlock(sqlite3_file *id, int eFileLock) {
assert( pFile );
assert( pSem );
OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
pFile->eFileLock, getpid()));
pFile->eFileLock, getpid()));
assert( eFileLock<=SHARED_LOCK );
/* no-op if possible */
@ -3024,7 +3024,7 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
if( newOffset == -1 ){
((unixFile*)id)->lastErrno = errno;
}else{
((unixFile*)id)->lastErrno = 0;
((unixFile*)id)->lastErrno = 0;
}
return -1;
}
@ -3112,7 +3112,7 @@ static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
if( newOffset == -1 ){
((unixFile*)id)->lastErrno = errno;
}else{
((unixFile*)id)->lastErrno = 0;
((unixFile*)id)->lastErrno = 0;
}
return -1;
}
@ -5626,7 +5626,7 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
** address in the shared range is taken for a SHARED lock, the entire
** shared range is taken for an EXCLUSIVE lock):
**
** PENDING_BYTE 0x40000000
** PENDING_BYTE 0x40000000
** RESERVED_BYTE 0x40000001
** SHARED_RANGE 0x40000002 -> 0x40000200
**

View File

@ -46,9 +46,11 @@
# define FILE_ATTRIBUTE_MASK (0x0003FFF7)
#endif
#ifndef SQLITE_OMIT_WAL
/* Forward references */
typedef struct winShm winShm; /* A connection to shared-memory */
typedef struct winShmNode winShmNode; /* A region of shared-memory */
#endif
/*
** WinCE lacks native support for file locking so we have to fake it
@ -76,7 +78,9 @@ struct winFile {
short sharedLockByte; /* Randomly chosen byte used as a shared lock */
u8 ctrlFlags; /* Flags. See WINFILE_* below */
DWORD lastErrno; /* The Windows errno from the last I/O error */
#ifndef SQLITE_OMIT_WAL
winShm *pShm; /* Instance of shared memory on this file */
#endif
const char *zPath; /* Full pathname of this file */
int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
#if SQLITE_OS_WINCE
@ -101,6 +105,22 @@ struct winFile {
# define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD)))
#endif
/*
* The value used with sqlite3_win32_set_directory() to specify that
* the data directory should be changed.
*/
#ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE
# define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1)
#endif
/*
* The value used with sqlite3_win32_set_directory() to specify that
* the temporary directory should be changed.
*/
#ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE
# define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2)
#endif
/*
* If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
* various Win32 API heap functions instead of our own.
@ -1314,6 +1334,42 @@ char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
return zFilenameMbcs;
}
/*
** This function sets the data directory or the temporary directory based on
** the provided arguments. The type argument must be 1 in order to set the
** data directory or 2 in order to set the temporary directory. The zValue
** argument is the name of the directory to use. The return value will be
** SQLITE_OK if successful.
*/
int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
char **ppDirectory = 0;
#ifndef SQLITE_OMIT_AUTOINIT
int rc = sqlite3_initialize();
if( rc ) return rc;
#endif
if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){
ppDirectory = &sqlite3_data_directory;
}else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){
ppDirectory = &sqlite3_temp_directory;
}
assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE
|| type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE
);
assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) );
if( ppDirectory ){
char *zValueUtf8 = 0;
if( zValue && zValue[0] ){
zValueUtf8 = unicodeToUtf8(zValue);
if ( zValueUtf8==0 ){
return SQLITE_NOMEM;
}
}
sqlite3_free(*ppDirectory);
*ppDirectory = zValueUtf8;
return SQLITE_OK;
}
return SQLITE_ERROR;
}
/*
** The return value of getLastErrorMsg
@ -1930,7 +1986,9 @@ static int winClose(sqlite3_file *id){
winFile *pFile = (winFile*)id;
assert( id!=0 );
#ifndef SQLITE_OMIT_WAL
assert( pFile->pShm==0 );
#endif
OSTRACE(("CLOSE %d\n", pFile->h));
do{
rc = osCloseHandle(pFile->h);
@ -3680,7 +3738,9 @@ static int winOpen(
pFile->h = h;
pFile->lastErrno = NO_ERROR;
pFile->pVfs = pVfs;
#ifndef SQLITE_OMIT_WAL
pFile->pShm = 0;
#endif
pFile->zPath = zName;
if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
pFile->ctrlFlags |= WINFILE_PSOW;

View File

@ -18,6 +18,29 @@
#include <stdlib.h>
#include <string.h>
/*
** Walk the expression tree pExpr and increase the aggregate function
** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node.
** This needs to occur when copying a TK_AGG_FUNCTION node from an
** outer query into an inner subquery.
**
** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..)
** is a helper function - a callback for the tree walker.
*/
static int incrAggDepth(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.i;
return WRC_Continue;
}
static void incrAggFunctionDepth(Expr *pExpr, int N){
if( N>0 ){
Walker w;
memset(&w, 0, sizeof(w));
w.xExprCallback = incrAggDepth;
w.u.i = N;
sqlite3WalkExpr(&w, pExpr);
}
}
/*
** Turn the pExpr expression into an alias for the iCol-th column of the
** result set in pEList.
@ -44,13 +67,20 @@
** The result of random()%5 in the GROUP BY clause is probably different
** from the result in the result-set. We might fix this someday. Or
** then again, we might not...
**
** The nSubquery parameter specifies how many levels of subquery the
** alias is removed from the original expression. The usually value is
** zero but it might be more if the alias is contained within a subquery
** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION
** structures must be increased by the nSubquery amount.
*/
static void resolveAlias(
Parse *pParse, /* Parsing context */
ExprList *pEList, /* A result set */
int iCol, /* A column in the result set. 0..pEList->nExpr-1 */
Expr *pExpr, /* Transform this into an alias to the result set */
const char *zType /* "GROUP" or "ORDER" or "" */
const char *zType, /* "GROUP" or "ORDER" or "" */
int nSubquery /* Number of subqueries that the label is moving */
){
Expr *pOrig; /* The iCol-th column of the result set */
Expr *pDup; /* Copy of pOrig */
@ -63,6 +93,7 @@ static void resolveAlias(
db = pParse->db;
if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){
pDup = sqlite3ExprDup(db, pOrig, 0);
incrAggFunctionDepth(pDup, nSubquery);
pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
if( pDup==0 ) return;
if( pEList->a[iCol].iAlias==0 ){
@ -151,9 +182,10 @@ static int lookupName(
NameContext *pNC, /* The name context used to resolve the name */
Expr *pExpr /* Make this EXPR node point to the selected column */
){
int i, j; /* Loop counters */
int i, j; /* Loop counters */
int cnt = 0; /* Number of matching column names */
int cntTab = 0; /* Number of matching table names */
int nSubquery = 0; /* How many levels of subquery */
sqlite3 *db = pParse->db; /* The database connection */
struct SrcList_item *pItem; /* Use for looping over pSrcList items */
struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
@ -315,7 +347,7 @@ static int lookupName(
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
return WRC_Abort;
}
resolveAlias(pParse, pEList, j, pExpr, "");
resolveAlias(pParse, pEList, j, pExpr, "", nSubquery);
cnt = 1;
pMatch = 0;
assert( zTab==0 && zDb==0 );
@ -329,6 +361,7 @@ static int lookupName(
*/
if( cnt==0 ){
pNC = pNC->pNext;
nSubquery++;
}
}
@ -568,13 +601,19 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
nId, zId);
pNC->nErr++;
}
if( is_agg ){
pExpr->op = TK_AGG_FUNCTION;
pNC->ncFlags |= NC_HasAgg;
}
if( is_agg ) pNC->ncFlags &= ~NC_AllowAgg;
sqlite3WalkExprList(pWalker, pList);
if( is_agg ) pNC->ncFlags |= NC_AllowAgg;
if( is_agg ){
NameContext *pNC2 = pNC;
pExpr->op = TK_AGG_FUNCTION;
pExpr->op2 = 0;
while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
pExpr->op2++;
pNC2 = pNC2->pNext;
}
if( pNC2 ) pNC2->ncFlags |= NC_HasAgg;
pNC->ncFlags |= NC_AllowAgg;
}
/* FIX ME: Compute pExpr->affinity based on the expected return
** type of the function
*/
@ -853,7 +892,7 @@ int sqlite3ResolveOrderGroupBy(
resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
return 1;
}
resolveAlias(pParse, pEList, pItem->iOrderByCol-1, pItem->pExpr, zType);
resolveAlias(pParse, pEList, pItem->iOrderByCol-1, pItem->pExpr, zType,0);
}
}
return 0;

View File

@ -3149,7 +3149,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){
if( IsVirtual(pTab) ) return 0;
if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
if( pAggInfo->nFunc==0 ) return 0;
if( NEVER(pAggInfo->nFunc==0) ) return 0;
if( (pAggInfo->aFunc[0].pFunc->flags&SQLITE_FUNC_COUNT)==0 ) return 0;
if( pExpr->flags&EP_Distinct ) return 0;
@ -3521,7 +3521,7 @@ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
/*
** This routine sets of a SELECT statement for processing. The
** This routine sets up a SELECT statement for processing. The
** following is accomplished:
**
** * VDBE Cursor numbers are assigned to all FROM-clause terms.
@ -3553,7 +3553,8 @@ void sqlite3SelectPrep(
**
** The aggregate accumulator is a set of memory cells that hold
** intermediate results while calculating an aggregate. This
** routine simply stores NULLs in all of those memory cells.
** routine generates code that stores NULLs in all of those memory
** cells.
*/
static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
Vdbe *v = pParse->pVdbe;
@ -4023,7 +4024,7 @@ int sqlite3Select(
ExprList *pDist = (isDistinct ? p->pEList : 0);
/* Begin the database scan. */
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy, pDist, 0,0);
if( pWInfo==0 ) goto select_end;
if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut;
@ -4196,7 +4197,7 @@ int sqlite3Select(
** in the right order to begin with.
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy, 0, 0, 0);
if( pWInfo==0 ) goto select_end;
if( pGroupBy==0 ){
/* The optimizer is able to deliver rows in group by order so
@ -4465,7 +4466,7 @@ int sqlite3Select(
** of output.
*/
resetAccumulator(pParse, &sAggInfo);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, 0, flag);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax,0,flag,0);
if( pWInfo==0 ){
sqlite3ExprListDelete(db, pDel);
goto select_end;

View File

@ -3154,8 +3154,11 @@ typedef struct sqlite3_context sqlite3_context;
** ^(In those routines that have a fourth argument, its value is the
** number of bytes in the parameter. To be clear: the value is the
** number of <u>bytes</u> in the value, not the number of characters.)^
** ^If the fourth parameter is negative, the length of the string is
** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()
** is negative, then the length of the string is
** the number of bytes up to the first zero terminator.
** If the fourth parameter to sqlite3_bind_blob() is negative, then
** the behavior is undefined.
** If a non-negative fourth parameter is provided to sqlite3_bind_text()
** or sqlite3_bind_text16() then that parameter must be the byte offset
** where the NUL terminator would occur assuming the string were NUL

View File

@ -1698,8 +1698,9 @@ struct Expr {
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
u8 flags2; /* Second set of flags. EP2_... */
u8 op2; /* If a TK_REGISTER, the original value of Expr.op */
/* If TK_COLUMN, the value of p5 for OP_Column */
u8 op2; /* TK_REGISTER: original value of Expr.op
** TK_COLUMN: the value of p5 for OP_Column
** TK_AGG_FUNCTION: nesting depth */
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
Table *pTab; /* Table for TK_COLUMN expressions. */
#if SQLITE_MAX_EXPR_DEPTH>0
@ -1954,6 +1955,7 @@ struct WhereLevel {
int addrInTop; /* Top of the IN loop */
} *aInLoop; /* Information about each nested IN operator */
} in; /* Used when plan.wsFlags&WHERE_IN_ABLE */
Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */
} u;
/* The following field is really not part of the current level. But
@ -2510,10 +2512,12 @@ struct Walker {
int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */
int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */
Parse *pParse; /* Parser context. */
int walkerDepth; /* Number of subqueries */
union { /* Extra data for callback */
NameContext *pNC; /* Naming context */
int i; /* Integer value */
SrcList *pSrcList; /* FROM clause */
struct SrcCount *pSrcCount; /* Counting column references */
} u;
};
@ -2815,7 +2819,8 @@ Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *,
#endif
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**,ExprList*,u16);
WhereInfo *sqlite3WhereBegin(
Parse*,SrcList*,Expr*,ExprList**,ExprList*,u16,int);
void sqlite3WhereEnd(WhereInfo*);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
@ -2847,6 +2852,7 @@ int sqlite3ExprCompare(Expr*, Expr*);
int sqlite3ExprListCompare(ExprList*, ExprList*);
void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
Vdbe *sqlite3GetVdbe(Parse*);
void sqlite3PrngSaveState(void);
void sqlite3PrngRestoreState(void);

View File

@ -5928,7 +5928,7 @@ static int optimization_control(
sqlite3 *db;
const char *zOpt;
int onoff;
int mask;
int mask = 0;
static const struct {
const char *zOptName;
int mask;

View File

@ -325,6 +325,12 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "fts3_unicode", "0", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_DISABLE_FTS4_DEFERRED
Tcl_SetVar2(interp, "sqlite_options", "fts4_deferred", "0", TCL_GLOBAL_ONLY);
#else
Tcl_SetVar2(interp, "sqlite_options", "fts4_deferred", "1", TCL_GLOBAL_ONLY);
#endif
#ifdef SQLITE_OMIT_GET_TABLE
Tcl_SetVar2(interp, "sqlite_options", "gettable", "0", TCL_GLOBAL_ONLY);
#else

View File

@ -502,11 +502,11 @@ static int multiplexOpen(
){
int rc = SQLITE_OK; /* Result code */
multiplexConn *pMultiplexOpen; /* The new multiplex file descriptor */
multiplexGroup *pGroup; /* Corresponding multiplexGroup object */
multiplexGroup *pGroup = 0; /* Corresponding multiplexGroup object */
sqlite3_file *pSubOpen = 0; /* Real file descriptor */
sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */
int nName;
int sz;
int nName = 0;
int sz = 0;
char *zToFree = 0;
UNUSED_PARAMETER(pVfs);

View File

@ -659,7 +659,7 @@ static int editDist3ConfigLoad(
int rc, rc2;
char *zSql;
int iLangPrev = -9999;
EditDist3Lang *pLang;
EditDist3Lang *pLang = 0;
zSql = sqlite3_mprintf("SELECT iLang, cFrom, cTo, iCost"
" FROM \"%w\" WHERE iLang>=0 ORDER BY iLang", zTable);
@ -680,7 +680,7 @@ static int editDist3ConfigLoad(
assert( zTo!=0 || nTo==0 );
if( nFrom>100 || nTo>100 ) continue;
if( iCost<0 ) continue;
if( iLang!=iLangPrev ){
if( pLang==0 || iLang!=iLangPrev ){
EditDist3Lang *pNew;
pNew = sqlite3_realloc(p->a, (p->nLang+1)*sizeof(p->a[0]));
if( pNew==0 ){ rc = SQLITE_NOMEM; break; }
@ -863,9 +863,9 @@ static void updateCost(
int j,
int iCost
){
int b;
assert( iCost>=0 );
if( iCost<10000 ){
b = m[j] + iCost;
unsigned int b = m[j] + iCost;
if( b<m[i] ) m[i] = b;
}
}
@ -2508,15 +2508,17 @@ static int spellfix1Filter(
*/
static int spellfix1Next(sqlite3_vtab_cursor *cur){
spellfix1_cursor *pCur = (spellfix1_cursor *)cur;
int rc = SQLITE_OK;
if( pCur->iRow < pCur->nRow ){
if( pCur->pFullScan ){
int rc = sqlite3_step(pCur->pFullScan);
rc = sqlite3_step(pCur->pFullScan);
if( rc!=SQLITE_ROW ) pCur->iRow = pCur->nRow;
if( rc==SQLITE_ROW || rc==SQLITE_DONE ) rc = SQLITE_OK;
}else{
pCur->iRow++;
}
}
return SQLITE_OK;
return rc;
}
/*
@ -2773,25 +2775,35 @@ static sqlite3_module spellfix1Module = {
** Register the various functions and the virtual table.
*/
static int spellfix1Register(sqlite3 *db){
int nErr = 0;
int rc = SQLITE_OK;
int i;
nErr += sqlite3_create_function(db, "spellfix1_translit", 1, SQLITE_UTF8, 0,
rc = sqlite3_create_function(db, "spellfix1_translit", 1, SQLITE_UTF8, 0,
transliterateSqlFunc, 0, 0);
nErr += sqlite3_create_function(db, "spellfix1_editdist", 2, SQLITE_UTF8, 0,
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "spellfix1_editdist", 2, SQLITE_UTF8, 0,
editdistSqlFunc, 0, 0);
nErr += sqlite3_create_function(db, "spellfix1_phonehash", 1, SQLITE_UTF8, 0,
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "spellfix1_phonehash", 1, SQLITE_UTF8, 0,
phoneticHashSqlFunc, 0, 0);
nErr += sqlite3_create_function(db, "spellfix1_scriptcode", 1, SQLITE_UTF8, 0,
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "spellfix1_scriptcode", 1, SQLITE_UTF8, 0,
scriptCodeSqlFunc, 0, 0);
nErr += sqlite3_create_module(db, "spellfix1", &spellfix1Module, 0);
nErr += editDist3Install(db);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_module(db, "spellfix1", &spellfix1Module, 0);
}
if( rc==SQLITE_OK ){
rc = editDist3Install(db);
}
/* Verify sanity of the translit[] table */
for(i=0; i<sizeof(translit)/sizeof(translit[0])-1; i++){
assert( translit[i].cFrom<translit[i+1].cFrom );
}
return nErr ? SQLITE_ERROR : SQLITE_OK;
return rc;
}
#if SQLITE_CORE || defined(SQLITE_TEST)

View File

@ -313,7 +313,7 @@ void sqlite3Update(
*/
sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
pWInfo = sqlite3WhereBegin(
pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED
pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED, 0
);
if( pWInfo==0 ) goto update_cleanup;
okOnePass = pWInfo->okOnePass;

View File

@ -125,12 +125,18 @@ int sqlite3WalkSelect(Walker *pWalker, Select *p){
int rc;
if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
rc = WRC_Continue;
while( p ){
pWalker->walkerDepth++;
while( p ){
rc = pWalker->xSelectCallback(pWalker, p);
if( rc ) break;
if( sqlite3WalkSelectExpr(pWalker, p) ) return WRC_Abort;
if( sqlite3WalkSelectFrom(pWalker, p) ) return WRC_Abort;
if( sqlite3WalkSelectExpr(pWalker, p)
|| sqlite3WalkSelectFrom(pWalker, p)
){
pWalker->walkerDepth--;
return WRC_Abort;
}
p = p->pPrior;
}
pWalker->walkerDepth--;
return rc & WRC_Abort;
}

View File

@ -3622,7 +3622,7 @@ static int codeAllEqualityTerms(
int r1;
int k = pIdx->aiColumn[j];
pTerm = findTerm(pWC, iCur, k, notReady, pLevel->plan.wsFlags, pIdx);
if( NEVER(pTerm==0) ) break;
if( pTerm==0 ) break;
/* The following true for indices with redundant columns.
** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
@ -4297,6 +4297,8 @@ static Bitmask codeOneLoopStart(
*/
WhereClause *pOrWc; /* The OR-clause broken out into subterms */
SrcList *pOrTab; /* Shortened table list or OR-clause generation */
Index *pCov = 0; /* Potential covering index (or NULL) */
int iCovCur = pParse->nTab++; /* Cursor used for index scans (if any) */
int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */
int regRowset = 0; /* Register for RowSet object */
@ -4315,7 +4317,7 @@ static Bitmask codeOneLoopStart(
pLevel->op = OP_Return;
pLevel->p1 = regReturn;
/* Set up a new SrcList ni pOrTab containing the table being scanned
/* Set up a new SrcList in pOrTab containing the table being scanned
** by this loop in the a[0] slot and all notReady tables in a[1..] slots.
** This becomes the SrcList in the recursive call to sqlite3WhereBegin().
*/
@ -4392,8 +4394,10 @@ static Bitmask codeOneLoopStart(
/* Loop through table entries that match term pOrTerm. */
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY);
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
assert( pSubWInfo || pParse->nErr || pParse->db->mallocFailed );
if( pSubWInfo ){
WhereLevel *pLvl;
explainOneScan(
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
);
@ -4414,11 +4418,36 @@ static Bitmask codeOneLoopStart(
*/
if( pSubWInfo->untestedTerms ) untestedTerms = 1;
/* If all of the OR-connected terms are optimized using the same
** index, and the index is opened using the same cursor number
** by each call to sqlite3WhereBegin() made by this loop, it may
** be possible to use that index as a covering index.
**
** If the call to sqlite3WhereBegin() above resulted in a scan that
** uses an index, and this is either the first OR-connected term
** processed or the index is the same as that used by all previous
** terms, set pCov to the candidate covering index. Otherwise, set
** pCov to NULL to indicate that no candidate covering index will
** be available.
*/
pLvl = &pSubWInfo->a[0];
if( (pLvl->plan.wsFlags & WHERE_INDEXED)!=0
&& (pLvl->plan.wsFlags & WHERE_TEMP_INDEX)==0
&& (ii==0 || pLvl->plan.u.pIdx==pCov)
){
assert( pLvl->iIdxCur==iCovCur );
pCov = pLvl->plan.u.pIdx;
}else{
pCov = 0;
}
/* Finish the loop through table entries that match term pOrTerm. */
sqlite3WhereEnd(pSubWInfo);
}
}
}
pLevel->u.pCovidx = pCov;
pLevel->iIdxCur = iCovCur;
if( pAndExpr ){
pAndExpr->pLeft = 0;
sqlite3ExprDelete(pParse->db, pAndExpr);
@ -4636,7 +4665,8 @@ WhereInfo *sqlite3WhereBegin(
Expr *pWhere, /* The WHERE clause */
ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
ExprList *pDistinct, /* The select-list for DISTINCT queries - or NULL */
u16 wctrlFlags /* One of the WHERE_* flags defined in sqliteInt.h */
u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */
int iIdxCur /* If WHERE_ONETABLE_ONLY is set, index cursor number */
){
int i; /* Loop counter */
int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */
@ -4956,7 +4986,13 @@ WhereInfo *sqlite3WhereBegin(
testcase( bestPlan.plan.wsFlags & WHERE_INDEXED );
testcase( bestPlan.plan.wsFlags & WHERE_TEMP_INDEX );
if( bestPlan.plan.wsFlags & (WHERE_INDEXED|WHERE_TEMP_INDEX) ){
pLevel->iIdxCur = pParse->nTab++;
if( (wctrlFlags & WHERE_ONETABLE_ONLY)
&& (bestPlan.plan.wsFlags & WHERE_TEMP_INDEX)==0
){
pLevel->iIdxCur = iIdxCur;
}else{
pLevel->iIdxCur = pParse->nTab++;
}
}else{
pLevel->iIdxCur = -1;
}
@ -5208,6 +5244,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
*/
assert( pWInfo->nLevel==1 || pWInfo->nLevel==pTabList->nSrc );
for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
Index *pIdx = 0;
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
@ -5237,12 +5274,15 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
** that reference the table and converts them into opcodes that
** reference the index.
*/
if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 && !db->mallocFailed){
if( pLevel->plan.wsFlags & WHERE_INDEXED ){
pIdx = pLevel->plan.u.pIdx;
}else if( pLevel->plan.wsFlags & WHERE_MULTI_OR ){
pIdx = pLevel->u.pCovidx;
}
if( pIdx && !db->mallocFailed){
int k, j, last;
VdbeOp *pOp;
Index *pIdx = pLevel->plan.u.pIdx;
assert( pIdx!=0 );
pOp = sqlite3VdbeGetOp(v, pWInfo->iTop);
last = sqlite3VdbeCurrentAddr(v);
for(k=pWInfo->iTop; k<last; k++, pOp++){

71
test/aggnested.test Normal file
View File

@ -0,0 +1,71 @@
# 2012 August 23
#
# 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.
#
# This file implements tests for processing aggregate queries with
# subqueries in which the subqueries hold the aggregate functions
# or in which the subqueries are themselves aggregate queries
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_test aggnested-1.1 {
db eval {
CREATE TABLE t1(a1 INTEGER);
INSERT INTO t1 VALUES(1), (2), (3);
CREATE TABLE t2(b1 INTEGER);
INSERT INTO t2 VALUES(4), (5);
SELECT (SELECT group_concat(a1,'x') FROM t2) FROM t1;
}
} {1x2x3}
do_test aggnested-1.2 {
db eval {
SELECT
(SELECT group_concat(a1,'x') || '-' || group_concat(b1,'y') FROM t2)
FROM t1;
}
} {1x2x3-4y5}
do_test aggnested-1.3 {
db eval {
SELECT (SELECT group_concat(b1,a1) FROM t2) FROM t1;
}
} {415 425 435}
do_test aggnested-1.4 {
db eval {
SELECT (SELECT group_concat(a1,b1) FROM t2) FROM t1;
}
} {151 252 353}
# This test case is a copy of the one in
# http://www.mail-archive.com/sqlite-users@sqlite.org/msg70787.html
#
do_test aggnested-2.0 {
sqlite3 db2 :memory:
db2 eval {
CREATE TABLE t1 (A1 INTEGER NOT NULL,A2 INTEGER NOT NULL,A3 INTEGER NOT
NULL,A4 INTEGER NOT NULL,PRIMARY KEY(A1));
REPLACE INTO t1 VALUES(1,11,111,1111);
REPLACE INTO t1 VALUES(2,22,222,2222);
REPLACE INTO t1 VALUES(3,33,333,3333);
CREATE TABLE t2 (B1 INTEGER NOT NULL,B2 INTEGER NOT NULL,B3 INTEGER NOT
NULL,B4 INTEGER NOT NULL,PRIMARY KEY(B1));
REPLACE INTO t2 VALUES(1,88,888,8888);
REPLACE INTO t2 VALUES(2,99,999,9999);
SELECT (SELECT GROUP_CONCAT(CASE WHEN a1=1 THEN'A' ELSE 'B' END) FROM t2),
t1.*
FROM t1;
}
} {A,B,B 3 33 333 3333}
db2 close
finish_test

View File

@ -67,7 +67,7 @@ proc do_fts3query_test {tn args} {
foreach {k v} [lrange $args 0 [expr $nArg-3]] {
switch -- $k {
-deferred {
set deferred $v
ifcapable fts4_deferred { set deferred $v }
}
default {
error "bad option \"$k\": must be -deferred"
@ -509,9 +509,9 @@ foreach {tn create} {
do_fts3query_test 3.$tn.2.1 t1 {a OR c}
do_test 3.$tn.3 {
fts3_zero_long_segments t1 $limit
} {1}
ifcapable fts4_deferred {
do_test 3.$tn.3 { fts3_zero_long_segments t1 $limit } {1}
}
foreach {tn2 expr def} {
1 {a NEAR c} {}
@ -550,7 +550,11 @@ foreach {tn create} {
do_test 4.$tn.2 {
set limit [fts3_make_deferrable t1 five]
execsql { INSERT INTO t1(t1) VALUES('optimize') }
expr {[fts3_zero_long_segments t1 $limit]>0}
ifcapable fts4_deferred {
expr {[fts3_zero_long_segments t1 $limit]>0}
} else {
expr 1
}
} {1}
do_fts3query_test 4.$tn.3.1 -deferred five t1 {one AND five}

View File

@ -13,7 +13,7 @@ set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
ifcapable !fts3 {
ifcapable !fts3||!fts4_deferred {
finish_test
return
}

View File

@ -13,7 +13,10 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/malloc_common.tcl
ifcapable !fts3 { finish_test ; return }
ifcapable !fts3||!fts4_deferred {
finish_test
return
}
set testprefix fts3defer2

View File

@ -275,11 +275,14 @@ do_matchinfo_test 4.3.4 t5 {t5 MATCH 'a a a'} { s {3 1} }
do_matchinfo_test 4.3.5 t5 {t5 MATCH '"a b" "a b"'} { s {2} }
do_matchinfo_test 4.3.6 t5 {t5 MATCH 'a OR b'} { s {1 2 1 1} }
do_execsql_test 4.4.0 {
INSERT INTO t5(t5) VALUES('optimize');
UPDATE t5_segments
SET block = zeroblob(length(block))
WHERE length(block)>10000;
do_execsql_test 4.4.0.1 { INSERT INTO t5(t5) VALUES('optimize') }
ifcapable fts4_deferred {
do_execsql_test 4.4.0.2 {
UPDATE t5_segments
SET block = zeroblob(length(block))
WHERE length(block)>10000;
}
}
do_matchinfo_test 4.4.2 t5 {t5 MATCH 'a b'} { s {2} }

View File

@ -1655,14 +1655,16 @@ do_test fts4aa-1.8 {
SELECT docid FROM t1_docsize EXCEPT SELECT docid FROM t1
}
} {}
do_test fts4aa-1.9 {
# Note: Token 'in' is being deferred in the following query.
db eval {
SELECT docid, mit(matchinfo(t1, 'pcxnal')) FROM t1
WHERE t1 MATCH 'joseph died in egypt'
ORDER BY docid;
}
} {1050026 {4 1 1 1 1 1 1 1 2 1 1 1 1 1 1 23 23}}
ifcapable fts4_deferred {
do_test fts4aa-1.9 {
# Note: Token 'in' is being deferred in the following query.
db eval {
SELECT docid, mit(matchinfo(t1, 'pcxnal')) FROM t1
WHERE t1 MATCH 'joseph died in egypt'
ORDER BY docid;
}
} {1050026 {4 1 1 1 1 1 1 1 2 1 1 1 1 1 1 23 23}}
}
# Should get the same search results from FTS3
#

View File

@ -151,6 +151,15 @@ array set ::Configs {
-DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
-DSQLITE_MAX_ATTACHED=62
}
"Devkit" {
-DSQLITE_DEFAULT_FILE_FORMAT=4
-DSQLITE_MAX_ATTACHED=30
-DSQLITE_ENABLE_COLUMN_METADATA
-DSQLITE_ENABLE_FTS4
-DSQLITE_ENABLE_FTS4_PARENTHESIS
-DSQLITE_DISABLE_FTS4_DEFERRED
-DSQLITE_ENABLE_RTREE
}
}
array set ::Platforms {
@ -166,6 +175,7 @@ array set ::Platforms {
"Device-One" fulltest
}
Linux-i686 {
"Devkit" test
"Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test"
"Device-One" test
"Device-Two" test

View File

@ -69,17 +69,18 @@ do_test 1.1 {
foreach {tn word res} {
1 raxpi* {rasping 5 rasped 5 raspberry 6 rasp 4 rasps 4}
2 ril* {rail 4 railway 4 railing 4 rails 4 railways 4}
3 rilis* {realist 6 realistic 6 realistically 6 realists 6 realism 6}
4 reail* {realities 3 reality 3 real 3 realest 3 realist 3}
5 ras* {rasp 3 rash 3 rasped 3 rasping 3 rasps 3}
2 ril* {rail 4 railed 4 railer 4 railers 4 railing 4}
3 rilis* {realism 6 realist 6 realistic 6 realistically 6 realists 6}
4 reail* {real 3 realest 3 realign 3 realigned 3 realigning 3}
5 ras* {rascal 3 rascally 3 rascals 3 rash 3 rasher 3}
6 realistss* {realists 8 realigns 8 realistic 9 realistically 9 realest 7}
7 realistss {realists 8 realist 7 realigns 8 realistic 9 realest 7}
8 rllation* {realities 9 reality 7 rallied 7 railed 4}
9 renstom* {rainstorm 8 ransomer 6 ransom 6 ransoming 6 ransoms 6}
9 renstom* {rainstorm 8 ransom 6 ransomer 6 ransoming 6 ransoms 6}
} {
do_execsql_test 1.2.$tn {
SELECT word, matchlen FROM t1 WHERE word MATCH $word LIMIT 5
SELECT word, matchlen FROM t1 WHERE word MATCH $word
ORDER BY score, word LIMIT 5
} $res
}

164
test/whereD.test Normal file
View File

@ -0,0 +1,164 @@
# 2012 August 24
#
# 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 that an index may be used as a covering
# index when there are OR expressions in the WHERE clause.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix whereD
do_execsql_test 1.1 {
CREATE TABLE t(i,j,k,m,n);
CREATE INDEX ijk ON t(i,j,k);
CREATE INDEX jmn ON t(j,m,n);
INSERT INTO t VALUES(3, 3, 'three', 3, 'tres');
INSERT INTO t VALUES(2, 2, 'two', 2, 'dos');
INSERT INTO t VALUES(1, 1, 'one', 1, 'uno');
INSERT INTO t VALUES(4, 4, 'four', 4, 'cuatro');
}
do_execsql_test 1.2 {
SELECT k FROM t WHERE (i=1 AND j=1) OR (i=2 AND j=2);
} {one two}
do_execsql_test 1.3 {
SELECT k FROM t WHERE (i=1 AND j=1) OR (+i=2 AND j=2);
} {one two}
do_execsql_test 1.4 {
SELECT n FROM t WHERE (i=1 AND j=1) OR (i=2 AND j=2);
} {uno dos}
do_execsql_test 1.5 {
SELECT k, n FROM t WHERE (i=1 AND j=1) OR (i=2 AND j=2);
} {one uno two dos}
do_execsql_test 1.6 {
SELECT k FROM t WHERE (i=1 AND j=1) OR (i=2 AND j=2) OR (i=3 AND j=3);
} {one two three}
do_execsql_test 1.7 {
SELECT n FROM t WHERE (i=1 AND j=1) OR (i=2 AND j=2) OR (i=3 AND j=3);
} {uno dos tres}
do_execsql_test 1.8 {
SELECT k FROM t WHERE (i=1 AND j=1) OR (j=2 AND m=2);
} {one two}
do_execsql_test 1.9 {
SELECT k FROM t WHERE (i=1 AND j=1) OR (i=2 AND j=2) OR (j=3 AND m=3);
} {one two three}
do_execsql_test 1.10 {
SELECT n FROM t WHERE (i=1 AND j=1) OR (i=2 AND j=2) OR (j=3 AND m=3);
} {uno dos tres}
do_execsql_test 1.11 {
SELECT k FROM t WHERE (i=1 AND j=1) OR (j=2 AND m=2) OR (i=3 AND j=3);
} {one two three}
do_execsql_test 1.12 {
SELECT n FROM t WHERE (i=1 AND j=1) OR (j=2 AND m=2) OR (i=3 AND j=3);
} {uno dos tres}
do_execsql_test 1.13 {
SELECT k FROM t WHERE (j=1 AND m=1) OR (i=2 AND j=2) OR (i=3 AND j=3);
} {one two three}
do_execsql_test 1.14 {
SELECT k FROM t WHERE (i=1 AND j=1) OR (j=2 AND i=2) OR (i=3 AND j=3);
} {one two three}
do_execsql_test 1.15 {
SELECT k FROM t WHERE (i=1 AND j=2) OR (i=2 AND j=1) OR (i=3 AND j=4);
} {}
do_execsql_test 1.16 {
SELECT k FROM t WHERE (i=1 AND (j=1 or j=2)) OR (i=3 AND j=3);
} {one three}
do_execsql_test 2.0 {
CREATE TABLE t1(a,b,c,d);
CREATE INDEX t1b ON t1(b);
CREATE INDEX t1c ON t1(c);
CREATE INDEX t1d ON t1(d);
CREATE TABLE t2(x,y);
CREATE INDEX t2y ON t2(y);
INSERT INTO t1 VALUES(1,2,3,4);
INSERT INTO t1 VALUES(5,6,7,8);
INSERT INTO t2 VALUES(1,2);
INSERT INTO t2 VALUES(2,7);
INSERT INTO t2 VALUES(3,4);
} {}
do_execsql_test 2.1 {
SELECT a, x FROM t1 JOIN t2 ON +y=d OR x=7 ORDER BY a, x;
} {1 3}
do_execsql_test 2.2 {
SELECT a, x FROM t1 JOIN t2 ON y=d OR x=7 ORDER BY a, x;
} {1 3}
# Similar to [do_execsql_test], except that two elements are appended
# to the result - the string "search" and the number of times test variable
# sqlite3_search_count is incremented by running the supplied SQL. e.g.
#
# do_searchcount_test 1.0 { SELECT * FROM t1 } {x y search 2}
#
proc do_searchcount_test {tn sql res} {
uplevel [subst -nocommands {
do_test $tn {
set ::sqlite_search_count 0
concat [db eval {$sql}] search [set ::sqlite_search_count]
} [list $res]
}]
}
do_execsql_test 3.0 {
CREATE TABLE t3(a, b, c);
CREATE UNIQUE INDEX i3 ON t3(a, b);
INSERT INTO t3 VALUES(1, 'one', 'i');
INSERT INTO t3 VALUES(3, 'three', 'iii');
INSERT INTO t3 VALUES(6, 'six', 'vi');
INSERT INTO t3 VALUES(2, 'two', 'ii');
INSERT INTO t3 VALUES(4, 'four', 'iv');
INSERT INTO t3 VALUES(5, 'five', 'v');
CREATE TABLE t4(x PRIMARY KEY, y);
INSERT INTO t4 VALUES('a', 'one');
INSERT INTO t4 VALUES('b', 'two');
}
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}
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}
do_searchcount_test 3.4.1 {
SELECT y FROM t4 WHERE x='a'
} {one search 2}
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}
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}
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}
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}
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}
finish_test

84
tool/checkSpacing.c Normal file
View File

@ -0,0 +1,84 @@
/*
** This program checks for formatting problems in source code:
**
** * Any use of tab characters
** * White space at the end of a line
** * Blank lines at the end of a file
**
** Any violations are reported.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CR_OK 0x001
#define WSEOL_OK 0x002
static void checkSpacing(const char *zFile, unsigned flags){
FILE *in = fopen(zFile, "rb");
int i;
int seenSpace;
int seenTab;
int ln = 0;
int lastNonspace = 0;
char zLine[2000];
if( in==0 ){
printf("cannot open %s\n", zFile);
return;
}
while( fgets(zLine, sizeof(zLine), in) ){
seenSpace = 0;
seenTab = 0;
ln++;
for(i=0; zLine[i]; i++){
if( zLine[i]=='\t' && seenTab==0 ){
printf("%s:%d: tab (\\t) character\n", zFile, ln);
seenTab = 1;
}else if( zLine[i]=='\r' ){
if( (flags & CR_OK)==0 ){
printf("%s:%d: carriage-return (\\r) character\n", zFile, ln);
}
}else if( zLine[i]==' ' ){
seenSpace = 1;
}else if( zLine[i]!='\n' ){
lastNonspace = ln;
seenSpace = 0;
}
}
if( seenSpace && (flags & WSEOL_OK)==0 ){
printf("%s:%d: whitespace at end-of-line\n", zFile, ln);
}
}
fclose(in);
if( lastNonspace<ln ){
printf("%s:%d: blank lines at end of file (%d)\n",
zFile, ln, ln - lastNonspace);
}
}
int main(int argc, char **argv){
int i;
unsigned flags = WSEOL_OK;
for(i=1; i<argc; i++){
const char *z = argv[i];
if( z[0]=='-' ){
while( z[0]=='-' ) z++;
if( strcmp(z,"crok")==0 ){
flags |= CR_OK;
}else if( strcmp(z, "wseol")==0 ){
flags &= ~WSEOL_OK;
}else if( strcmp(z, "help")==0 ){
printf("Usage: %s [options] FILE ...\n", argv[0]);
printf(" --crok Do not report on carriage-returns\n");
printf(" --wseol Complain about whitespace at end-of-line\n");
printf(" --help This message\n");
}else{
printf("unknown command-line option: [%s]\n", argv[i]);
printf("use --help for additional information\n");
}
}else{
checkSpacing(argv[i], flags);
}
}
return 0;
}

View File

@ -15,7 +15,7 @@
#ifndef __WIN32__
# if defined(_WIN32) || defined(WIN32)
# define __WIN32__
# define __WIN32__
# endif
#endif
@ -653,7 +653,7 @@ void FindRulePrecedences(struct lemon *xp)
}
}else if( sp->prec>=0 ){
rp->precsym = rp->rhs[i];
}
}
}
}
}
@ -711,12 +711,12 @@ void FindFirstSets(struct lemon *lemp)
progress += SetAdd(s1->firstset,s2->subsym[j]->index);
}
break;
}else if( s1==s2 ){
}else if( s1==s2 ){
if( s1->lambda==LEMON_FALSE ) break;
}else{
}else{
progress += SetUnion(s1->firstset,s2->firstset);
if( s2->lambda==LEMON_FALSE ) break;
}
}
}
}
}while( progress );
@ -959,8 +959,8 @@ void FindFollowSets(struct lemon *lemp)
if( change ){
plp->cfp->status = INCOMPLETE;
progress = 1;
}
}
}
}
cfp->status = COMPLETE;
}
}
@ -993,7 +993,7 @@ void FindActions(struct lemon *lemp)
** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */
Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp);
}
}
}
}
}
}
@ -1262,11 +1262,11 @@ void Configlist_closure(struct lemon *lemp)
SetAdd(newcfp->fws, xsp->subsym[k]->index);
}
break;
}else{
}else{
SetUnion(newcfp->fws,xsp->firstset);
if( xsp->lambda==LEMON_FALSE ) break;
}
}
}
}
if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp);
}
}
@ -1996,7 +1996,7 @@ static void parseonetoken(struct pstate *psp)
"There is no prior rule upon which to attach the code \
fragment which begins on this line.");
psp->errorcnt++;
}else if( psp->prevrule->code!=0 ){
}else if( psp->prevrule->code!=0 ){
ErrorMsg(psp->filename,psp->tokenlineno,
"Code fragment beginning on this line is not the first \
to follow the previous rule.");
@ -2004,7 +2004,7 @@ to follow the previous rule.");
}else{
psp->prevrule->line = psp->tokenlineno;
psp->prevrule->code = &x[1];
}
}
}else if( x[0]=='[' ){
psp->state = PRECEDENCE_MARK_1;
}else{
@ -2097,7 +2097,7 @@ to follow the previous rule.");
"Can't allocate enough memory for this rule.");
psp->errorcnt++;
psp->prevrule = 0;
}else{
}else{
int i;
rp->ruleline = psp->tokenlineno;
rp->rhs = (struct symbol**)&rp[1];
@ -2105,7 +2105,7 @@ to follow the previous rule.");
for(i=0; i<psp->nrhs; i++){
rp->rhs[i] = psp->rhs[i];
rp->rhsalias[i] = psp->alias[i];
}
}
rp->lhs = psp->lhs;
rp->lhsalias = psp->lhsalias;
rp->nrhs = psp->nrhs;
@ -2117,12 +2117,12 @@ to follow the previous rule.");
rp->next = 0;
if( psp->firstrule==0 ){
psp->firstrule = psp->lastrule = rp;
}else{
}else{
psp->lastrule->next = rp;
psp->lastrule = rp;
}
}
psp->prevrule = rp;
}
}
psp->state = WAITING_FOR_DECL_OR_RULE;
}else if( isalpha(x[0]) ){
if( psp->nrhs>=MAXRHS ){
@ -2131,11 +2131,11 @@ to follow the previous rule.");
x);
psp->errorcnt++;
psp->state = RESYNC_AFTER_RULE_ERROR;
}else{
}else{
psp->rhs[psp->nrhs] = Symbol_new(x);
psp->alias[psp->nrhs] = 0;
psp->nrhs++;
}
}
}else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){
struct symbol *msp = psp->rhs[psp->nrhs-1];
if( msp->type!=MULTITERMINAL ){
@ -2199,24 +2199,24 @@ to follow the previous rule.");
if( strcmp(x,"name")==0 ){
psp->declargslot = &(psp->gp->name);
psp->insertLineMacro = 0;
}else if( strcmp(x,"include")==0 ){
}else if( strcmp(x,"include")==0 ){
psp->declargslot = &(psp->gp->include);
}else if( strcmp(x,"code")==0 ){
}else if( strcmp(x,"code")==0 ){
psp->declargslot = &(psp->gp->extracode);
}else if( strcmp(x,"token_destructor")==0 ){
}else if( strcmp(x,"token_destructor")==0 ){
psp->declargslot = &psp->gp->tokendest;
}else if( strcmp(x,"default_destructor")==0 ){
}else if( strcmp(x,"default_destructor")==0 ){
psp->declargslot = &psp->gp->vardest;
}else if( strcmp(x,"token_prefix")==0 ){
}else if( strcmp(x,"token_prefix")==0 ){
psp->declargslot = &psp->gp->tokenprefix;
psp->insertLineMacro = 0;
}else if( strcmp(x,"syntax_error")==0 ){
}else if( strcmp(x,"syntax_error")==0 ){
psp->declargslot = &(psp->gp->error);
}else if( strcmp(x,"parse_accept")==0 ){
}else if( strcmp(x,"parse_accept")==0 ){
psp->declargslot = &(psp->gp->accept);
}else if( strcmp(x,"parse_failure")==0 ){
}else if( strcmp(x,"parse_failure")==0 ){
psp->declargslot = &(psp->gp->failure);
}else if( strcmp(x,"stack_overflow")==0 ){
}else if( strcmp(x,"stack_overflow")==0 ){
psp->declargslot = &(psp->gp->overflow);
}else if( strcmp(x,"extra_argument")==0 ){
psp->declargslot = &(psp->gp->arg);
@ -2245,9 +2245,9 @@ to follow the previous rule.");
psp->preccounter++;
psp->declassoc = NONE;
psp->state = WAITING_FOR_PRECEDENCE_SYMBOL;
}else if( strcmp(x,"destructor")==0 ){
}else if( strcmp(x,"destructor")==0 ){
psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL;
}else if( strcmp(x,"type")==0 ){
}else if( strcmp(x,"type")==0 ){
psp->state = WAITING_FOR_DATATYPE_SYMBOL;
}else if( strcmp(x,"fallback")==0 ){
psp->fallback = 0;
@ -2259,7 +2259,7 @@ to follow the previous rule.");
"Unknown declaration keyword: \"%%%s\".",x);
psp->errorcnt++;
psp->state = RESYNC_AFTER_DECL_ERROR;
}
}
}else{
ErrorMsg(psp->filename,psp->tokenlineno,
"Illegal declaration keyword: \"%s\".",x);
@ -2314,10 +2314,10 @@ to follow the previous rule.");
ErrorMsg(psp->filename,psp->tokenlineno,
"Symbol \"%s\" has already be given a precedence.",x);
psp->errorcnt++;
}else{
}else{
sp->prec = psp->preccounter;
sp->assoc = psp->declassoc;
}
}
}else{
ErrorMsg(psp->filename,psp->tokenlineno,
"Can't assign a precedence to \"%s\".",x);
@ -2587,12 +2587,12 @@ void Parse(struct lemon *gp)
if( c=='\n' ) lineno++;
prevc = c;
cp++;
}
}else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */
}
}else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */
cp = &cp[2];
while( (c= *cp)!=0 && c!='\n' ) cp++;
if( c ) lineno++;
}else if( c=='\'' || c=='\"' ){ /* String a character literals */
}else if( c=='\'' || c=='\"' ){ /* String a character literals */
int startchar, prevc;
startchar = c;
prevc = 0;
@ -2600,8 +2600,8 @@ void Parse(struct lemon *gp)
if( c=='\n' ) lineno++;
if( prevc=='\\' ) prevc = 0;
else prevc = c;
}
}
}
}
}
if( c==0 ){
ErrorMsg(ps.filename,ps.tokenlineno,