Merge the latest trunk changes into the sessions branch.
FossilOrigin-Name: aa62d6881b5aae64e15dbae70ce8e77bcc2a9f0b
This commit is contained in:
commit
310874ca00
22
Makefile.msc
22
Makefile.msc
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
75
manifest
75
manifest
@ -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
|
||||
|
@ -1 +1 @@
|
||||
fc07a4795e027108674d1d41eb4350df629ddc8b
|
||||
aa62d6881b5aae64e15dbae70ce8e77bcc2a9f0b
|
@ -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;
|
||||
|
@ -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 );
|
||||
|
@ -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);
|
||||
|
73
src/expr.c
73
src/expr.c
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
**
|
||||
|
60
src/os_win.c
60
src/os_win.c
@ -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;
|
||||
|
@ -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;
|
||||
|
13
src/select.c
13
src/select.c
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
12
src/walker.c
12
src/walker.c
@ -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;
|
||||
}
|
||||
|
56
src/where.c
56
src/where.c
@ -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
71
test/aggnested.test
Normal 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
|
@ -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}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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} }
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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
|
||||
|
@ -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
164
test/whereD.test
Normal 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
84
tool/checkSpacing.c
Normal 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;
|
||||
}
|
78
tool/lemon.c
78
tool/lemon.c
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user