mirror of https://github.com/sqlite/sqlite
Merge latest trunk changes into this branch.
FossilOrigin-Name: 1506e99eca19f72fb59b55ec9e2534505dfa7a6e
This commit is contained in:
commit
e11afed562
|
@ -543,6 +543,9 @@ sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h
|
|||
sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS)
|
||||
|
||||
fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) -o $@ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS)
|
||||
|
||||
mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
|
||||
$(LTLINK) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
|
||||
$(TLIBS) -rpath "$(libdir)"
|
||||
|
|
35
Makefile.msc
35
Makefile.msc
|
@ -115,6 +115,14 @@ USE_RC = 1
|
|||
FOR_WINRT = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to compile binaries suitable for the UAP environment.
|
||||
# This setting does not apply to any binaries that require Tcl to operate
|
||||
# properly (i.e. the text fixture, etc).
|
||||
#
|
||||
!IFNDEF FOR_UAP
|
||||
FOR_UAP = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to skip attempting to look for and/or link with the Tcl
|
||||
# runtime library.
|
||||
#
|
||||
|
@ -288,6 +296,11 @@ BCC = $(BCC) -FAcs
|
|||
#
|
||||
!IF $(USE_NATIVE_LIBPATHS)!=0
|
||||
NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)"
|
||||
|
||||
!IFDEF NUCRTLIBPATH
|
||||
NUCRTLIBPATH = $(NUCRTLIBPATH:\\=\)
|
||||
NLTLIBPATHS = $(NLTLIBPATHS) "/LIBPATH:$(NUCRTLIBPATH)"
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
# C compiler and options for use in building executables that
|
||||
|
@ -708,7 +721,7 @@ LTLIBOPTS = /NOLOGO
|
|||
#
|
||||
!IF $(FOR_WINRT)!=0
|
||||
LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER
|
||||
!IF "$(VISUALSTUDIOVERSION)"=="12.0"
|
||||
!IF "$(VISUALSTUDIOVERSION)"=="12.0" || "$(VISUALSTUDIOVERSION)"=="14.0"
|
||||
!IFNDEF STORELIBPATH
|
||||
!IF "$(PLATFORM)"=="x86"
|
||||
STORELIBPATH = $(CRTLIBPATH)\store
|
||||
|
@ -752,6 +765,16 @@ LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelH
|
|||
LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib
|
||||
!ENDIF
|
||||
|
||||
# When compiling for UAP, some extra linker options are also required.
|
||||
#
|
||||
!IF $(FOR_UAP)!=0
|
||||
LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE /NODEFAULTLIB:kernel32.lib
|
||||
LTLINKOPTS = $(LTLINKOPTS) mincore.lib
|
||||
!IFDEF PSDKLIBPATH
|
||||
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(PSDKLIBPATH)"
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
# If either debugging or symbols are enabled, enable PDBs.
|
||||
#
|
||||
!IF $(DEBUG)>1 || $(SYMBOLS)!=0
|
||||
|
@ -1159,12 +1182,15 @@ sqlite3.exe: $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
|
|||
sqldiff.exe: $(TOP)\tool\sqldiff.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) $(TOP)\tool\sqldiff.c sqlite3.c
|
||||
|
||||
fuzzershell.exe: $(TOP)\tool\fuzzershell.c sqlite3.c sqlite3.h
|
||||
$(LTLINK) $(TOP)\tool\fuzzershell.c sqlite3.c
|
||||
|
||||
mptester.exe: $(TOP)\mptest\mptest.c $(SHELL_CORE_DEP) $(LIBRESOBJS) sqlite3.h
|
||||
$(LTLINK) $(SHELL_COMPILE_OPTS) $(TOP)\mptest\mptest.c \
|
||||
/link $(LTLINKOPTS) $(LTLIBPATHS) $(SHELL_LINK_OPTS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
|
||||
|
||||
MPTEST1 = mptester mptest.db $(TOP)/mptest/crash01.test --repeat 20
|
||||
MPTEST2 = mptester mptest.db $(TOP)/mptest/multiwrite01.test --repeat 20
|
||||
MPTEST1 = mptester mptest.db $(TOP)\mptest\crash01.test --repeat 20
|
||||
MPTEST2 = mptester mptest.db $(TOP)\mptest\multiwrite01.test --repeat 20
|
||||
|
||||
mptest: mptester.exe
|
||||
del /Q mptest.db 2>NUL
|
||||
|
@ -1613,6 +1639,9 @@ queryplantest: testfixture.exe sqlite3.exe
|
|||
test: testfixture.exe sqlite3.exe
|
||||
.\testfixture.exe $(TOP)\test\veryquick.test
|
||||
|
||||
smoketest: testfixture.exe
|
||||
.\testfixture.exe $(TOP)\test\main.test
|
||||
|
||||
sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\test_stat.c $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
|
||||
copy $(SQLITE3C) + $(TOP)\src\test_stat.c + $(TOP)\src\tclsqlite.c $@
|
||||
echo static const char *tclsh_main_loop(void){ >> $@
|
||||
|
|
|
@ -2810,7 +2810,7 @@ static int fts3SegReaderCursor(
|
|||
** calls out here. */
|
||||
if( iLevel<0 && p->aIndex ){
|
||||
Fts3SegReader *pSeg = 0;
|
||||
rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg);
|
||||
rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg);
|
||||
if( rc==SQLITE_OK && pSeg ){
|
||||
rc = fts3SegReaderCursorAppend(pCsr, pSeg);
|
||||
}
|
||||
|
@ -3459,11 +3459,31 @@ static void fts3ReversePoslist(char *pStart, char **ppPoslist){
|
|||
char *p = &(*ppPoslist)[-2];
|
||||
char c = 0;
|
||||
|
||||
/* Skip backwards passed any trailing 0x00 bytes added by NearTrim() */
|
||||
while( p>pStart && (c=*p--)==0 );
|
||||
|
||||
/* Search backwards for a varint with value zero (the end of the previous
|
||||
** poslist). This is an 0x00 byte preceded by some byte that does not
|
||||
** have the 0x80 bit set. */
|
||||
while( p>pStart && (*p & 0x80) | c ){
|
||||
c = *p--;
|
||||
}
|
||||
if( p>pStart ){ p = &p[2]; }
|
||||
assert( p==pStart || c==0 );
|
||||
|
||||
/* At this point p points to that preceding byte without the 0x80 bit
|
||||
** set. So to find the start of the poslist, skip forward 2 bytes then
|
||||
** over a varint.
|
||||
**
|
||||
** Normally. The other case is that p==pStart and the poslist to return
|
||||
** is the first in the doclist. In this case do not skip forward 2 bytes.
|
||||
** The second part of the if condition (c==0 && *ppPoslist>&p[2])
|
||||
** is required for cases where the first byte of a doclist and the
|
||||
** doclist is empty. For example, if the first docid is 10, a doclist
|
||||
** that begins with:
|
||||
**
|
||||
** 0x0A 0x00 <next docid delta varint>
|
||||
*/
|
||||
if( p>pStart || (c==0 && *ppPoslist>&p[2]) ){ p = &p[2]; }
|
||||
while( *p++&0x80 );
|
||||
*ppPoslist = p;
|
||||
}
|
||||
|
@ -4597,12 +4617,14 @@ static void fts3EvalStartReaders(
|
|||
){
|
||||
if( pExpr && SQLITE_OK==*pRc ){
|
||||
if( pExpr->eType==FTSQUERY_PHRASE ){
|
||||
int i;
|
||||
int nToken = pExpr->pPhrase->nToken;
|
||||
for(i=0; i<nToken; i++){
|
||||
if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
|
||||
if( nToken ){
|
||||
int i;
|
||||
for(i=0; i<nToken; i++){
|
||||
if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
|
||||
}
|
||||
pExpr->bDeferred = (i==nToken);
|
||||
}
|
||||
pExpr->bDeferred = (i==nToken);
|
||||
*pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase);
|
||||
}else{
|
||||
fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc);
|
||||
|
@ -5765,7 +5787,8 @@ int sqlite3Fts3EvalPhrasePoslist(
|
|||
pIter = pPhrase->pOrPoslist;
|
||||
iDocid = pPhrase->iOrDocid;
|
||||
if( pCsr->bDesc==bDescDoclist ){
|
||||
bEof = (pIter >= (pPhrase->doclist.aAll + pPhrase->doclist.nAll));
|
||||
bEof = !pPhrase->doclist.nAll ||
|
||||
(pIter >= (pPhrase->doclist.aAll + pPhrase->doclist.nAll));
|
||||
while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
|
||||
sqlite3Fts3DoclistNext(
|
||||
bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
|
||||
|
|
|
@ -279,9 +279,9 @@ static void testFunc(
|
|||
p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
|
||||
|
||||
if( !p ){
|
||||
char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
char *zErr2 = sqlite3_mprintf("unknown tokenizer: %s", zName);
|
||||
sqlite3_result_error(context, zErr2, -1);
|
||||
sqlite3_free(zErr2);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -326,7 +326,7 @@ static int fts3SqlStmt(
|
|||
/* 25 */ "",
|
||||
|
||||
/* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
|
||||
/* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'",
|
||||
/* 27 */ "SELECT ? UNION SELECT level / (1024 * ?) FROM %Q.'%q_segdir'",
|
||||
|
||||
/* This statement is used to determine which level to read the input from
|
||||
** when performing an incremental merge. It returns the absolute level number
|
||||
|
@ -3444,7 +3444,8 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
|
|||
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
int rc2;
|
||||
sqlite3_bind_int(pAllLangid, 1, p->nIndex);
|
||||
sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
|
||||
sqlite3_bind_int(pAllLangid, 2, p->nIndex);
|
||||
while( sqlite3_step(pAllLangid)==SQLITE_ROW ){
|
||||
int i;
|
||||
int iLangid = sqlite3_column_int(pAllLangid, 0);
|
||||
|
@ -4776,7 +4777,7 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
|
|||
pHint->n = i;
|
||||
i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
|
||||
i += fts3GetVarint32(&pHint->a[i], pnInput);
|
||||
if( i!=nHint ) return SQLITE_CORRUPT_VTAB;
|
||||
if( i!=nHint ) return FTS_CORRUPT_VTAB;
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
@ -5144,7 +5145,8 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
|
|||
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
int rc2;
|
||||
sqlite3_bind_int(pAllLangid, 1, p->nIndex);
|
||||
sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
|
||||
sqlite3_bind_int(pAllLangid, 2, p->nIndex);
|
||||
while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){
|
||||
int iLangid = sqlite3_column_int(pAllLangid, 0);
|
||||
int i;
|
||||
|
@ -5157,7 +5159,6 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
|
|||
}
|
||||
|
||||
/* This block calculates the checksum according to the %_content table */
|
||||
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule;
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
|
@ -5254,7 +5255,7 @@ static int fts3DoIntegrityCheck(
|
|||
int rc;
|
||||
int bOk = 0;
|
||||
rc = fts3IntegrityCheck(p, &bOk);
|
||||
if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB;
|
||||
if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -876,7 +876,7 @@ static fuzzer_stem *fuzzerNewStem(
|
|||
if( pNew==0 ) return 0;
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
pNew->zBasis = (char*)&pNew[1];
|
||||
pNew->nBasis = (int)strlen(zWord);
|
||||
pNew->nBasis = (fuzzer_len)strlen(zWord);
|
||||
memcpy(pNew->zBasis, zWord, pNew->nBasis+1);
|
||||
pRule = pCur->pVtab->pRule;
|
||||
while( fuzzerSkipRule(pRule, pNew, pCur->iRuleset) ){
|
||||
|
|
4
main.mk
4
main.mk
|
@ -412,6 +412,10 @@ sqldiff$(EXE): $(TOP)/tool/sqldiff.c sqlite3.c sqlite3.h
|
|||
$(TCCX) -o sqldiff$(EXE) -DSQLITE_THREADSAFE=0 \
|
||||
$(TOP)/tool/sqldiff.c sqlite3.c $(TLIBS) $(THREADLIB)
|
||||
|
||||
fuzzershell$(EXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h
|
||||
$(TCCX) -o fuzzershell$(EXE) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION\
|
||||
$(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) $(THREADLIB)
|
||||
|
||||
mptester$(EXE): sqlite3.c $(TOP)/mptest/mptest.c
|
||||
$(TCCX) -o $@ -I. $(TOP)/mptest/mptest.c sqlite3.c \
|
||||
$(TLIBS) $(THREADLIB)
|
||||
|
|
154
manifest
154
manifest
|
@ -1,9 +1,9 @@
|
|||
C Fix\sa\sperformance\sproblem\sin\scalls\sto\ssqlite3ota_close()\smade\safter\sthe\sOTA\supdate\shas\sbeen\scompletely\sapplied\sand\scheckpointed.
|
||||
D 2015-04-23T19:18:42.820
|
||||
C Merge\slatest\strunk\schanges\sinto\sthis\sbranch.
|
||||
D 2015-04-23T19:32:19.839
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 79b306896135a2305cfb7e6d88990fc4820fb917
|
||||
F Makefile.in 34ca00e764c293f3a75208b607b4083a90a1bccf
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
F Makefile.msc 0078f5781538e07ea38683439f38d5f5ab79ab6e
|
||||
F Makefile.msc 32d8fe89ac5c130f9f14293fb4a59b120895c943
|
||||
F Makefile.vxworks e1b65dea203f054e71653415bd8f96dcaed47858
|
||||
F README.md d58e3bebc0a4145e0f2a87994015fdb575a8e866
|
||||
F VERSION 2e244662b71e6e68a5c29b014ebc5b7564f4cc5a
|
||||
|
@ -78,7 +78,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
|||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c 4bd75289875b63c04f943d6ed7c31737da99cd74
|
||||
F ext/fts3/fts3.c 81f9ed55ad58614828ad9d8b1e0525ad78fede1b
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h 3626655d6ba903a3919bb44e1c38e5f0f9d6be82
|
||||
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
|
||||
|
@ -91,12 +91,12 @@ F ext/fts3/fts3_snippet.c 52c2dcf410b1f9af5a44d81a2cf8c68ed1cb5283
|
|||
F ext/fts3/fts3_term.c a521f75132f9a495bdca1bdd45949b3191c52763
|
||||
F ext/fts3/fts3_test.c 8a3a78c4458b2d7c631fcf4b152a5cd656fa7038
|
||||
F ext/fts3/fts3_tokenize_vtab.c becc661223db7898b213f9e8a23d75bac02408c9
|
||||
F ext/fts3/fts3_tokenizer.c b7e586baeb8d0a061cf01a0f7081d88f3935eecf
|
||||
F ext/fts3/fts3_tokenizer.c 9afd223b07740b14dd589edd3116acacf951fd78
|
||||
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
|
||||
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
|
||||
F ext/fts3/fts3_unicode.c a93f5edc0aff44ef8b06d7cb55b52026541ca145
|
||||
F ext/fts3/fts3_unicode2.c c3d01968d497bd7001e7dc774ba75b372738c057
|
||||
F ext/fts3/fts3_write.c 7104ec015474ee61a8a570349b925f35c6b0a294
|
||||
F ext/fts3/fts3_write.c 4f005f78592a1447ca96c8475ef5342ab7dbe02a
|
||||
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
|
||||
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
|
||||
F ext/fts3/tool/fts3view.c 8e53d0190a7b3443764bbd32ad47be2bd852026d
|
||||
|
@ -111,7 +111,7 @@ F ext/misc/closure.c 636024302cde41b2bf0c542f81c40c624cfb7012
|
|||
F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
|
||||
F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
|
||||
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
|
||||
F ext/misc/fuzzer.c e3e18f47252c151b5553d7e806f38e757d37c4cc
|
||||
F ext/misc/fuzzer.c 4c84635c71c26cfa7c2e5848cf49fe2d2cfcd767
|
||||
F ext/misc/ieee754.c b0362167289170627659e84173f5d2e8fee8566e
|
||||
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
|
||||
|
@ -171,7 +171,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
|||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 95e9c8295b3ce06c0cbe6977b2b3ed8407cfe217
|
||||
F main.mk e58fe4b049a08b1fa73567790495b70f686f6162
|
||||
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
|
||||
F mkopcodeh.awk d5e22023b5238985bb54a72d33e0ac71fe4f8a32
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
|
@ -179,37 +179,37 @@ F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
|||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
|
||||
F mptest/crash02.subtest f4ef05adcd15d60e5d2bd654204f2c008b519df8
|
||||
F mptest/mptest.c dae6de83eddac3ef97fc4111632f6066760f939a
|
||||
F mptest/mptest.c fca59f0a922e03f95ed17c44b1515ed37a841c81
|
||||
F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
|
||||
F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c d23d6b6991f66b383934f137fd4384d93fb98c81
|
||||
F src/analyze.c 91540f835163d5369ccbae78e2e6c74d0dd53c1d
|
||||
F src/attach.c 3c1053a4cf1c3ca05c8c1d74a94cb688d763cef2
|
||||
F src/analyze.c d23790787f80ebed58df7774744b4cf96401498b
|
||||
F src/attach.c c38ac5a520a231d5d0308fd7f2ad95191c867bae
|
||||
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
|
||||
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
|
||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
|
||||
F src/btree.c 67648f6532c2da79d3b3fb6853aa1a0c3ba0e1ad
|
||||
F src/btree.c 127aceb71ba93f59bc9c6ba810e992a04299e98a
|
||||
F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
|
||||
F src/btreeInt.h 973a22a6fd61350b454ad614832b1f0a5e25a1e4
|
||||
F src/build.c 01b969b20a44a3d9620e597d9af8242348123540
|
||||
F src/build.c e246c2cea69c8f6fc825a156ea2de9dd4a17f18b
|
||||
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
|
||||
F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575
|
||||
F src/ctime.c 98f89724adc891a1a4c655bee04e33e716e05887
|
||||
F src/date.c e4d50b3283696836ec1036b695ead9a19e37a5ac
|
||||
F src/delete.c 37964e6c1d73ff49cbea9ff690c9605fb15f600e
|
||||
F src/expr.c 8800584340a9b4f4c0ca55c360de751c6da0b11a
|
||||
F src/expr.c 4c05a28eebe63b288fda1db0e8de556a82ca2ec6
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 3343d551a8d810782257244fb33f2ce191493c39
|
||||
F src/fkey.c c9b63a217d86582c22121699a47f22f524608869
|
||||
F src/func.c 1414c24c873c48796ad45942257a179a423ba42f
|
||||
F src/global.c 4f77cadbc5427d00139ba43d0f3979804cbb700e
|
||||
F src/hash.c 4263fbc955f26c2e8cdc0cf214bc42435aa4e4f5
|
||||
F src/hash.h c8f3c31722cf3277d03713909761e152a5b81094
|
||||
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
|
||||
F src/insert.c 305dd3f9539d0affa4bf1c14cc7dffb34867e040
|
||||
F src/insert.c 8176ba5bad8fcef643558ca5708f33ed05a4035a
|
||||
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c ba1863ea58c4c840335a84ec276fc2b25e22bc4e
|
||||
F src/lempar.c 7274c97d24bb46631e504332ccd3bd1b37841770
|
||||
|
@ -236,29 +236,29 @@ F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
|
|||
F src/os_unix.c 5ed7e2e453c2980909a6b2c80dc55764b50819a8
|
||||
F src/os_win.c 03d27be3a20048ef52a648d5f0a15f5edda9f2a3
|
||||
F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca
|
||||
F src/pager.c 4120a49ecd37697e28f5ed807f470b9c0b88410c
|
||||
F src/pager.c 5283581c8ce8950ff483a0b3a3cab9cb4d25a21e
|
||||
F src/pager.h c3476e7c89cdf1c6914e50a11f3714e30b4e0a77
|
||||
F src/parse.y 1299c66e7b1707322ccd8af43a359b8fb0d46d72
|
||||
F src/parse.y c4e0387bc88c8e21e5ba653e2578959a1f3cdbc7
|
||||
F src/pcache.c 10539fb959849ad6efff80050541cab3d25089d4
|
||||
F src/pcache.h b44658c9c932d203510279439d891a2a83e12ba8
|
||||
F src/pcache1.c 69d137620a305f814398bd29a0c998038c0695e9
|
||||
F src/pragma.c 3965ae4e82bed39fb97ce04c5fe18c9bc3ee6a88
|
||||
F src/pragma.c c1f4d012ea9f6b1ce52d341b2cd0ad72d560afd7
|
||||
F src/pragma.h 09c89bca58e9a44de2116cc8272b8d454657129f
|
||||
F src/prepare.c 173a5a499138451b2561614ecb87d78f9f4644b9
|
||||
F src/prepare.c 1fffbdcd6f8a0173a8f70d71f22528f4c0e1e3d3
|
||||
F src/printf.c 08fa675c200aac29e561c6153f91f909ed17612f
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c 66cfe49a9c3b449ef13b89a8c47036a4ed167eab
|
||||
F src/resolve.c 13109bc3b5ab404446296efa17039640de5bc35d
|
||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||
F src/select.c 93260bc9e7e0e6dfe1b7cb8815b0ed4cad8be9e3
|
||||
F src/shell.c 84a1593bd86aaa14f4da8a8f9b16fbc239d262aa
|
||||
F src/select.c 35433ea8894ac42594ddc31eb0165a6d6401cfe5
|
||||
F src/shell.c 78eabce4c16c45e36fea2368f95118116399ba8a
|
||||
F src/sqlite.h.in 3be4d9a7d38ef83fadd4aadd7ef3c6039e165da7
|
||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
|
||||
F src/sqliteInt.h 90b7bfd89d7307cd0750663da419ba4bb81e7379
|
||||
F src/sqliteInt.h 8abcea1295138f10ef8f7ed38db5f1b573b93ece
|
||||
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
|
||||
F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179
|
||||
F src/table.c e7a09215315a978057fb42c640f890160dbcc45e
|
||||
F src/tclsqlite.c 796b427293e8f0e2769d3956c23df66880fe5535
|
||||
F src/tclsqlite.c 9ac7a3ee50a14e7aa4cbd35a6fb5c7c1bbf89e16
|
||||
F src/test1.c 90fbedce75330d48d99eadb7d5f4223e86969585
|
||||
F src/test2.c 577961fe48961b2f2e5c8b56ee50c3f459d3359d
|
||||
F src/test3.c 64d2afdd68feac1bb5e2ffb8226c8c639f798622
|
||||
|
@ -284,12 +284,12 @@ F src/test_intarray.c 6c610a21ab8edde85a3a2c7f2b069244ecf4d834
|
|||
F src/test_intarray.h 9dc57417fb65bc7835cc18548852cc08cc062202
|
||||
F src/test_journal.c 5360fbe1d1e4416ca36290562fd5a2e3f70f32aa
|
||||
F src/test_loadext.c a5251f956ab6af21e138dc1f9c0399394a510cb4
|
||||
F src/test_malloc.c b9495384e74923aefde8311de974bf9b0f5ba570
|
||||
F src/test_multiplex.c 97813565daa7ee480abcc5dd1e9984ed1f71eb8c
|
||||
F src/test_malloc.c 208f09a4e21defa496bc1094fcfadea19385a112
|
||||
F src/test_multiplex.c 4dfb159e5c280c0ebdbf8b5ab9d95bf2765061f9
|
||||
F src/test_multiplex.h c08e4e8f8651f0c5e0509b138ff4d5b43ed1f5d3
|
||||
F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f
|
||||
F src/test_onefile.c 0396f220561f3b4eedc450cef26d40c593c69a25
|
||||
F src/test_osinst.c 3d0340bc31a9f3d8a3547e0272373e80f78dde25
|
||||
F src/test_onefile.c 38f7cbe79d5bafe95bde683cc3a53b8ca16daf10
|
||||
F src/test_osinst.c 5423dc1d355f594371f27dd292ca54bd320b8196
|
||||
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
|
||||
F src/test_quota.c 180813f43683be5725458fc1ff13ac455d8e722d
|
||||
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
|
||||
|
@ -302,31 +302,31 @@ F src/test_superlock.c 06797157176eb7085027d9dd278c0d7a105e3ec9
|
|||
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
|
||||
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
|
||||
F src/test_thread.c af391ec03d23486dffbcc250b7e58e073f172af9
|
||||
F src/test_vfs.c b7e6831e6fcf04c5090accff30640ec5c9630739
|
||||
F src/test_vfs.c 3b65d42e18b262805716bd96178c81da8f2d9283
|
||||
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 6bbcc9fe50c917864d48287b4792d46d6e873481
|
||||
F src/tokenize.c a8234a67577308935cdf13e618cd66556f5f45d1
|
||||
F src/trigger.c 69a91bed7c94e46223e37ffccfeeb35e34b999ac
|
||||
F src/tokenize.c b7fb584c2be5ec39b6fdf04b185e7c6f33f8dc15
|
||||
F src/trigger.c 322f23aad694e8f31d384dcfa386d52a48d3c52f
|
||||
F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13
|
||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||
F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e
|
||||
F src/util.c a6431c92803b975b7322724a7b433e538d243539
|
||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||
F src/vdbe.c 3f3afd12d4794cb51fe13dc948b1172a5eb71a94
|
||||
F src/vdbe.c f0cf3cf527d5a40b8d5d2324fdbb31da6c90cd8b
|
||||
F src/vdbe.h 7e538ecf47dccb307ea2d087c3ddc2dd8d70e79d
|
||||
F src/vdbeInt.h 9cbaa84f53ddd2d09a0cf61a94337a3a035d08a0
|
||||
F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75
|
||||
F src/vdbeaux.c a20504ae52392459fa08402fda3f195f19d7c79d
|
||||
F src/vdbeaux.c 03591cca98ec50e1493043f0ff7abbece0b9c83d
|
||||
F src/vdbeblob.c 4f2e8e075d238392df98c5e03a64342465b03f90
|
||||
F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9
|
||||
F src/vdbemem.c b5256445b318b0f2b3bc429028469cfbb08f19a5
|
||||
F src/vdbesort.c 2e7f683464fd5db3be4beaa1ff2d39e24fcb64b8
|
||||
F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010
|
||||
F src/vtab.c 9ca557215e8591ceb66e0b7c0a579c6df1e54b2d
|
||||
F src/vdbetrace.c f95c2dff9041fcf07f871789c22ebb0648ea0b7c
|
||||
F src/vtab.c 5f81f8a59c1f5ddb94c918f25ed5d83578fcc633
|
||||
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
|
||||
F src/wal.c 753995db83247f20361a8e8a874990b21a75abd9
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
|
||||
F src/where.c 7e5d9a5690e71c39bfc4afea9f351766299dbf2f
|
||||
F src/where.c 80998bcd8929d2d098ee8d68a81215d5a22ef127
|
||||
F src/whereInt.h 1fca2f8c649f0ee38fd52332659d0e7deb11d428
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
|
@ -339,8 +339,8 @@ F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
|
|||
F test/alter4.test c461150723ac957f3b2214aa0b11552cd72023ec
|
||||
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/analyze.test 1772936d66471c65221e437b6d1999c3a03166c4
|
||||
F test/analyze3.test 75b9e42ea1e4edc919250450dc5762186965d4e6
|
||||
F test/analyze.test 3eb35a4af972f98422e5dc0586501b17d103d321
|
||||
F test/analyze3.test 0f0ee6135b293a0e5af471a8423b80b688469d71
|
||||
F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
|
||||
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
|
||||
F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f
|
||||
|
@ -445,7 +445,7 @@ F test/corrupt8.test 2399dfe40d2c0c63af86706e30f3e6302a8d0516
|
|||
F test/corrupt9.test 730a3db08d4ab9aa43392ea30d9c2b4879cbff85
|
||||
F test/corruptA.test 53e56dafd180addcdadb402244b8cb9771d2ba26
|
||||
F test/corruptB.test 73a8d6c0b9833697ecf16b63e3c5c05c945b5dec
|
||||
F test/corruptC.test 02405cf7ed0c1e989060e1aab6d02ffbc3906fbb
|
||||
F test/corruptC.test 3fcc0f73d2cf2d69befe2d96332b942426a6aae2
|
||||
F test/corruptD.test b3c205fac7952b1de645ce44bb02335cd9e3e040
|
||||
F test/corruptE.test 193b4ca4e927e77c1d5f4f56203ddc998432a7ee
|
||||
F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
|
||||
|
@ -454,7 +454,7 @@ F test/corruptH.test 5dd4fa98c6c1ed33b178f9e8a48c4fdd3cfc9067
|
|||
F test/corruptI.test 221ad8b7f0a9ac6b80fc577e73b5ad8cdea31243
|
||||
F test/corruptJ.test 9e29e7a81ee3b6ac50f77ea7a9e2f3fa03f32d91
|
||||
F test/cost.test 19d314526616ce4473eb4e4e450fcb94499ce318
|
||||
F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5
|
||||
F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
|
||||
F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62
|
||||
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
|
||||
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
|
||||
|
@ -495,7 +495,7 @@ F test/e_expr.test 8f5fdd7261e2d746813b0c6a1c0e34824ad3c5ad
|
|||
F test/e_fkey.test a1783fe1f759e1990e6a11adfcf0702dac4d0707
|
||||
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
|
||||
F test/e_insert.test 0e63edc037afe738bb81a626a676811ed7862c90
|
||||
F test/e_reindex.test 396b7b4f0a66863b4e95116a67d93b227193e589
|
||||
F test/e_reindex.test 57d439f6c644befc8274ac93cf2f5449cf2736c1
|
||||
F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
|
||||
F test/e_select.test 52692ff3849541e828ad4661fe3773a9b8711763
|
||||
F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
|
||||
|
@ -518,13 +518,13 @@ F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
|
|||
F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308
|
||||
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
||||
F test/exists.test 8f7b27b61c2fbe5822f0a1f899c715d14e416e30
|
||||
F test/expr.test c4b9bf0cc60b26862475e19999fbd2609ca8259c
|
||||
F test/expr.test 79c3e7502d9e571553b85f0ecc8ff2ac7d0e4931
|
||||
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
|
||||
F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
|
||||
F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a
|
||||
F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146
|
||||
F test/fkey1.test e1d1fa84cde579185ea01358436839703e415a5b
|
||||
F test/fkey2.test 223c624e7eccee21e89c98d4d127ac88d774b940
|
||||
F test/fkey1.test de5b287f6a480b36bd51e8debcf48168e26e4ed2
|
||||
F test/fkey2.test f3d27ecba480a348c328965d154214719bb158a9
|
||||
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
|
||||
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
|
||||
F test/fkey5.test 56bcb5a6e8b725b17febc267fb041a6695e86853
|
||||
|
@ -570,7 +570,7 @@ F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e
|
|||
F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a
|
||||
F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
|
||||
F test/fts3_common.tcl 99cf6659b87c0f74f55963c2aea03b3a7d66ceb0
|
||||
F test/fts3aa.test edd20ddbbc5b6015ab340abf2ca278ae11ec387d
|
||||
F test/fts3aa.test 6c263a6f8845205ee02550981a94c2e8dc1e7058
|
||||
F test/fts3ab.test 7f6cf260ae80dda064023df8e8e503e9a412b91f
|
||||
F test/fts3ac.test 636ed7486043055d4f126a0e385f2d5a82ebbf63
|
||||
F test/fts3ad.test e40570cb6f74f059129ad48bcef3d7cbc20dda49
|
||||
|
@ -606,6 +606,7 @@ F test/fts3expr.test 3401d47b229c4504424caf362cc4ff704cad4162
|
|||
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
|
||||
F test/fts3expr3.test 9e91b8edbcb197bf2e92161aa7696446d96dce5f
|
||||
F test/fts3expr4.test e1be1248566f43c252d4404d52914f1fc4bfa065
|
||||
F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49
|
||||
F test/fts3fault.test cb72dccb0a3b9f730f16c5240f3fcb9303eb1660
|
||||
F test/fts3fault2.test f953bb3cf903988172270a9a0aafd5a890b0f98f
|
||||
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
|
||||
|
@ -624,7 +625,7 @@ F test/fts3tok1.test 178c050199af8c05299b1ad572514ce1c54b7827
|
|||
F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d
|
||||
F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e
|
||||
F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb
|
||||
F test/fts4check.test 74d77f6cdb768ac49df5afda575cef14ae3d239a
|
||||
F test/fts4check.test 9d9e818fd6cb29c0e007cd6d00447739d4fde430
|
||||
F test/fts4content.test abb0c77bc3da3df64fec72e00844d2257a90025d
|
||||
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
|
||||
F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53
|
||||
|
@ -674,18 +675,18 @@ F test/incrvacuum3.test 75256fb1377e7c39ef2de62bfc42bbff67be295a
|
|||
F test/incrvacuum_ioerr.test 6ae2f783424e47a0033304808fe27789cf93e635
|
||||
F test/index.test 4d990005a67a36984e4f1a5f1bdccea8d08da4ee
|
||||
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
|
||||
F test/index3.test 55a90cff99834305e8141df7afaef39674b57062
|
||||
F test/index3.test b6ec456cf3b81d9a32123fe7e449bde434db338b
|
||||
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
|
||||
F test/index5.test 25b0b451aceed4ac5f7d49f856f6de7257470b3e
|
||||
F test/index6.test 3ae54e53c53f2adcacda269237d8e52bdb05a481
|
||||
F test/index7.test 3d54dce09344c4530ea39a458aa304da044c887a
|
||||
F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c
|
||||
F test/indexedby.test 5f527a78bae74c61b8046ae3037f9dfb0bf0c353
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
|
||||
F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
|
||||
F test/insert2.test 4d14b8f1b810a41995f6286b64a6943215d52208
|
||||
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
|
||||
F test/insert4.test 4791662c50518bdd37d394cae9a7a8014e845bb3
|
||||
F test/insert4.test a20432f1c0fbbcff8f11d0e6ab4acb8c9db58023
|
||||
F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
|
||||
F test/instr.test 737bbf80685232033f3abedc6ae92f75860b5dd2
|
||||
F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4
|
||||
|
@ -762,11 +763,11 @@ F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd
|
|||
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
|
||||
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
|
||||
F test/minmax4.test 936941484ebdceb8adec7c86b6cd9b6e5e897c1f
|
||||
F test/misc1.test 9abcae9a0b8785d6fa92925dbb19c309ae9ea077
|
||||
F test/misc1.test 783ba75743b2cf71e0f646bf540a6cef57264811
|
||||
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
|
||||
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
|
||||
F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
|
||||
F test/misc5.test 528468b26d03303b1f047146e5eefc941b9069f5
|
||||
F test/misc5.test f96428ea95b3820aafc6f1c50cf48a09e4597ee1
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test edd0b63e2ee29a256900b0514f6fff27e19e9bb2
|
||||
F test/misc8.test fc2754d38892f7dac30c22db3616c2764f117d66
|
||||
|
@ -814,7 +815,7 @@ F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
|
|||
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test 0e2dc2aab7b1043bd2b4404f51651c31da007e52
|
||||
F test/pragma.test e6605ce89c66db930aef561e43a22281a09ffc66
|
||||
F test/pragma.test be7195f0aa72bdb8a512133e9640ac40f15b57a2
|
||||
F test/pragma2.test f624a496a95ee878e81e59961eade66d5c00c028
|
||||
F test/pragma3.test 6f849ccffeee7e496d2f2b5e74152306c0b8757c
|
||||
F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
|
||||
|
@ -832,8 +833,8 @@ F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
|
|||
F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.tcl b290782d0697b4e83d671da192cd9a7f71e2f6c1
|
||||
F test/resolver01.test 33abf37ff8335e6bf98f2b45a0af3e06996ccd9a
|
||||
F test/releasetest.tcl 1ed00e5e59cde1147868d458fb236f302ce64289
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
|
||||
F test/rollback2.test fc14cf6d1a2b250d2735ef16124b971bce152f14
|
||||
F test/rollbackfault.test 6a004f71087cc399296cffbb5429ea6da655ae65
|
||||
|
@ -856,10 +857,10 @@ F test/schema4.test e6a66e20cc69f0e306667c08be7fda3d11707dc5
|
|||
F test/schema5.test 29699b4421f183c8f0e88bd28ce7d75d13ea653e
|
||||
F test/securedel.test 21749c32ccc30f1ea9e4b9f33295a6521ec20fa0
|
||||
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
|
||||
F test/select1.test fc2a61f226a649393664ad54bc5376631801517c
|
||||
F test/select1.test be62204d2bd9a5a8a149e9974cfddce893d8f686
|
||||
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
|
||||
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
|
||||
F test/select4.test 16fa1cafb942f42294ec85cbb78954c2f2d15a44
|
||||
F test/select4.test 48e14766d98b744b2202cca6d4679bf7ef3784c8
|
||||
F test/select5.test e758b8ef94f69b111df4cb819008856655dcd535
|
||||
F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
|
||||
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
|
||||
|
@ -920,7 +921,7 @@ F test/spellfix.test 24f676831acddd2f4056a598fd731a72c6311f49
|
|||
F test/sqllimits1.test e05786eaed7950ff6a2d00031d001d8a26131e68
|
||||
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
|
||||
F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
|
||||
F test/subquery.test 666fdecceac258f5fd84bed09a64e49d9f37edd9
|
||||
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
|
||||
F test/subquery2.test 438f8a7da1457277b22e4176510f7659b286995f
|
||||
F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
|
||||
F test/substr.test 18f57c4ca8a598805c4d64e304c418734d843c1a
|
||||
|
@ -928,7 +929,7 @@ F test/superlock.test 1cde669f68d2dd37d6c9bd35eee1d95491ae3fc2
|
|||
F test/sync.test a34cd43e98b7fb84eabbf38f7ed8f7349b3f3d85
|
||||
F test/syscall.test d2fdaad713f103ac611fe7ef9b724c7b69f8149c
|
||||
F test/sysfault.test fa776e60bf46bdd3ae69f0b73e46ee3977a58ae6
|
||||
F test/table.test 06271d61eb13871490d38168433c1ef3dd82bb2a
|
||||
F test/table.test bd841e8df69b99172ce9c7d53587463913d711ca
|
||||
F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
|
||||
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
|
||||
F test/tclsqlite.test 7fb866443c7deceed22b63948ccd6f76b52ad054
|
||||
|
@ -1091,7 +1092,7 @@ F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1
|
|||
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
|
||||
F test/tpch01.test 04adbf8d8300fa60a222f28d901abd76e7be6dd4
|
||||
F test/trace.test 73a5508100f7fccfbc3f8018d5f6963ed478eea0
|
||||
F test/trace2.test 93b47ca6996c66b47f57224cfb146f34e07df382
|
||||
F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983
|
||||
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
|
||||
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
|
||||
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
|
||||
|
@ -1102,12 +1103,12 @@ F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
|
|||
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
|
||||
F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83
|
||||
F test/trigger6.test 0e411654f122552da6590f0b4e6f781048a4a9b9
|
||||
F test/trigger7.test b39e6dee1debe0ff9c2ef66326668f149f07c9c4
|
||||
F test/trigger7.test 200dd51e728c9cdc20c72d99d9e9d45c667248f8
|
||||
F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
|
||||
F test/trigger9.test 2226ec795a33b0460ab5cf8891e9054cc7edef41
|
||||
F test/triggerA.test fe5597f47ee21bacb4936dc827994ed94161e332
|
||||
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
|
||||
F test/triggerC.test a68980c5955d62ee24be6f97129d824f199f9a4c
|
||||
F test/triggerC.test 302d8995f5ffe63bbc15053abb3ef7a39cf5a092
|
||||
F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650
|
||||
F test/triggerE.test 355e9c5cbaed5cd039a60baad1fb2197caeb8e52
|
||||
F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1
|
||||
|
@ -1133,7 +1134,7 @@ F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
|
|||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
F test/view.test f311691d696a5cc27e3c1b875cec1b0866b4ccd9
|
||||
F test/vtab1.test c9dc2a73e93331d70b37ce4b246ef6dc18412fef
|
||||
F test/vtab1.test d1e5ec7a818f1d3f0402382b6a1d0c06071b770f
|
||||
F test/vtab2.test 3644649aa8d1daac57fd541f6a5f914cac59203e
|
||||
F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
|
||||
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
|
||||
|
@ -1142,7 +1143,7 @@ F test/vtab6.test 5f5380c425e52993560ab4763db4f826d2ba7b09
|
|||
F test/vtab7.test ae560ebea870ed04e9aa4177cc302f910faaabb5
|
||||
F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583
|
||||
F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b
|
||||
F test/vtabA.test c86e1990b7e1e2bb34602a06fffa4c69f2b516dc
|
||||
F test/vtabA.test 1317f06a03597eee29f40a49b6c21e1aaba4285f
|
||||
F test/vtabB.test 04df5dc531b9f44d9ca65b9c1b79f12b5922a796
|
||||
F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292
|
||||
F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96
|
||||
|
@ -1216,17 +1217,18 @@ F test/without_rowid6.test db0dbf03c49030aa3c1ba5f618620334bd2baf5f
|
|||
F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda
|
||||
F test/zeroblob.test fb3c0e4ab172d386954deda24c03f500e121d80d
|
||||
F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
|
||||
F tool/build-all-msvc.bat 72e05bc8deca39a547884485c086b915f50a91ed x
|
||||
F tool/build-all-msvc.bat 9058bd90a3c078a3d8c17d40e853aaa0f47885f4 x
|
||||
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
|
||||
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
|
||||
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
|
||||
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
|
||||
F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
|
||||
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
|
||||
F tool/fuzzershell.c bcdca60b54654c8fc25fd215953d9b6bb55fd7d4
|
||||
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
|
||||
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/lemon.c ae5f61e3b164d35955777b20d6febcbaf0950702
|
||||
F tool/lemon.c b9109f59b57e7b6f101c4fe644c8361ba6dee969
|
||||
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
|
||||
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
|
||||
F tool/mkautoconfamal.sh d1a2da0e15b2ed33d60af35c7e9d483f13a8eb9f
|
||||
|
@ -1238,14 +1240,14 @@ F tool/mksqlite3c-noext.tcl 69bae8ce4aa52d2ff82d4a8a856bf283ec035b2e
|
|||
F tool/mksqlite3c.tcl 9f664f73301ad91ab8ff8886f35152293c564b17
|
||||
F tool/mksqlite3h.tcl 44730d586c9031638cdd2eb443b801c0d2dbd9f8
|
||||
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
|
||||
F tool/mkvsix.tcl 52a4c613707ac34ae9c226e5ccc69cb948556105
|
||||
F tool/mkvsix.tcl 3b58b9398f91c7dbf18d49eb87cefeee9efdbce1
|
||||
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
|
||||
F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97
|
||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
|
||||
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
|
||||
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
|
||||
F tool/showdb.c 63cdef19e7fbca0c164b096ef8aef3bb9e9dd222
|
||||
F tool/showdb.c 3b5d335d537e4dc44d0c86967023819453c87dc6
|
||||
F tool/showjournal.c 053eb1cc774710c6890b7dd6293300cc297b16a5
|
||||
F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
|
||||
F tool/showstat4.c 9515faa8ec176599d4a8288293ba8ec61f7b728a
|
||||
|
@ -1259,7 +1261,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
|||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
||||
F tool/sqldiff.c 5c16cf3a1f566873abbdecac0d13a6691437564f
|
||||
F tool/sqldiff.c 393b0f5b17ef29341664563a90d40ee63a0a18f7
|
||||
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
||||
F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
|
||||
|
@ -1270,7 +1272,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
|||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P baee3556ea10d96f1623cf4dce112fa1a1070820
|
||||
R 3707e9567587057d1905ac3053e5ac43
|
||||
P fa62093b2531424846ea500c4155170d1bc7110e b5e43602833249aa4b73337bf85b7f308450dab6
|
||||
R c95117e2851354f4fbc699c1409b62e5
|
||||
U dan
|
||||
Z 69c7c4a32a6fe3149d703bd1c7c578ac
|
||||
Z 4eaccde899eceec56aac43725e359315
|
||||
|
|
|
@ -1 +1 @@
|
|||
fa62093b2531424846ea500c4155170d1bc7110e
|
||||
1506e99eca19f72fb59b55ec9e2534505dfa7a6e
|
|
@ -53,6 +53,13 @@
|
|||
# define GETPID getpid
|
||||
#endif
|
||||
|
||||
/* The directory separator character(s) */
|
||||
#if defined(_WIN32)
|
||||
# define isDirSep(c) (((c) == '/') || ((c) == '\\'))
|
||||
#else
|
||||
# define isDirSep(c) ((c) == '/')
|
||||
#endif
|
||||
|
||||
/* Mark a parameter as unused to suppress compiler warnings */
|
||||
#define UNUSED_PARAMETER(x) (void)x
|
||||
|
||||
|
@ -824,7 +831,7 @@ static void waitForClient(int iClient, int iTimeout, char *zErrPrefix){
|
|||
*/
|
||||
static char *filenameTail(char *z){
|
||||
int i, j;
|
||||
for(i=j=0; z[i]; i++) if( z[i]=='/' ) j = i+1;
|
||||
for(i=j=0; z[i]; i++) if( isDirSep(z[i]) ) j = i+1;
|
||||
return z+j;
|
||||
}
|
||||
|
||||
|
@ -1021,9 +1028,9 @@ static void runScript(
|
|||
char *zNewFile, *zNewScript;
|
||||
char *zToDel = 0;
|
||||
zNewFile = azArg[0];
|
||||
if( zNewFile[0]!='/' ){
|
||||
if( !isDirSep(zNewFile[0]) ){
|
||||
int k;
|
||||
for(k=(int)strlen(zFilename)-1; k>=0 && zFilename[k]!='/'; k--){}
|
||||
for(k=(int)strlen(zFilename)-1; k>=0 && !isDirSep(zFilename[k]); k--){}
|
||||
if( k>0 ){
|
||||
zNewFile = zToDel = sqlite3_mprintf("%.*s/%s", k,zFilename,zNewFile);
|
||||
}
|
||||
|
@ -1231,7 +1238,7 @@ static void usage(const char *argv0){
|
|||
int i;
|
||||
const char *zTail = argv0;
|
||||
for(i=0; argv0[i]; i++){
|
||||
if( argv0[i]=='/' ) zTail = argv0+i+1;
|
||||
if( isDirSep(argv0[i]) ) zTail = argv0+i+1;
|
||||
}
|
||||
fprintf(stderr,"Usage: %s DATABASE ?OPTIONS? ?SCRIPT?\n", zTail);
|
||||
exit(1);
|
||||
|
@ -1338,6 +1345,7 @@ int SQLITE_CDECL main(int argc, char **argv){
|
|||
#endif
|
||||
runSql("PRAGMA journal_mode=%Q;", zJMode);
|
||||
}
|
||||
if( !g.bSync ) trySql("PRAGMA synchronous=OFF");
|
||||
sqlite3_enable_load_extension(g.db, 1);
|
||||
sqlite3_busy_handler(g.db, busyHandler, 0);
|
||||
sqlite3_create_function(g.db, "vfsname", 0, SQLITE_UTF8, 0,
|
||||
|
@ -1346,7 +1354,6 @@ int SQLITE_CDECL main(int argc, char **argv){
|
|||
evalFunc, 0, 0);
|
||||
g.iTimeout = DEFAULT_TIMEOUT;
|
||||
if( g.bSqlTrace ) sqlite3_trace(g.db, sqlTraceCallback, 0);
|
||||
if( !g.bSync ) trySql("PRAGMA synchronous=OFF");
|
||||
if( iClient>0 ){
|
||||
if( n>0 ) unrecognizedArguments(argv[0], n, argv+2);
|
||||
if( g.iTrace ) logMessage("start-client");
|
||||
|
|
|
@ -1519,14 +1519,17 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
|
|||
z = argv[2];
|
||||
|
||||
if( pIndex ){
|
||||
tRowcnt *aiRowEst = 0;
|
||||
int nCol = pIndex->nKeyCol+1;
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
tRowcnt * const aiRowEst = pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(
|
||||
sizeof(tRowcnt) * nCol
|
||||
);
|
||||
if( aiRowEst==0 ) pInfo->db->mallocFailed = 1;
|
||||
#else
|
||||
tRowcnt * const aiRowEst = 0;
|
||||
/* Index.aiRowEst may already be set here if there are duplicate
|
||||
** sqlite_stat1 entries for this index. In that case just clobber
|
||||
** the old data with the new instead of allocating a new array. */
|
||||
if( pIndex->aiRowEst==0 ){
|
||||
pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol);
|
||||
if( pIndex->aiRowEst==0 ) pInfo->db->mallocFailed = 1;
|
||||
}
|
||||
aiRowEst = pIndex->aiRowEst;
|
||||
#endif
|
||||
pIndex->bUnordered = 0;
|
||||
decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex);
|
||||
|
|
|
@ -332,7 +332,6 @@ static void codeAttach(
|
|||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
|
||||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
|
||||
){
|
||||
pParse->nErr++;
|
||||
goto attach_end;
|
||||
}
|
||||
|
||||
|
|
94
src/btree.c
94
src/btree.c
|
@ -4451,13 +4451,18 @@ static const void *fetchPayload(
|
|||
BtCursor *pCur, /* Cursor pointing to entry to read from */
|
||||
u32 *pAmt /* Write the number of available bytes here */
|
||||
){
|
||||
u32 amt;
|
||||
assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
|
||||
assert( pCur->info.nSize>0 );
|
||||
*pAmt = pCur->info.nLocal;
|
||||
assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB );
|
||||
assert( pCur->info.pPayload<pCur->apPage[pCur->iPage]->aDataEnd ||CORRUPT_DB);
|
||||
amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload);
|
||||
if( pCur->info.nLocal<amt ) amt = pCur->info.nLocal;
|
||||
*pAmt = amt;
|
||||
return (void*)pCur->info.pPayload;
|
||||
}
|
||||
|
||||
|
@ -8523,6 +8528,57 @@ static void checkList(
|
|||
}
|
||||
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
||||
|
||||
/*
|
||||
** An implementation of a min-heap.
|
||||
**
|
||||
** aHeap[0] is the number of elements on the heap. aHeap[1] is the
|
||||
** root element. The daughter nodes of aHeap[N] are aHeap[N*2]
|
||||
** and aHeap[N*2+1].
|
||||
**
|
||||
** The heap property is this: Every node is less than or equal to both
|
||||
** of its daughter nodes. A consequence of the heap property is that the
|
||||
** root node aHeap[1] is always the minimum value current in the heap.
|
||||
**
|
||||
** The btreeHeapInsert() routine inserts an unsigned 32-bit number onto
|
||||
** the heap, preserving the heap property. The btreeHeapPull() routine
|
||||
** removes the root element from the heap (the minimum value in the heap)
|
||||
** and then move other nodes around as necessary to preserve the heap
|
||||
** property.
|
||||
**
|
||||
** This heap is used for cell overlap and coverage testing. Each u32
|
||||
** entry represents the span of a cell or freeblock on a btree page.
|
||||
** The upper 16 bits are the index of the first byte of a range and the
|
||||
** lower 16 bits are the index of the last byte of that range.
|
||||
*/
|
||||
static void btreeHeapInsert(u32 *aHeap, u32 x){
|
||||
u32 j, i = ++aHeap[0];
|
||||
aHeap[i] = x;
|
||||
while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){
|
||||
x = aHeap[j];
|
||||
aHeap[j] = aHeap[i];
|
||||
aHeap[i] = x;
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
static int btreeHeapPull(u32 *aHeap, u32 *pOut){
|
||||
u32 j, i, x;
|
||||
if( (x = aHeap[0])==0 ) return 0;
|
||||
*pOut = aHeap[1];
|
||||
aHeap[1] = aHeap[x];
|
||||
aHeap[x] = 0xffffffff;
|
||||
aHeap[0]--;
|
||||
i = 1;
|
||||
while( (j = i*2)<=aHeap[0] ){
|
||||
if( aHeap[j]>aHeap[j+1] ) j++;
|
||||
if( aHeap[i]<aHeap[j] ) break;
|
||||
x = aHeap[i];
|
||||
aHeap[i] = aHeap[j];
|
||||
aHeap[j] = x;
|
||||
i = j;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
||||
/*
|
||||
** Do various sanity checks on a single page of a tree. Return
|
||||
|
@ -8555,7 +8611,8 @@ static int checkTreePage(
|
|||
u8 *data;
|
||||
BtShared *pBt;
|
||||
int usableSize;
|
||||
char *hit = 0;
|
||||
u32 *heap = 0;
|
||||
u32 x, prev = 0;
|
||||
i64 nMinKey = 0;
|
||||
i64 nMaxKey = 0;
|
||||
const char *saved_zPfx = pCheck->zPfx;
|
||||
|
@ -8700,15 +8757,15 @@ static int checkTreePage(
|
|||
*/
|
||||
data = pPage->aData;
|
||||
hdr = pPage->hdrOffset;
|
||||
hit = sqlite3PageMalloc( pBt->pageSize );
|
||||
heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
|
||||
pCheck->zPfx = 0;
|
||||
if( hit==0 ){
|
||||
if( heap==0 ){
|
||||
pCheck->mallocFailed = 1;
|
||||
}else{
|
||||
int contentOffset = get2byteNotZero(&data[hdr+5]);
|
||||
assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
|
||||
memset(hit+contentOffset, 0, usableSize-contentOffset);
|
||||
memset(hit, 1, contentOffset);
|
||||
heap[0] = 0;
|
||||
btreeHeapInsert(heap, contentOffset-1);
|
||||
/* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
|
||||
** number of cells on the page. */
|
||||
nCell = get2byte(&data[hdr+3]);
|
||||
|
@ -8720,7 +8777,6 @@ static int checkTreePage(
|
|||
for(i=0; i<nCell; i++){
|
||||
int pc = get2byte(&data[cellStart+i*2]);
|
||||
u32 size = 65536;
|
||||
int j;
|
||||
if( pc<=usableSize-4 ){
|
||||
size = cellSizePtr(pPage, &data[pc]);
|
||||
}
|
||||
|
@ -8729,7 +8785,7 @@ static int checkTreePage(
|
|||
checkAppendMsg(pCheck,
|
||||
"Corruption detected in cell %d on page %d",i,iPage);
|
||||
}else{
|
||||
for(j=pc+size-1; j>=pc; j--) hit[j]++;
|
||||
btreeHeapInsert(heap, (pc<<16)|(pc+size-1));
|
||||
}
|
||||
}
|
||||
/* EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
|
||||
|
@ -8741,7 +8797,7 @@ static int checkTreePage(
|
|||
assert( i<=usableSize-4 ); /* Enforced by btreeInitPage() */
|
||||
size = get2byte(&data[i+2]);
|
||||
assert( i+size<=usableSize ); /* Enforced by btreeInitPage() */
|
||||
for(j=i+size-1; j>=i; j--) hit[j]++;
|
||||
btreeHeapInsert(heap, (i<<16)|(i+size-1));
|
||||
/* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a
|
||||
** big-endian integer which is the offset in the b-tree page of the next
|
||||
** freeblock in the chain, or zero if the freeblock is the last on the
|
||||
|
@ -8753,27 +8809,33 @@ static int checkTreePage(
|
|||
assert( j<=usableSize-4 ); /* Enforced by btreeInitPage() */
|
||||
i = j;
|
||||
}
|
||||
for(i=cnt=0; i<usableSize; i++){
|
||||
if( hit[i]==0 ){
|
||||
cnt++;
|
||||
}else if( hit[i]>1 ){
|
||||
cnt = 0;
|
||||
assert( heap[0]>0 );
|
||||
assert( (heap[1]>>16)==0 );
|
||||
btreeHeapPull(heap,&prev);
|
||||
while( btreeHeapPull(heap,&x) ){
|
||||
if( (prev&0xffff)+1>(x>>16) ){
|
||||
checkAppendMsg(pCheck,
|
||||
"Multiple uses for byte %d of page %d", i, iPage);
|
||||
"Multiple uses for byte %u of page %d", x>>16, iPage);
|
||||
break;
|
||||
}else{
|
||||
cnt += (x>>16) - (prev&0xffff) - 1;
|
||||
prev = x;
|
||||
}
|
||||
}
|
||||
cnt += usableSize - (prev&0xffff) - 1;
|
||||
/* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments
|
||||
** is stored in the fifth field of the b-tree page header.
|
||||
** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the
|
||||
** number of fragmented free bytes within the cell content area.
|
||||
*/
|
||||
if( cnt!=data[hdr+7] ){
|
||||
if( heap[0]==0 && cnt!=data[hdr+7] ){
|
||||
checkAppendMsg(pCheck,
|
||||
"Fragmentation of %d bytes reported as %d on page %d",
|
||||
cnt, data[hdr+7], iPage);
|
||||
}
|
||||
}
|
||||
sqlite3PageFree(hit);
|
||||
sqlite3PageFree(heap);
|
||||
releasePage(pPage);
|
||||
|
||||
end_of_check:
|
||||
|
|
17
src/build.c
17
src/build.c
|
@ -142,9 +142,11 @@ void sqlite3FinishCoding(Parse *pParse){
|
|||
|
||||
assert( pParse->pToplevel==0 );
|
||||
db = pParse->db;
|
||||
if( db->mallocFailed ) return;
|
||||
if( pParse->nested ) return;
|
||||
if( pParse->nErr ) return;
|
||||
if( db->mallocFailed || pParse->nErr ){
|
||||
if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Begin by generating some termination code at the end of the
|
||||
** vdbe program
|
||||
|
@ -761,14 +763,12 @@ int sqlite3TwoPartName(
|
|||
if( ALWAYS(pName2!=0) && pName2->n>0 ){
|
||||
if( db->init.busy ) {
|
||||
sqlite3ErrorMsg(pParse, "corrupt database");
|
||||
pParse->nErr++;
|
||||
return -1;
|
||||
}
|
||||
*pUnqual = pName2;
|
||||
iDb = sqlite3FindDb(db, pName1);
|
||||
if( iDb<0 ){
|
||||
sqlite3ErrorMsg(pParse, "unknown database %T", pName1);
|
||||
pParse->nErr++;
|
||||
return -1;
|
||||
}
|
||||
}else{
|
||||
|
@ -927,7 +927,7 @@ void sqlite3StartTable(
|
|||
if( !noErr ){
|
||||
sqlite3ErrorMsg(pParse, "table %T already exists", pName);
|
||||
}else{
|
||||
assert( !db->init.busy );
|
||||
assert( !db->init.busy || CORRUPT_DB );
|
||||
sqlite3CodeVerifySchema(pParse, iDb);
|
||||
}
|
||||
goto begin_table_error;
|
||||
|
@ -1216,7 +1216,8 @@ void sqlite3AddColumnType(Parse *pParse, Token *pType){
|
|||
p = pParse->pNewTable;
|
||||
if( p==0 || NEVER(p->nCol<1) ) return;
|
||||
pCol = &p->aCol[p->nCol-1];
|
||||
assert( pCol->zType==0 );
|
||||
assert( pCol->zType==0 || CORRUPT_DB );
|
||||
sqlite3DbFree(pParse->db, pCol->zType);
|
||||
pCol->zType = sqlite3NameFromToken(pParse->db, pType);
|
||||
pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst);
|
||||
}
|
||||
|
@ -2450,6 +2451,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
|
|||
}
|
||||
assert( pParse->nErr==0 );
|
||||
assert( pName->nSrc==1 );
|
||||
if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
|
||||
if( noErr ) db->suppressErr++;
|
||||
pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
|
||||
if( noErr ) db->suppressErr--;
|
||||
|
@ -2857,8 +2859,7 @@ Index *sqlite3CreateIndex(
|
|||
char *zExtra = 0; /* Extra space after the Index object */
|
||||
Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */
|
||||
|
||||
assert( pParse->nErr==0 ); /* Never called with prior errors */
|
||||
if( db->mallocFailed || IN_DECLARE_VTAB ){
|
||||
if( db->mallocFailed || IN_DECLARE_VTAB || pParse->nErr>0 ){
|
||||
goto exit_create_index;
|
||||
}
|
||||
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
||||
|
|
|
@ -1251,7 +1251,8 @@ u32 sqlite3ExprListFlags(const ExprList *pList){
|
|||
u32 m = 0;
|
||||
if( pList ){
|
||||
for(i=0; i<pList->nExpr; i++){
|
||||
m |= pList->a[i].pExpr->flags;
|
||||
Expr *pExpr = pList->a[i].pExpr;
|
||||
if( ALWAYS(pExpr) ) m |= pList->a[i].pExpr->flags;
|
||||
}
|
||||
}
|
||||
return m;
|
||||
|
@ -2016,7 +2017,7 @@ int sqlite3CodeSubselect(
|
|||
pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0,
|
||||
&sqlite3IntTokens[1]);
|
||||
pSel->iLimit = 0;
|
||||
pSel->selFlags &= ~SF_AllValues;
|
||||
pSel->selFlags &= ~SF_MultiValue;
|
||||
if( sqlite3Select(pParse, pSel, &dest) ){
|
||||
return 0;
|
||||
}
|
||||
|
@ -3382,7 +3383,7 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
|||
break;
|
||||
}
|
||||
case TK_ID: {
|
||||
sqlite3TreeViewLine(pView,"ID %Q", pExpr->u.zToken);
|
||||
sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
|
||||
break;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_CAST
|
||||
|
@ -4017,7 +4018,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
|
|||
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
|
||||
if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
|
||||
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
|
||||
if( ALWAYS((combinedFlags & EP_Reduced)==0) ){
|
||||
if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){
|
||||
if( pA->iColumn!=pB->iColumn ) return 2;
|
||||
if( pA->iTable!=pB->iTable
|
||||
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
|
||||
|
|
25
src/fkey.c
25
src/fkey.c
|
@ -1197,10 +1197,10 @@ static Trigger *fkActionTrigger(
|
|||
** parent table are used for the comparison. */
|
||||
pEq = sqlite3PExpr(pParse, TK_EQ,
|
||||
sqlite3PExpr(pParse, TK_DOT,
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld),
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol)
|
||||
sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
|
||||
sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)
|
||||
, 0),
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tFromCol)
|
||||
sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0)
|
||||
, 0);
|
||||
pWhere = sqlite3ExprAnd(db, pWhere, pEq);
|
||||
|
||||
|
@ -1212,12 +1212,12 @@ static Trigger *fkActionTrigger(
|
|||
if( pChanges ){
|
||||
pEq = sqlite3PExpr(pParse, TK_IS,
|
||||
sqlite3PExpr(pParse, TK_DOT,
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld),
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol),
|
||||
sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
|
||||
sqlite3ExprAlloc(db, TK_ID, &tToCol, 0),
|
||||
0),
|
||||
sqlite3PExpr(pParse, TK_DOT,
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew),
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol),
|
||||
sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
|
||||
sqlite3ExprAlloc(db, TK_ID, &tToCol, 0),
|
||||
0),
|
||||
0);
|
||||
pWhen = sqlite3ExprAnd(db, pWhen, pEq);
|
||||
|
@ -1227,8 +1227,8 @@ static Trigger *fkActionTrigger(
|
|||
Expr *pNew;
|
||||
if( action==OE_Cascade ){
|
||||
pNew = sqlite3PExpr(pParse, TK_DOT,
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew),
|
||||
sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol)
|
||||
sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
|
||||
sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)
|
||||
, 0);
|
||||
}else if( action==OE_SetDflt ){
|
||||
Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt;
|
||||
|
@ -1275,13 +1275,12 @@ static Trigger *fkActionTrigger(
|
|||
pTrigger = (Trigger *)sqlite3DbMallocZero(db,
|
||||
sizeof(Trigger) + /* struct Trigger */
|
||||
sizeof(TriggerStep) + /* Single step in trigger program */
|
||||
nFrom + 1 /* Space for pStep->target.z */
|
||||
nFrom + 1 /* Space for pStep->zTarget */
|
||||
);
|
||||
if( pTrigger ){
|
||||
pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1];
|
||||
pStep->target.z = (char *)&pStep[1];
|
||||
pStep->target.n = nFrom;
|
||||
memcpy((char *)pStep->target.z, zFrom, nFrom);
|
||||
pStep->zTarget = (char *)&pStep[1];
|
||||
memcpy((char *)pStep->zTarget, zFrom, nFrom);
|
||||
|
||||
pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
|
||||
pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE);
|
||||
|
|
37
src/insert.c
37
src/insert.c
|
@ -342,20 +342,23 @@ static int xferOptimization(
|
|||
/*
|
||||
** This routine is called to handle SQL of the following forms:
|
||||
**
|
||||
** insert into TABLE (IDLIST) values(EXPRLIST)
|
||||
** insert into TABLE (IDLIST) values(EXPRLIST),(EXPRLIST),...
|
||||
** insert into TABLE (IDLIST) select
|
||||
** insert into TABLE (IDLIST) default values
|
||||
**
|
||||
** The IDLIST following the table name is always optional. If omitted,
|
||||
** then a list of all columns for the table is substituted. The IDLIST
|
||||
** appears in the pColumn parameter. pColumn is NULL if IDLIST is omitted.
|
||||
** then a list of all (non-hidden) columns for the table is substituted.
|
||||
** The IDLIST appears in the pColumn parameter. pColumn is NULL if IDLIST
|
||||
** is omitted.
|
||||
**
|
||||
** The pList parameter holds EXPRLIST in the first form of the INSERT
|
||||
** statement above, and pSelect is NULL. For the second form, pList is
|
||||
** NULL and pSelect is a pointer to the select statement used to generate
|
||||
** data for the insert.
|
||||
** For the pSelect parameter holds the values to be inserted for the
|
||||
** first two forms shown above. A VALUES clause is really just short-hand
|
||||
** for a SELECT statement that omits the FROM clause and everything else
|
||||
** that follows. If the pSelect parameter is NULL, that means that the
|
||||
** DEFAULT VALUES form of the INSERT statement is intended.
|
||||
**
|
||||
** The code generated follows one of four templates. For a simple
|
||||
** insert with data coming from a VALUES clause, the code executes
|
||||
** insert with data coming from a single-row VALUES clause, the code executes
|
||||
** once straight down through. Pseudo-code follows (we call this
|
||||
** the "1st template"):
|
||||
**
|
||||
|
@ -462,7 +465,7 @@ void sqlite3Insert(
|
|||
u8 useTempTable = 0; /* Store SELECT results in intermediate table */
|
||||
u8 appendFlag = 0; /* True if the insert is likely to be an append */
|
||||
u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */
|
||||
u8 bIdListInOrder = 1; /* True if IDLIST is in table order */
|
||||
u8 bIdListInOrder; /* True if IDLIST is in table order */
|
||||
ExprList *pList = 0; /* List of VALUES() to be inserted */
|
||||
|
||||
/* Register allocations */
|
||||
|
@ -487,8 +490,8 @@ void sqlite3Insert(
|
|||
}
|
||||
|
||||
/* If the Select object is really just a simple VALUES() list with a
|
||||
** single row values (the common case) then keep that one row of values
|
||||
** and go ahead and discard the Select object
|
||||
** single row (the common case) then keep that one row of values
|
||||
** and discard the other (unused) parts of the pSelect object
|
||||
*/
|
||||
if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){
|
||||
pList = pSelect->pEList;
|
||||
|
@ -596,6 +599,7 @@ void sqlite3Insert(
|
|||
** is appears in the original table. (The index of the INTEGER
|
||||
** PRIMARY KEY in the original table is pTab->iPKey.)
|
||||
*/
|
||||
bIdListInOrder = (pTab->tabFlags & TF_OOOHidden)==0;
|
||||
if( pColumn ){
|
||||
for(i=0; i<pColumn->nId; i++){
|
||||
pColumn->a[i].idx = -1;
|
||||
|
@ -631,7 +635,8 @@ void sqlite3Insert(
|
|||
** co-routine is the common header to the 3rd and 4th templates.
|
||||
*/
|
||||
if( pSelect ){
|
||||
/* Data is coming from a SELECT. Generate a co-routine to run the SELECT */
|
||||
/* Data is coming from a SELECT or from a multi-row VALUES clause.
|
||||
** Generate a co-routine to run the SELECT. */
|
||||
int regYield; /* Register holding co-routine entry-point */
|
||||
int addrTop; /* Top of the co-routine */
|
||||
int rc; /* Result code */
|
||||
|
@ -644,8 +649,7 @@ void sqlite3Insert(
|
|||
dest.nSdst = pTab->nCol;
|
||||
rc = sqlite3Select(pParse, pSelect, &dest);
|
||||
regFromSelect = dest.iSdst;
|
||||
assert( pParse->nErr==0 || rc );
|
||||
if( rc || db->mallocFailed ) goto insert_cleanup;
|
||||
if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup;
|
||||
sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield);
|
||||
sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
|
||||
assert( pSelect->pEList );
|
||||
|
@ -693,8 +697,8 @@ void sqlite3Insert(
|
|||
sqlite3ReleaseTempReg(pParse, regTempRowid);
|
||||
}
|
||||
}else{
|
||||
/* This is the case if the data for the INSERT is coming from a VALUES
|
||||
** clause
|
||||
/* This is the case if the data for the INSERT is coming from a
|
||||
** single-row VALUES clause
|
||||
*/
|
||||
NameContext sNC;
|
||||
memset(&sNC, 0, sizeof(sNC));
|
||||
|
@ -2021,7 +2025,6 @@ static int xferOptimization(
|
|||
** might change the definition of a collation sequence and then run
|
||||
** a VACUUM command. In that case keys may not be written in strictly
|
||||
** sorted order. */
|
||||
int i;
|
||||
for(i=0; i<pSrcIdx->nColumn; i++){
|
||||
char *zColl = pSrcIdx->azColl[i];
|
||||
assert( zColl!=0 );
|
||||
|
|
|
@ -3044,9 +3044,7 @@ static int pagerWalFrames(
|
|||
){
|
||||
int rc; /* Return code */
|
||||
int nList; /* Number of pages in pList */
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
|
||||
PgHdr *p; /* For looping over pages */
|
||||
#endif
|
||||
|
||||
assert( pPager->pWal );
|
||||
assert( pList );
|
||||
|
@ -3063,7 +3061,6 @@ static int pagerWalFrames(
|
|||
** any pages with page numbers greater than nTruncate into the WAL file.
|
||||
** They will never be read by any client. So remove them from the pDirty
|
||||
** list here. */
|
||||
PgHdr *p;
|
||||
PgHdr **ppNext = &pList;
|
||||
nList = 0;
|
||||
for(p=pList; (*ppNext = p)!=0; p=p->pDirty){
|
||||
|
@ -3083,7 +3080,6 @@ static int pagerWalFrames(
|
|||
pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
|
||||
);
|
||||
if( rc==SQLITE_OK && pPager->pBackup ){
|
||||
PgHdr *p;
|
||||
for(p=pList; p; p=p->pDirty){
|
||||
sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
|
||||
}
|
||||
|
|
44
src/parse.y
44
src/parse.y
|
@ -409,28 +409,35 @@ cmd ::= select(X). {
|
|||
%type oneselect {Select*}
|
||||
%destructor oneselect {sqlite3SelectDelete(pParse->db, $$);}
|
||||
|
||||
select(A) ::= with(W) selectnowith(X). {
|
||||
Select *p = X, *pNext, *pLoop;
|
||||
if( p ){
|
||||
int cnt = 0, mxSelect;
|
||||
p->pWith = W;
|
||||
%include {
|
||||
/*
|
||||
** For a compound SELECT statement, make sure p->pPrior->pNext==p for
|
||||
** all elements in the list. And make sure list length does not exceed
|
||||
** SQLITE_LIMIT_COMPOUND_SELECT.
|
||||
*/
|
||||
static void parserDoubleLinkSelect(Parse *pParse, Select *p){
|
||||
if( p->pPrior ){
|
||||
u16 allValues = SF_Values;
|
||||
pNext = 0;
|
||||
Select *pNext = 0, *pLoop;
|
||||
int mxSelect, cnt = 0;
|
||||
for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){
|
||||
pLoop->pNext = pNext;
|
||||
pLoop->selFlags |= SF_Compound;
|
||||
allValues &= pLoop->selFlags;
|
||||
}
|
||||
if( allValues ){
|
||||
p->selFlags |= SF_AllValues;
|
||||
}else if(
|
||||
(mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0
|
||||
&& cnt>mxSelect
|
||||
if( (p->selFlags & SF_MultiValue)==0 &&
|
||||
(mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 &&
|
||||
cnt>mxSelect
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
select(A) ::= with(W) selectnowith(X). {
|
||||
Select *p = X;
|
||||
if( p ){
|
||||
p->pWith = W;
|
||||
parserDoubleLinkSelect(pParse, p);
|
||||
}else{
|
||||
sqlite3WithDelete(pParse->db, W);
|
||||
}
|
||||
|
@ -445,12 +452,14 @@ selectnowith(A) ::= selectnowith(X) multiselect_op(Y) oneselect(Z). {
|
|||
SrcList *pFrom;
|
||||
Token x;
|
||||
x.n = 0;
|
||||
parserDoubleLinkSelect(pParse, pRhs);
|
||||
pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0);
|
||||
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0);
|
||||
}
|
||||
if( pRhs ){
|
||||
pRhs->op = (u8)Y;
|
||||
pRhs->pPrior = X;
|
||||
pRhs->selFlags &= ~SF_MultiValue;
|
||||
if( Y!=TK_ALL ) pParse->hasCompound = 1;
|
||||
}else{
|
||||
sqlite3SelectDelete(pParse->db, X);
|
||||
|
@ -498,13 +507,16 @@ values(A) ::= VALUES LP nexprlist(X) RP. {
|
|||
A = sqlite3SelectNew(pParse,X,0,0,0,0,0,SF_Values,0,0);
|
||||
}
|
||||
values(A) ::= values(X) COMMA LP exprlist(Y) RP. {
|
||||
Select *pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values,0,0);
|
||||
Select *pRight, *pLeft = X;
|
||||
pRight = sqlite3SelectNew(pParse,Y,0,0,0,0,0,SF_Values|SF_MultiValue,0,0);
|
||||
if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
|
||||
if( pRight ){
|
||||
pRight->op = TK_ALL;
|
||||
pRight->pPrior = X;
|
||||
pLeft = X;
|
||||
pRight->pPrior = pLeft;
|
||||
A = pRight;
|
||||
}else{
|
||||
A = X;
|
||||
A = pLeft;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
16
src/pragma.c
16
src/pragma.c
|
@ -164,15 +164,15 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){
|
|||
*/
|
||||
static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
int mem = ++pParse->nMem;
|
||||
int nMem = ++pParse->nMem;
|
||||
i64 *pI64 = sqlite3DbMallocRaw(pParse->db, sizeof(value));
|
||||
if( pI64 ){
|
||||
memcpy(pI64, &value, sizeof(value));
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, OP_Int64, 0, mem, 0, (char*)pI64, P4_INT64);
|
||||
sqlite3VdbeAddOp4(v, OP_Int64, 0, nMem, 0, (char*)pI64, P4_INT64);
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, nMem, 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -337,11 +337,11 @@ void sqlite3Pragma(
|
|||
rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( aFcntl[0] ){
|
||||
int mem = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0);
|
||||
int nMem = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, nMem, 0, aFcntl[0], 0);
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, nMem, 1);
|
||||
sqlite3_free(aFcntl[0]);
|
||||
}
|
||||
goto pragma_out;
|
||||
|
@ -946,7 +946,9 @@ void sqlite3Pragma(
|
|||
sqlite3ErrorMsg(pParse,
|
||||
"Safety level may not be changed inside a transaction");
|
||||
}else{
|
||||
pDb->safety_level = getSafetyLevel(zRight,0,1)+1;
|
||||
int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK;
|
||||
if( iLevel==0 ) iLevel = 1;
|
||||
pDb->safety_level = iLevel;
|
||||
setAllPagerFlags(db);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|
|||
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
|
||||
if( argv[1]==0 ){
|
||||
corruptSchema(pData, argv[0], 0);
|
||||
}else if( argv[2] && argv[2][0] ){
|
||||
}else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){
|
||||
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
|
||||
** But because db->init.busy is set to 1, no VDBE code is generated
|
||||
** or executed. All the parser does is build the internal data
|
||||
|
@ -98,8 +98,8 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|
|||
}
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
}else if( argv[0]==0 ){
|
||||
corruptSchema(pData, 0, 0);
|
||||
}else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){
|
||||
corruptSchema(pData, argv[0], 0);
|
||||
}else{
|
||||
/* If the SQL column is blank it means this is an index that
|
||||
** was created to be the PRIMARY KEY or to fulfill a UNIQUE
|
||||
|
|
|
@ -79,7 +79,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
|
|||
** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase;
|
||||
**
|
||||
** The nSubquery parameter specifies how many levels of subquery the
|
||||
** alias is removed from the original expression. The usually value is
|
||||
** alias is removed from the original expression. The usual 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.
|
||||
|
@ -99,7 +99,7 @@ static void resolveAlias(
|
|||
assert( iCol>=0 && iCol<pEList->nExpr );
|
||||
pOrig = pEList->a[iCol].pExpr;
|
||||
assert( pOrig!=0 );
|
||||
assert( pOrig->flags & EP_Resolved );
|
||||
assert( (pOrig->flags & EP_Resolved)!=0 || zType[0]==0 );
|
||||
db = pParse->db;
|
||||
pDup = sqlite3ExprDup(db, pOrig, 0);
|
||||
if( pDup==0 ) return;
|
||||
|
@ -460,7 +460,6 @@ static int lookupName(
|
|||
if( cnt==0 && zTab==0 && ExprHasProperty(pExpr,EP_DblQuoted) ){
|
||||
pExpr->op = TK_STRING;
|
||||
pExpr->pTab = 0;
|
||||
pExpr->iTable = -1;
|
||||
return WRC_Prune;
|
||||
}
|
||||
|
||||
|
@ -1300,8 +1299,15 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
|||
** The ORDER BY clause for compounds SELECT statements is handled
|
||||
** below, after all of the result-sets for all of the elements of
|
||||
** the compound have been resolved.
|
||||
**
|
||||
** If there is an ORDER BY clause on a term of a compound-select other
|
||||
** than the right-most term, then that is a syntax error. But the error
|
||||
** is not detected until much later, and so we need to go ahead and
|
||||
** resolve those symbols on the incorrect ORDER BY for consistency.
|
||||
*/
|
||||
if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){
|
||||
if( isCompound<=nCompound /* Defer right-most ORDER BY of a compound */
|
||||
&& resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER")
|
||||
){
|
||||
return WRC_Abort;
|
||||
}
|
||||
if( db->mallocFailed ){
|
||||
|
|
39
src/select.c
39
src/select.c
|
@ -111,7 +111,6 @@ Select *sqlite3SelectNew(
|
|||
Select standin;
|
||||
sqlite3 *db = pParse->db;
|
||||
pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
|
||||
assert( db->mallocFailed || !pOffset || pLimit ); /* OFFSET implies LIMIT */
|
||||
if( pNew==0 ){
|
||||
assert( db->mallocFailed );
|
||||
pNew = &standin;
|
||||
|
@ -131,7 +130,7 @@ Select *sqlite3SelectNew(
|
|||
pNew->op = TK_SELECT;
|
||||
pNew->pLimit = pLimit;
|
||||
pNew->pOffset = pOffset;
|
||||
assert( pOffset==0 || pLimit!=0 );
|
||||
assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 );
|
||||
pNew->addrOpenEphm[0] = -1;
|
||||
pNew->addrOpenEphm[1] = -1;
|
||||
if( db->mallocFailed ) {
|
||||
|
@ -1381,7 +1380,7 @@ static const char *columnTypeImpl(
|
|||
** of the SELECT statement. Return the declaration type and origin
|
||||
** data for the result-set column of the sub-select.
|
||||
*/
|
||||
if( iCol>=0 && ALWAYS(iCol<pS->pEList->nExpr) ){
|
||||
if( iCol>=0 && iCol<pS->pEList->nExpr ){
|
||||
/* If iCol is less than zero, then the expression requests the
|
||||
** rowid of the sub-select or view. This expression is legal (see
|
||||
** test case misc2.2.2) - it always evaluates to NULL.
|
||||
|
@ -1701,12 +1700,14 @@ static void selectAddColumnTypeAndCollation(
|
|||
a = pSelect->pEList->a;
|
||||
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
|
||||
p = a[i].pExpr;
|
||||
pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
|
||||
if( pCol->zType==0 ){
|
||||
pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
|
||||
}
|
||||
szAll += pCol->szEst;
|
||||
pCol->affinity = sqlite3ExprAffinity(p);
|
||||
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
|
||||
pColl = sqlite3ExprCollSeq(pParse, p);
|
||||
if( pColl ){
|
||||
if( pColl && pCol->zColl==0 ){
|
||||
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
|
||||
}
|
||||
}
|
||||
|
@ -2108,8 +2109,7 @@ static int multiSelectValues(
|
|||
int nExpr = p->pEList->nExpr;
|
||||
int nRow = 1;
|
||||
int rc = 0;
|
||||
assert( p->pNext==0 );
|
||||
assert( p->selFlags & SF_AllValues );
|
||||
assert( p->selFlags & SF_MultiValue );
|
||||
do{
|
||||
assert( p->selFlags & SF_Values );
|
||||
assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
|
||||
|
@ -2218,7 +2218,7 @@ static int multiSelect(
|
|||
|
||||
/* Special handling for a compound-select that originates as a VALUES clause.
|
||||
*/
|
||||
if( p->selFlags & SF_AllValues ){
|
||||
if( p->selFlags & SF_MultiValue ){
|
||||
rc = multiSelectValues(pParse, p, &dest);
|
||||
goto multi_select_end;
|
||||
}
|
||||
|
@ -2629,7 +2629,7 @@ static int generateOutputSubroutine(
|
|||
** of the scan loop.
|
||||
*/
|
||||
case SRT_Mem: {
|
||||
assert( pIn->nSdst==1 );
|
||||
assert( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 );
|
||||
sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1);
|
||||
/* The LIMIT clause will jump out of the loop for us */
|
||||
break;
|
||||
|
@ -2644,7 +2644,7 @@ static int generateOutputSubroutine(
|
|||
pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst);
|
||||
pDest->nSdst = pIn->nSdst;
|
||||
}
|
||||
sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pDest->nSdst);
|
||||
sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pIn->nSdst);
|
||||
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
|
||||
break;
|
||||
}
|
||||
|
@ -2860,8 +2860,10 @@ static int multiSelectOrderBy(
|
|||
if( aPermute ){
|
||||
struct ExprList_item *pItem;
|
||||
for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
|
||||
assert( pItem->u.x.iOrderByCol>0
|
||||
&& pItem->u.x.iOrderByCol<=p->pEList->nExpr );
|
||||
assert( pItem->u.x.iOrderByCol>0 );
|
||||
/* assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ) is also true
|
||||
** but only for well-formed SELECT statements. */
|
||||
testcase( pItem->u.x.iOrderByCol > p->pEList->nExpr );
|
||||
aPermute[i] = pItem->u.x.iOrderByCol - 1;
|
||||
}
|
||||
pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
|
||||
|
@ -4422,7 +4424,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
|
|||
sqlite3WalkSelect(&w, pSelect);
|
||||
}
|
||||
w.xSelectCallback = selectExpander;
|
||||
if( (pSelect->selFlags & SF_AllValues)==0 ){
|
||||
if( (pSelect->selFlags & SF_MultiValue)==0 ){
|
||||
w.xSelectCallback2 = selectPopWith;
|
||||
}
|
||||
sqlite3WalkSelect(&w, pSelect);
|
||||
|
@ -4608,7 +4610,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
|
|||
}
|
||||
if( pF->iDistinct>=0 ){
|
||||
addrNext = sqlite3VdbeMakeLabel(v);
|
||||
assert( nArg==1 );
|
||||
testcase( nArg==0 ); /* Error condition */
|
||||
testcase( nArg>1 ); /* Also an error */
|
||||
codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
|
||||
}
|
||||
if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
|
||||
|
@ -5483,10 +5486,9 @@ int sqlite3Select(
|
|||
*/
|
||||
sqlite3VdbeResolveLabel(v, iEnd);
|
||||
|
||||
/* The SELECT was successfully coded. Set the return code to 0
|
||||
** to indicate no errors.
|
||||
*/
|
||||
rc = 0;
|
||||
/* The SELECT has been coded. If there is an error in the Parse structure,
|
||||
** set the return code to 1. Otherwise 0. */
|
||||
rc = (pParse->nErr>0);
|
||||
|
||||
/* Control jumps to here if an error is encountered above, or upon
|
||||
** successful coding of the SELECT.
|
||||
|
@ -5538,6 +5540,7 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
|
|||
StrAccum x;
|
||||
char zLine[100];
|
||||
sqlite3StrAccumInit(&x, zLine, sizeof(zLine), 0);
|
||||
x.useMalloc = 0;
|
||||
sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor);
|
||||
if( pItem->zDatabase ){
|
||||
sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName);
|
||||
|
|
113
src/shell.c
113
src/shell.c
|
@ -336,7 +336,7 @@ static int stdin_is_interactive = 1;
|
|||
** to this database a static variable so that it can be accessed
|
||||
** by the SIGINT handler to interrupt database processing.
|
||||
*/
|
||||
static sqlite3 *db = 0;
|
||||
static sqlite3 *globalDb = 0;
|
||||
|
||||
/*
|
||||
** True if an interrupt (Control-C) has been received.
|
||||
|
@ -527,6 +527,7 @@ struct ShellState {
|
|||
int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
|
||||
int statsOn; /* True to display memory stats before each finalize */
|
||||
int scanstatsOn; /* True to display scan stats before each finalize */
|
||||
int backslashOn; /* Resolve C-style \x escapes in SQL input text */
|
||||
int outCount; /* Revert to stdout when reaching zero */
|
||||
int cnt; /* Number of records displayed so far */
|
||||
FILE *out; /* Write results here */
|
||||
|
@ -804,7 +805,7 @@ static void interrupt_handler(int NotUsed){
|
|||
UNUSED_PARAMETER(NotUsed);
|
||||
seenInterrupt++;
|
||||
if( seenInterrupt>2 ) exit(1);
|
||||
if( db ) sqlite3_interrupt(db);
|
||||
if( globalDb ) sqlite3_interrupt(globalDb);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1908,23 +1909,23 @@ static void open_db(ShellState *p, int keepAlive){
|
|||
if( p->db==0 ){
|
||||
sqlite3_initialize();
|
||||
sqlite3_open(p->zDbFilename, &p->db);
|
||||
db = p->db;
|
||||
if( db && sqlite3_errcode(db)==SQLITE_OK ){
|
||||
sqlite3_create_function(db, "shellstatic", 0, SQLITE_UTF8, 0,
|
||||
globalDb = p->db;
|
||||
if( p->db && sqlite3_errcode(p->db)==SQLITE_OK ){
|
||||
sqlite3_create_function(p->db, "shellstatic", 0, SQLITE_UTF8, 0,
|
||||
shellstaticFunc, 0, 0);
|
||||
}
|
||||
if( db==0 || SQLITE_OK!=sqlite3_errcode(db) ){
|
||||
if( p->db==0 || SQLITE_OK!=sqlite3_errcode(p->db) ){
|
||||
fprintf(stderr,"Error: unable to open database \"%s\": %s\n",
|
||||
p->zDbFilename, sqlite3_errmsg(db));
|
||||
p->zDbFilename, sqlite3_errmsg(p->db));
|
||||
if( keepAlive ) return;
|
||||
exit(1);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
||||
sqlite3_enable_load_extension(p->db, 1);
|
||||
#endif
|
||||
sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
|
||||
sqlite3_create_function(p->db, "readfile", 1, SQLITE_UTF8, 0,
|
||||
readfileFunc, 0, 0);
|
||||
sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
|
||||
sqlite3_create_function(p->db, "writefile", 2, SQLITE_UTF8, 0,
|
||||
writefileFunc, 0, 0);
|
||||
}
|
||||
}
|
||||
|
@ -1944,7 +1945,7 @@ static void resolve_backslashes(char *z){
|
|||
char c;
|
||||
while( *z && *z!='\\' ) z++;
|
||||
for(i=j=0; (c = z[i])!=0; i++, j++){
|
||||
if( c=='\\' ){
|
||||
if( c=='\\' && z[i+1]!=0 ){
|
||||
c = z[++i];
|
||||
if( c=='n' ){
|
||||
c = '\n';
|
||||
|
@ -2585,7 +2586,7 @@ static int shell_dbinfo_command(ShellState *p, int nArg, char **azArg){
|
|||
** Return 1 on error, 2 to exit, and 0 otherwise.
|
||||
*/
|
||||
static int do_meta_command(char *zLine, ShellState *p){
|
||||
int i = 1;
|
||||
int h = 1;
|
||||
int nArg = 0;
|
||||
int n, c;
|
||||
int rc = 0;
|
||||
|
@ -2593,24 +2594,24 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
|
||||
/* Parse the input line into tokens.
|
||||
*/
|
||||
while( zLine[i] && nArg<ArraySize(azArg) ){
|
||||
while( IsSpace(zLine[i]) ){ i++; }
|
||||
if( zLine[i]==0 ) break;
|
||||
if( zLine[i]=='\'' || zLine[i]=='"' ){
|
||||
int delim = zLine[i++];
|
||||
azArg[nArg++] = &zLine[i];
|
||||
while( zLine[i] && zLine[i]!=delim ){
|
||||
if( zLine[i]=='\\' && delim=='"' && zLine[i+1]!=0 ) i++;
|
||||
i++;
|
||||
while( zLine[h] && nArg<ArraySize(azArg) ){
|
||||
while( IsSpace(zLine[h]) ){ h++; }
|
||||
if( zLine[h]==0 ) break;
|
||||
if( zLine[h]=='\'' || zLine[h]=='"' ){
|
||||
int delim = zLine[h++];
|
||||
azArg[nArg++] = &zLine[h];
|
||||
while( zLine[h] && zLine[h]!=delim ){
|
||||
if( zLine[h]=='\\' && delim=='"' && zLine[h+1]!=0 ) h++;
|
||||
h++;
|
||||
}
|
||||
if( zLine[i]==delim ){
|
||||
zLine[i++] = 0;
|
||||
if( zLine[h]==delim ){
|
||||
zLine[h++] = 0;
|
||||
}
|
||||
if( delim=='"' ) resolve_backslashes(azArg[nArg-1]);
|
||||
}else{
|
||||
azArg[nArg++] = &zLine[i];
|
||||
while( zLine[i] && !IsSpace(zLine[i]) ){ i++; }
|
||||
if( zLine[i] ) zLine[i++] = 0;
|
||||
azArg[nArg++] = &zLine[h];
|
||||
while( zLine[h] && !IsSpace(zLine[h]) ){ h++; }
|
||||
if( zLine[h] ) zLine[h++] = 0;
|
||||
resolve_backslashes(azArg[nArg-1]);
|
||||
}
|
||||
}
|
||||
|
@ -2986,7 +2987,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
nByte = strlen30(zSql);
|
||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
import_append_char(&sCtx, 0); /* To ensure sCtx.z is allocated */
|
||||
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
|
||||
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(p->db))==0 ){
|
||||
char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
|
||||
char cSep = '(';
|
||||
while( xRead(&sCtx) ){
|
||||
|
@ -3006,7 +3007,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
sqlite3_free(zCreate);
|
||||
if( rc ){
|
||||
fprintf(stderr, "CREATE TABLE %s(...) failed: %s\n", zTable,
|
||||
sqlite3_errmsg(db));
|
||||
sqlite3_errmsg(p->db));
|
||||
sqlite3_free(sCtx.z);
|
||||
xCloser(sCtx.in);
|
||||
return 1;
|
||||
|
@ -3016,7 +3017,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
sqlite3_free(zSql);
|
||||
if( rc ){
|
||||
if (pStmt) sqlite3_finalize(pStmt);
|
||||
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(db));
|
||||
fprintf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
|
||||
xCloser(sCtx.in);
|
||||
return 1;
|
||||
}
|
||||
|
@ -3041,13 +3042,13 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( rc ){
|
||||
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(db));
|
||||
fprintf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
|
||||
if (pStmt) sqlite3_finalize(pStmt);
|
||||
xCloser(sCtx.in);
|
||||
return 1;
|
||||
}
|
||||
needCommit = sqlite3_get_autocommit(db);
|
||||
if( needCommit ) sqlite3_exec(db, "BEGIN", 0, 0, 0);
|
||||
needCommit = sqlite3_get_autocommit(p->db);
|
||||
if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
|
||||
do{
|
||||
int startLine = sCtx.nLine;
|
||||
for(i=0; i<nCol; i++){
|
||||
|
@ -3086,7 +3087,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
rc = sqlite3_reset(pStmt);
|
||||
if( rc!=SQLITE_OK ){
|
||||
fprintf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile, startLine,
|
||||
sqlite3_errmsg(db));
|
||||
sqlite3_errmsg(p->db));
|
||||
}
|
||||
}
|
||||
}while( sCtx.cTerm!=EOF );
|
||||
|
@ -3094,7 +3095,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
xCloser(sCtx.in);
|
||||
sqlite3_free(sCtx.z);
|
||||
sqlite3_finalize(pStmt);
|
||||
if( needCommit ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
|
||||
if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
|
||||
}else
|
||||
|
||||
if( c=='i' && (strncmp(azArg[0], "indices", n)==0
|
||||
|
@ -3648,13 +3649,13 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
if( nRow>=nAlloc ){
|
||||
char **azNew;
|
||||
int n = nAlloc*2 + 10;
|
||||
azNew = sqlite3_realloc(azResult, sizeof(azResult[0])*n);
|
||||
int n2 = nAlloc*2 + 10;
|
||||
azNew = sqlite3_realloc(azResult, sizeof(azResult[0])*n2);
|
||||
if( azNew==0 ){
|
||||
fprintf(stderr, "Error: out of memory\n");
|
||||
break;
|
||||
}
|
||||
nAlloc = n;
|
||||
nAlloc = n2;
|
||||
azResult = azNew;
|
||||
}
|
||||
azResult[nRow] = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0));
|
||||
|
@ -3707,15 +3708,15 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
{ "imposter", SQLITE_TESTCTRL_IMPOSTER },
|
||||
};
|
||||
int testctrl = -1;
|
||||
int rc = 0;
|
||||
int i, n;
|
||||
int rc2 = 0;
|
||||
int i, n2;
|
||||
open_db(p, 0);
|
||||
|
||||
/* convert testctrl text option to value. allow any unique prefix
|
||||
** of the option name, or a numerical value. */
|
||||
n = strlen30(azArg[1]);
|
||||
n2 = strlen30(azArg[1]);
|
||||
for(i=0; i<(int)(sizeof(aCtrl)/sizeof(aCtrl[0])); i++){
|
||||
if( strncmp(azArg[1], aCtrl[i].zCtrlName, n)==0 ){
|
||||
if( strncmp(azArg[1], aCtrl[i].zCtrlName, n2)==0 ){
|
||||
if( testctrl<0 ){
|
||||
testctrl = aCtrl[i].ctrlCode;
|
||||
}else{
|
||||
|
@ -3736,8 +3737,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
case SQLITE_TESTCTRL_RESERVE:
|
||||
if( nArg==3 ){
|
||||
int opt = (int)strtol(azArg[2], 0, 0);
|
||||
rc = sqlite3_test_control(testctrl, p->db, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
|
||||
rc2 = sqlite3_test_control(testctrl, p->db, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
|
||||
} else {
|
||||
fprintf(stderr,"Error: testctrl %s takes a single int option\n",
|
||||
azArg[1]);
|
||||
|
@ -3750,8 +3751,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
case SQLITE_TESTCTRL_PRNG_RESET:
|
||||
case SQLITE_TESTCTRL_BYTEORDER:
|
||||
if( nArg==2 ){
|
||||
rc = sqlite3_test_control(testctrl);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
|
||||
rc2 = sqlite3_test_control(testctrl);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
|
||||
} else {
|
||||
fprintf(stderr,"Error: testctrl %s takes no options\n", azArg[1]);
|
||||
}
|
||||
|
@ -3761,8 +3762,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
case SQLITE_TESTCTRL_PENDING_BYTE:
|
||||
if( nArg==3 ){
|
||||
unsigned int opt = (unsigned int)integerValue(azArg[2]);
|
||||
rc = sqlite3_test_control(testctrl, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
|
||||
rc2 = sqlite3_test_control(testctrl, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
|
||||
} else {
|
||||
fprintf(stderr,"Error: testctrl %s takes a single unsigned"
|
||||
" int option\n", azArg[1]);
|
||||
|
@ -3775,8 +3776,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
case SQLITE_TESTCTRL_NEVER_CORRUPT:
|
||||
if( nArg==3 ){
|
||||
int opt = booleanValue(azArg[2]);
|
||||
rc = sqlite3_test_control(testctrl, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
|
||||
rc2 = sqlite3_test_control(testctrl, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
|
||||
} else {
|
||||
fprintf(stderr,"Error: testctrl %s takes a single int option\n",
|
||||
azArg[1]);
|
||||
|
@ -3788,8 +3789,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
case SQLITE_TESTCTRL_ISKEYWORD:
|
||||
if( nArg==3 ){
|
||||
const char *opt = azArg[2];
|
||||
rc = sqlite3_test_control(testctrl, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
|
||||
rc2 = sqlite3_test_control(testctrl, opt);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
|
||||
} else {
|
||||
fprintf(stderr,"Error: testctrl %s takes a single char * option\n",
|
||||
azArg[1]);
|
||||
|
@ -3799,11 +3800,11 @@ static int do_meta_command(char *zLine, ShellState *p){
|
|||
|
||||
case SQLITE_TESTCTRL_IMPOSTER:
|
||||
if( nArg==5 ){
|
||||
rc = sqlite3_test_control(testctrl, p->db,
|
||||
rc2 = sqlite3_test_control(testctrl, p->db,
|
||||
azArg[2],
|
||||
integerValue(azArg[3]),
|
||||
integerValue(azArg[4]));
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
|
||||
fprintf(p->out, "%d (0x%08x)\n", rc2, rc2);
|
||||
}else{
|
||||
fprintf(stderr,"Usage: .testctrl imposter dbName onoff tnum\n");
|
||||
}
|
||||
|
@ -4111,6 +4112,7 @@ static int process_input(ShellState *p, FILE *in){
|
|||
&& sqlite3_complete(zSql) ){
|
||||
p->cnt = 0;
|
||||
open_db(p, 0);
|
||||
if( p->backslashOn ) resolve_backslashes(zSql);
|
||||
BEGIN_TIMER;
|
||||
rc = shell_exec(p->db, zSql, shell_callback, p, &zErrMsg);
|
||||
END_TIMER;
|
||||
|
@ -4577,6 +4579,13 @@ int SQLITE_CDECL main(int argc, char **argv){
|
|||
data.statsOn = 1;
|
||||
}else if( strcmp(z,"-scanstats")==0 ){
|
||||
data.scanstatsOn = 1;
|
||||
}else if( strcmp(z,"-backslash")==0 ){
|
||||
/* Undocumented command-line option: -backslash
|
||||
** Causes C-style backslash escapes to be evaluated in SQL statements
|
||||
** prior to sending the SQL into SQLite. Useful for injecting
|
||||
** crazy bytes in the middle of SQL statements for testing and debugging.
|
||||
*/
|
||||
data.backslashOn = 1;
|
||||
}else if( strcmp(z,"-bail")==0 ){
|
||||
bail_on_error = 1;
|
||||
}else if( strcmp(z,"-version")==0 ){
|
||||
|
|
|
@ -1622,6 +1622,12 @@ struct Table {
|
|||
|
||||
/*
|
||||
** Allowed values for Table.tabFlags.
|
||||
**
|
||||
** TF_OOOHidden applies to virtual tables that have hidden columns that are
|
||||
** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING
|
||||
** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden,
|
||||
** the TF_OOOHidden attribute would apply in this case. Such tables require
|
||||
** special handling during INSERT processing.
|
||||
*/
|
||||
#define TF_Readonly 0x01 /* Read-only system table */
|
||||
#define TF_Ephemeral 0x02 /* An ephemeral table */
|
||||
|
@ -1629,6 +1635,7 @@ struct Table {
|
|||
#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */
|
||||
#define TF_Virtual 0x10 /* Is a virtual table */
|
||||
#define TF_WithoutRowid 0x20 /* No rowid used. PRIMARY KEY is the key */
|
||||
#define TF_OOOHidden 0x40 /* Out-of-Order hidden columns */
|
||||
|
||||
|
||||
/*
|
||||
|
@ -2385,7 +2392,7 @@ struct Select {
|
|||
#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
|
||||
#define SF_Compound 0x0040 /* Part of a compound query */
|
||||
#define SF_Values 0x0080 /* Synthesized from VALUES clause */
|
||||
#define SF_AllValues 0x0100 /* All terms of compound are VALUES */
|
||||
#define SF_MultiValue 0x0100 /* Single VALUES term with multiple rows */
|
||||
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
|
||||
#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
|
||||
#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */
|
||||
|
@ -2769,7 +2776,7 @@ struct Trigger {
|
|||
* orconf -> stores the ON CONFLICT algorithm
|
||||
* pSelect -> If this is an INSERT INTO ... SELECT ... statement, then
|
||||
* this stores a pointer to the SELECT statement. Otherwise NULL.
|
||||
* target -> A token holding the quoted name of the table to insert into.
|
||||
* zTarget -> Dequoted name of the table to insert into.
|
||||
* pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
|
||||
* this stores values to be inserted. Otherwise NULL.
|
||||
* pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
|
||||
|
@ -2777,12 +2784,12 @@ struct Trigger {
|
|||
* inserted into.
|
||||
*
|
||||
* (op == TK_DELETE)
|
||||
* target -> A token holding the quoted name of the table to delete from.
|
||||
* zTarget -> Dequoted name of the table to delete from.
|
||||
* pWhere -> The WHERE clause of the DELETE statement if one is specified.
|
||||
* Otherwise NULL.
|
||||
*
|
||||
* (op == TK_UPDATE)
|
||||
* target -> A token holding the quoted name of the table to update rows of.
|
||||
* zTarget -> Dequoted name of the table to update.
|
||||
* pWhere -> The WHERE clause of the UPDATE statement if one is specified.
|
||||
* Otherwise NULL.
|
||||
* pExprList -> A list of the columns to update and the expressions to update
|
||||
|
@ -2794,8 +2801,8 @@ struct TriggerStep {
|
|||
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
|
||||
u8 orconf; /* OE_Rollback etc. */
|
||||
Trigger *pTrig; /* The trigger that this step is a part of */
|
||||
Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */
|
||||
Token target; /* Target table for DELETE, UPDATE, INSERT */
|
||||
Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */
|
||||
char *zTarget; /* Target table for DELETE, UPDATE, INSERT */
|
||||
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
|
||||
ExprList *pExprList; /* SET clause for UPDATE. */
|
||||
IdList *pIdList; /* Column names for INSERT */
|
||||
|
|
|
@ -1191,7 +1191,7 @@ static int dbPrepareAndBind(
|
|||
int n;
|
||||
u8 *data;
|
||||
const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
|
||||
char c = zType[0];
|
||||
c = zType[0];
|
||||
if( zVar[0]=='@' ||
|
||||
(c=='b' && strcmp(zType,"bytearray")==0 && pVar->bytes==0) ){
|
||||
/* Load a BLOB type if the Tcl variable is a bytearray and
|
||||
|
@ -2298,7 +2298,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
|||
}
|
||||
Tcl_DecrRefCount(pRet);
|
||||
}else{
|
||||
ClientData cd[2];
|
||||
ClientData cd2[2];
|
||||
DbEvalContext *p;
|
||||
Tcl_Obj *pArray = 0;
|
||||
Tcl_Obj *pScript;
|
||||
|
@ -2312,9 +2312,9 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
|
|||
p = (DbEvalContext *)Tcl_Alloc(sizeof(DbEvalContext));
|
||||
dbEvalInit(p, pDb, objv[2], pArray);
|
||||
|
||||
cd[0] = (void *)p;
|
||||
cd[1] = (void *)pScript;
|
||||
rc = DbEvalNextCmd(cd, interp, TCL_OK);
|
||||
cd2[0] = (void *)p;
|
||||
cd2[1] = (void *)pScript;
|
||||
rc = DbEvalNextCmd(cd2, interp, TCL_OK);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -211,15 +211,15 @@ static int faultsimInstall(int install){
|
|||
faultsimBeginBenign, faultsimEndBenign
|
||||
);
|
||||
}else{
|
||||
sqlite3_mem_methods m;
|
||||
sqlite3_mem_methods m2;
|
||||
assert(memfault.m.xMalloc);
|
||||
|
||||
/* One should be able to reset the default memory allocator by storing
|
||||
** a zeroed allocator then calling GETMALLOC. */
|
||||
memset(&m, 0, sizeof(m));
|
||||
sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
|
||||
sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m);
|
||||
assert( memcmp(&m, &memfault.m, sizeof(m))==0 );
|
||||
memset(&m2, 0, sizeof(m2));
|
||||
sqlite3_config(SQLITE_CONFIG_MALLOC, &m2);
|
||||
sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m2);
|
||||
assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 );
|
||||
|
||||
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);
|
||||
sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0);
|
||||
|
|
|
@ -568,15 +568,15 @@ static int multiplexOpen(
|
|||
if( pSubOpen==0 && rc==SQLITE_OK ) rc = SQLITE_CANTOPEN;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_int64 sz;
|
||||
sqlite3_int64 sz64;
|
||||
|
||||
rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
|
||||
rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz64);
|
||||
if( rc==SQLITE_OK && zName ){
|
||||
int bExists;
|
||||
if( flags & SQLITE_OPEN_MASTER_JOURNAL ){
|
||||
pGroup->bEnabled = 0;
|
||||
}else
|
||||
if( sz==0 ){
|
||||
if( sz64==0 ){
|
||||
if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
|
||||
/* If opening a main journal file and the first chunk is zero
|
||||
** bytes in size, delete any subsequent chunks from the
|
||||
|
@ -607,10 +607,10 @@ static int multiplexOpen(
|
|||
rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
|
||||
SQLITE_ACCESS_EXISTS, &bExists);
|
||||
bExists = multiplexSubSize(pGroup, 1, &rc)>0;
|
||||
if( rc==SQLITE_OK && bExists && sz==(sz&0xffff0000) && sz>0
|
||||
&& sz!=pGroup->szChunk ){
|
||||
pGroup->szChunk = (int)sz;
|
||||
}else if( rc==SQLITE_OK && !bExists && sz>pGroup->szChunk ){
|
||||
if( rc==SQLITE_OK && bExists && sz64==(sz64&0xffff0000) && sz64>0
|
||||
&& sz64!=pGroup->szChunk ){
|
||||
pGroup->szChunk = (int)sz64;
|
||||
}else if( rc==SQLITE_OK && !bExists && sz64>pGroup->szChunk ){
|
||||
pGroup->bEnabled = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -595,9 +595,9 @@ static int fsOpen(
|
|||
int rc = SQLITE_OK;
|
||||
|
||||
if( 0==(flags&(SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL)) ){
|
||||
tmp_file *p = (tmp_file *)pFile;
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->base.pMethods = &tmp_io_methods;
|
||||
tmp_file *p2 = (tmp_file *)pFile;
|
||||
memset(p2, 0, sizeof(*p2));
|
||||
p2->base.pMethods = &tmp_io_methods;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1131,7 +1131,6 @@ static int test_vfslog(
|
|||
|
||||
switch( (enum VL_enum)iSub ){
|
||||
case VL_ANNOTATE: {
|
||||
int rc;
|
||||
char *zVfs;
|
||||
char *zMsg;
|
||||
if( objc!=4 ){
|
||||
|
@ -1148,7 +1147,6 @@ static int test_vfslog(
|
|||
break;
|
||||
}
|
||||
case VL_FINALIZE: {
|
||||
int rc;
|
||||
char *zVfs;
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "VFS");
|
||||
|
@ -1164,7 +1162,6 @@ static int test_vfslog(
|
|||
};
|
||||
|
||||
case VL_NEW: {
|
||||
int rc;
|
||||
char *zVfs;
|
||||
char *zParent;
|
||||
char *zLog;
|
||||
|
|
|
@ -1080,7 +1080,7 @@ static int testvfs_obj_cmd(
|
|||
switch( aSubcmd[i].eCmd ){
|
||||
case CMD_SHM: {
|
||||
Tcl_Obj *pObj;
|
||||
int i, rc;
|
||||
int rc;
|
||||
TestvfsBuffer *pBuffer;
|
||||
char *zName;
|
||||
if( objc!=3 && objc!=4 ){
|
||||
|
@ -1160,7 +1160,6 @@ static int testvfs_obj_cmd(
|
|||
};
|
||||
Tcl_Obj **apElem = 0;
|
||||
int nElem = 0;
|
||||
int i;
|
||||
int mask = 0;
|
||||
if( objc!=3 ){
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "LIST");
|
||||
|
|
|
@ -516,8 +516,6 @@ abort_parse:
|
|||
pParse->pZombieTab = p->pNextZombie;
|
||||
sqlite3DeleteTable(db, p);
|
||||
}
|
||||
if( nErr>0 && pParse->rc==SQLITE_OK ){
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
}
|
||||
assert( nErr==0 || pParse->rc!=SQLITE_OK );
|
||||
return nErr;
|
||||
}
|
||||
|
|
|
@ -193,7 +193,6 @@ void sqlite3BeginTrigger(
|
|||
/* Do not create a trigger on a system table */
|
||||
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
|
||||
sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
|
||||
pParse->nErr++;
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
|
||||
|
@ -373,12 +372,12 @@ static TriggerStep *triggerStepAllocate(
|
|||
){
|
||||
TriggerStep *pTriggerStep;
|
||||
|
||||
pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n);
|
||||
pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1);
|
||||
if( pTriggerStep ){
|
||||
char *z = (char*)&pTriggerStep[1];
|
||||
memcpy(z, pName->z, pName->n);
|
||||
pTriggerStep->target.z = z;
|
||||
pTriggerStep->target.n = pName->n;
|
||||
sqlite3Dequote(z);
|
||||
pTriggerStep->zTarget = z;
|
||||
pTriggerStep->op = op;
|
||||
}
|
||||
return pTriggerStep;
|
||||
|
@ -661,7 +660,7 @@ Trigger *sqlite3TriggersExist(
|
|||
}
|
||||
|
||||
/*
|
||||
** Convert the pStep->target token into a SrcList and return a pointer
|
||||
** Convert the pStep->zTarget string into a SrcList and return a pointer
|
||||
** to that SrcList.
|
||||
**
|
||||
** This routine adds a specific database name, if needed, to the target when
|
||||
|
@ -674,16 +673,17 @@ static SrcList *targetSrcList(
|
|||
Parse *pParse, /* The parsing context */
|
||||
TriggerStep *pStep /* The trigger containing the target token */
|
||||
){
|
||||
sqlite3 *db = pParse->db;
|
||||
int iDb; /* Index of the database to use */
|
||||
SrcList *pSrc; /* SrcList to be returned */
|
||||
|
||||
pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0);
|
||||
pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
|
||||
if( pSrc ){
|
||||
assert( pSrc->nSrc>0 );
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema);
|
||||
pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget);
|
||||
iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema);
|
||||
if( iDb==0 || iDb>=2 ){
|
||||
sqlite3 *db = pParse->db;
|
||||
assert( iDb<pParse->db->nDb );
|
||||
assert( iDb<db->nDb );
|
||||
pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName);
|
||||
}
|
||||
}
|
||||
|
@ -795,6 +795,7 @@ static void transferParseError(Parse *pTo, Parse *pFrom){
|
|||
if( pTo->nErr==0 ){
|
||||
pTo->zErrMsg = pFrom->zErrMsg;
|
||||
pTo->nErr = pFrom->nErr;
|
||||
pTo->rc = pFrom->rc;
|
||||
}else{
|
||||
sqlite3DbFree(pFrom->db, pFrom->zErrMsg);
|
||||
}
|
||||
|
|
|
@ -655,6 +655,7 @@ int sqlite3GetInt32(const char *zNum, int *pValue){
|
|||
}
|
||||
}
|
||||
#endif
|
||||
while( zNum[0]=='0' ) zNum++;
|
||||
for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
|
||||
v = v*10 + c;
|
||||
}
|
||||
|
|
22
src/vdbe.c
22
src/vdbe.c
|
@ -539,6 +539,9 @@ int sqlite3VdbeExec(
|
|||
){
|
||||
Op *aOp = p->aOp; /* Copy of p->aOp */
|
||||
Op *pOp = aOp; /* Current operation */
|
||||
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
|
||||
Op *pOrigOp; /* Value of pOp at the top of the loop */
|
||||
#endif
|
||||
int rc = SQLITE_OK; /* Value to return */
|
||||
sqlite3 *db = p->db; /* The database */
|
||||
u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
|
||||
|
@ -681,6 +684,9 @@ int sqlite3VdbeExec(
|
|||
memAboutToChange(p, &aMem[pOp->p3]);
|
||||
}
|
||||
#endif
|
||||
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
|
||||
pOrigOp = pOp;
|
||||
#endif
|
||||
|
||||
switch( pOp->opcode ){
|
||||
|
||||
|
@ -2919,7 +2925,7 @@ case OP_Savepoint: {
|
|||
db->nDeferredImmCons = pSavepoint->nDeferredImmCons;
|
||||
}
|
||||
|
||||
if( !isTransaction ){
|
||||
if( !isTransaction || p1==SAVEPOINT_ROLLBACK ){
|
||||
rc = sqlite3VtabSavepoint(db, p1, iSavepoint);
|
||||
if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
||||
}
|
||||
|
@ -6489,8 +6495,8 @@ default: { /* This is really OP_Noop and OP_Explain */
|
|||
#ifdef VDBE_PROFILE
|
||||
{
|
||||
u64 endTime = sqlite3Hwtime();
|
||||
if( endTime>start ) pOp->cycles += endTime - start;
|
||||
pOp->cnt++;
|
||||
if( endTime>start ) pOrigOp->cycles += endTime - start;
|
||||
pOrigOp->cnt++;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -6500,16 +6506,16 @@ default: { /* This is really OP_Noop and OP_Explain */
|
|||
** the evaluator loop. So we can leave it out when NDEBUG is defined.
|
||||
*/
|
||||
#ifndef NDEBUG
|
||||
assert( pOp>=&aOp[-1] && pOp<&aOp[p->nOp] );
|
||||
assert( pOp>=&aOp[-1] && pOp<&aOp[p->nOp-1] );
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( db->flags & SQLITE_VdbeTrace ){
|
||||
if( rc!=0 ) printf("rc=%d\n",rc);
|
||||
if( pOp->opflags & (OPFLG_OUT2) ){
|
||||
registerTrace(pOp->p2, &aMem[pOp->p2]);
|
||||
if( pOrigOp->opflags & (OPFLG_OUT2) ){
|
||||
registerTrace(pOrigOp->p2, &aMem[pOrigOp->p2]);
|
||||
}
|
||||
if( pOp->opflags & OPFLG_OUT3 ){
|
||||
registerTrace(pOp->p3, &aMem[pOp->p3]);
|
||||
if( pOrigOp->opflags & OPFLG_OUT3 ){
|
||||
registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]);
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_DEBUG */
|
||||
|
|
|
@ -1789,6 +1789,22 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Close all cursors in the current frame.
|
||||
*/
|
||||
static void closeCursorsInFrame(Vdbe *p){
|
||||
if( p->apCsr ){
|
||||
int i;
|
||||
for(i=0; i<p->nCursor; i++){
|
||||
VdbeCursor *pC = p->apCsr[i];
|
||||
if( pC ){
|
||||
sqlite3VdbeFreeCursor(p, pC);
|
||||
p->apCsr[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Copy the values stored in the VdbeFrame structure to its Vdbe. This
|
||||
** is used, for example, when a trigger sub-program is halted to restore
|
||||
|
@ -1796,6 +1812,7 @@ void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
|
|||
*/
|
||||
int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
|
||||
Vdbe *v = pFrame->v;
|
||||
closeCursorsInFrame(v);
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
v->anExec = pFrame->anExec;
|
||||
#endif
|
||||
|
@ -1830,17 +1847,7 @@ static void closeAllCursors(Vdbe *p){
|
|||
p->nFrame = 0;
|
||||
}
|
||||
assert( p->nFrame==0 );
|
||||
|
||||
if( p->apCsr ){
|
||||
int i;
|
||||
for(i=0; i<p->nCursor; i++){
|
||||
VdbeCursor *pC = p->apCsr[i];
|
||||
if( pC ){
|
||||
sqlite3VdbeFreeCursor(p, pC);
|
||||
p->apCsr[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
closeCursorsInFrame(p);
|
||||
if( p->aMem ){
|
||||
releaseMemArray(&p->aMem[1], p->nMem);
|
||||
}
|
||||
|
|
|
@ -1647,7 +1647,7 @@ void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
|
|||
Mem *aMem = pRec->aMem;
|
||||
sqlite3 *db = aMem[0].db;
|
||||
for(i=0; i<nCol; i++){
|
||||
if( aMem[i].szMalloc ) sqlite3DbFree(db, aMem[i].zMalloc);
|
||||
sqlite3VdbeMemRelease(&aMem[i]);
|
||||
}
|
||||
sqlite3KeyInfoUnref(pRec->pKeyInfo);
|
||||
sqlite3DbFree(db, pRec);
|
||||
|
|
|
@ -95,6 +95,8 @@ char *sqlite3VdbeExpandSql(
|
|||
assert( (zRawSql - zStart) > 0 );
|
||||
sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart));
|
||||
}
|
||||
}else if( p->nVar==0 ){
|
||||
sqlite3StrAccumAppend(&out, zRawSql, sqlite3Strlen30(zRawSql));
|
||||
}else{
|
||||
while( zRawSql[0] ){
|
||||
n = findNextHostParameter(zRawSql, &nToken);
|
||||
|
@ -111,10 +113,12 @@ char *sqlite3VdbeExpandSql(
|
|||
idx = nextIndex;
|
||||
}
|
||||
}else{
|
||||
assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' );
|
||||
assert( zRawSql[0]==':' || zRawSql[0]=='$' ||
|
||||
zRawSql[0]=='@' || zRawSql[0]=='#' );
|
||||
testcase( zRawSql[0]==':' );
|
||||
testcase( zRawSql[0]=='$' );
|
||||
testcase( zRawSql[0]=='@' );
|
||||
testcase( zRawSql[0]=='#' );
|
||||
idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken);
|
||||
assert( idx>0 );
|
||||
}
|
||||
|
|
13
src/vtab.c
13
src/vtab.c
|
@ -472,7 +472,7 @@ void sqlite3VtabArgExtend(Parse *pParse, Token *p){
|
|||
pArg->z = p->z;
|
||||
pArg->n = p->n;
|
||||
}else{
|
||||
assert(pArg->z < p->z);
|
||||
assert(pArg->z <= p->z);
|
||||
pArg->n = (int)(&p->z[p->n] - pArg->z);
|
||||
}
|
||||
}
|
||||
|
@ -559,6 +559,7 @@ static int vtabCallConstructor(
|
|||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
int iCol;
|
||||
u8 oooHidden = 0;
|
||||
/* If everything went according to plan, link the new VTable structure
|
||||
** into the linked list headed by pTab->pVTable. Then loop through the
|
||||
** columns of the table to see if any of them contain the token "hidden".
|
||||
|
@ -571,7 +572,10 @@ static int vtabCallConstructor(
|
|||
char *zType = pTab->aCol[iCol].zType;
|
||||
int nType;
|
||||
int i = 0;
|
||||
if( !zType ) continue;
|
||||
if( !zType ){
|
||||
pTab->tabFlags |= oooHidden;
|
||||
continue;
|
||||
}
|
||||
nType = sqlite3Strlen30(zType);
|
||||
if( sqlite3StrNICmp("hidden", zType, 6)||(zType[6] && zType[6]!=' ') ){
|
||||
for(i=0; i<nType; i++){
|
||||
|
@ -594,6 +598,9 @@ static int vtabCallConstructor(
|
|||
zType[i-1] = '\0';
|
||||
}
|
||||
pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN;
|
||||
oooHidden = TF_OOOHidden;
|
||||
}else{
|
||||
pTab->tabFlags |= oooHidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -957,7 +964,7 @@ int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
|
|||
int rc = SQLITE_OK;
|
||||
|
||||
assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN );
|
||||
assert( iSavepoint>=0 );
|
||||
assert( iSavepoint>=-1 );
|
||||
if( db->aVTrans ){
|
||||
int i;
|
||||
for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
|
||||
|
|
10
src/where.c
10
src/where.c
|
@ -255,13 +255,14 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
|
|||
** all terms of the WHERE clause.
|
||||
*/
|
||||
static void whereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
|
||||
Expr *pE2 = sqlite3ExprSkipCollate(pExpr);
|
||||
pWC->op = op;
|
||||
if( pExpr==0 ) return;
|
||||
if( pExpr->op!=op ){
|
||||
if( pE2==0 ) return;
|
||||
if( pE2->op!=op ){
|
||||
whereClauseInsert(pWC, pExpr, 0);
|
||||
}else{
|
||||
whereSplit(pWC, pExpr->pLeft, op);
|
||||
whereSplit(pWC, pExpr->pRight, op);
|
||||
whereSplit(pWC, pE2->pLeft, op);
|
||||
whereSplit(pWC, pE2->pRight, op);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6656,7 +6657,6 @@ WhereInfo *sqlite3WhereBegin(
|
|||
}
|
||||
#ifdef WHERETRACE_ENABLED /* !=0 */
|
||||
if( sqlite3WhereTrace ){
|
||||
int ii;
|
||||
sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut);
|
||||
if( pWInfo->nOBSat>0 ){
|
||||
sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask);
|
||||
|
|
|
@ -359,6 +359,6 @@ do_test analyze-99.1 {
|
|||
catchsql {
|
||||
ANALYZE
|
||||
}
|
||||
} {1 {malformed database schema (sqlite_stat1) - near "nonsense": syntax error}}
|
||||
} {1 {malformed database schema (sqlite_stat1)}}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix analyze3
|
||||
|
||||
ifcapable !stat4&&!stat3 {
|
||||
finish_test
|
||||
|
@ -46,6 +47,9 @@ ifcapable !stat4&&!stat3 {
|
|||
#
|
||||
# analyze3-6.*: Test that the problem fixed by commit [127a5b776d] is fixed.
|
||||
#
|
||||
# analyze3-7.*: Test that some memory leaks discovered by fuzz testing
|
||||
# have been fixed.
|
||||
#
|
||||
|
||||
proc getvar {varname} { uplevel #0 set $varname }
|
||||
db function var getvar
|
||||
|
@ -662,4 +666,30 @@ do_eqp_test analyze3-6-2 {
|
|||
SELECT * FROM t1 WHERE a = 5 AND b > 'w' AND c = 13;
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}}
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# 2015-04-20.
|
||||
# Memory leak in sqlite3Stat4ProbeFree(). (Discovered while fuzzing.)
|
||||
#
|
||||
do_execsql_test analyze-7.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c);
|
||||
INSERT INTO t1 VALUES(1,1,'0000');
|
||||
CREATE INDEX t0b ON t1(b);
|
||||
ANALYZE;
|
||||
SELECT c FROM t1 WHERE b=3 AND a BETWEEN 30 AND hex(1);
|
||||
} {}
|
||||
|
||||
# At one point duplicate stat1 entries were causing a memory leak.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 7.2 {
|
||||
CREATE TABLE t1(a,b,c);
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
ANALYZE;
|
||||
SELECT * FROM sqlite_stat1;
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000');
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000');
|
||||
ANALYZE sqlite_master;
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -292,7 +292,7 @@ do_test corruptC-2.15 {
|
|||
hexio_write test.db 986 b9
|
||||
sqlite3 db test.db
|
||||
catchsql {SELECT count(*) FROM sqlite_master;}
|
||||
} {1 {malformed database schema (t1i1) - no such table: main.t1}}
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
#
|
||||
# Now test for a series of quasi-random seeds.
|
||||
|
|
|
@ -191,4 +191,9 @@ do_execsql_test count-5.1 {
|
|||
SELECT count(*) FROM t5;
|
||||
} {1}
|
||||
|
||||
do_catchsql_test count-6.1 {
|
||||
CREATE TABLE t6(x);
|
||||
SELECT count(DISTINCT) FROM t6 GROUP BY x;
|
||||
} {1 {DISTINCT aggregates must have exactly one argument}}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -48,8 +48,11 @@ do_execsql_test e_reindex-1.1 {
|
|||
INSERT INTO t1 VALUES(1, 2);
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
INSERT INTO t1 VALUES(5, 6);
|
||||
|
||||
CREATE TABLE saved(a,b,c,d,e);
|
||||
INSERT INTO saved SELECT * FROM sqlite_master WHERE type = 'index';
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_master SET sql = '-- ' || sql WHERE type = 'index';
|
||||
DELETE FROM sqlite_master WHERE type = 'index';
|
||||
} {}
|
||||
|
||||
db close
|
||||
|
@ -59,7 +62,8 @@ do_execsql_test e_reindex-1.2 {
|
|||
INSERT INTO t1 VALUES(7, 8);
|
||||
INSERT INTO t1 VALUES(9, 10);
|
||||
PRAGMA writable_schema = 1;
|
||||
UPDATE sqlite_master SET sql = substr(sql, 4) WHERE type = 'index';
|
||||
INSERT INTO sqlite_master SELECT * FROM saved;
|
||||
DROP TABLE saved;
|
||||
} {}
|
||||
|
||||
db close
|
||||
|
|
|
@ -943,5 +943,13 @@ do_realnum_test expr-13.7 {
|
|||
}
|
||||
} {9.22337203685478e+18}
|
||||
|
||||
do_execsql_test expr-13.8 {
|
||||
SELECT "" <= '';
|
||||
} {1}
|
||||
do_execsql_test expr-13.9 {
|
||||
SELECT '' <= "";
|
||||
} {1}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -121,4 +121,34 @@ do_test fkey1-3.5 {
|
|||
sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
|
||||
} {0 0 0}
|
||||
|
||||
# Stress the dequoting logic. The first test is not so bad.
|
||||
do_execsql_test fkey1-4.0 {
|
||||
PRAGMA foreign_keys=ON;
|
||||
CREATE TABLE "xx1"("xx2" TEXT PRIMARY KEY, "xx3" TEXT);
|
||||
INSERT INTO "xx1"("xx2","xx3") VALUES('abc','def');
|
||||
CREATE TABLE "xx4"("xx5" TEXT REFERENCES "xx1" ON DELETE CASCADE);
|
||||
INSERT INTO "xx4"("xx5") VALUES('abc');
|
||||
INSERT INTO "xx1"("xx2","xx3") VALUES('uvw','xyz');
|
||||
SELECT 1, "xx5" FROM "xx4";
|
||||
DELETE FROM "xx1";
|
||||
SELECT 2, "xx5" FROM "xx4";
|
||||
} {1 abc}
|
||||
|
||||
# This case is identical to the previous except the "xx" in each name
|
||||
# is changed to a single escaped double-quote character.
|
||||
do_execsql_test fkey1-4.1 {
|
||||
PRAGMA foreign_keys=ON;
|
||||
CREATE TABLE """1"("""2" TEXT PRIMARY KEY, """3" TEXT);
|
||||
INSERT INTO """1"("""2","""3") VALUES('abc','def');
|
||||
CREATE TABLE """4"("""5" TEXT REFERENCES """1" ON DELETE CASCADE);
|
||||
INSERT INTO """4"("""5") VALUES('abc');
|
||||
INSERT INTO """1"("""2","""3") VALUES('uvw','xyz');
|
||||
SELECT 1, """5" FROM """4";
|
||||
DELETE FROM """1";
|
||||
SELECT 2, """5" FROM """4";
|
||||
} {1 abc}
|
||||
do_execsql_test fkey1-4.2 {
|
||||
PRAGMA table_info="""1";
|
||||
} {0 {"2} TEXT 0 {} 1 1 {"3} TEXT 0 {} 0}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -676,6 +676,11 @@ do_test fkey2-9.2.3 {
|
|||
SELECT * FROM cc;
|
||||
}
|
||||
} {{} A {} {} B {} 3 A 2 3 B 2}
|
||||
do_execsql_test fkey2-9.3.0 {
|
||||
CREATE TABLE t3(x PRIMARY KEY REFERENCES t3 ON DELETE SET NULL);
|
||||
INSERT INTO t3(x) VALUES(12345);
|
||||
DROP TABLE t3;
|
||||
} {}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests, fkey2-10.*, test "foreign key mismatch" and
|
||||
|
@ -2014,4 +2019,18 @@ do_test fkey2-ce7c13.1.6 {
|
|||
}
|
||||
} {1 {FOREIGN KEY constraint failed}}
|
||||
|
||||
# 2015-04-16: Foreign key errors propagate back up to the parser.
|
||||
#
|
||||
do_test fkey2-20150416-100 {
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
catchsql {
|
||||
PRAGMA foreign_keys=1;
|
||||
CREATE TABLE t1(x PRIMARY KEY);
|
||||
CREATE TABLE t(y REFERENCES t0(x)ON DELETE SET DEFAULT);
|
||||
CREATE TABLE t0(y REFERENCES t1 ON DELETE SET NULL);
|
||||
REPLACE INTO t1 SELECT(0);CREATE TABLE t2(x);CREATE TABLE t3;
|
||||
}
|
||||
} {1 {foreign key mismatch - "t" referencing "t0"}}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix fts3aa
|
||||
|
||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
ifcapable !fts3 {
|
||||
|
@ -221,5 +222,26 @@ do_catchsql_test fts3aa-7.5 {
|
|||
CREATE VIRTUAL TABLE t4 USING fts4(tokenize=simple, tokenize=simple);
|
||||
} {1 {unrecognized parameter: tokenize=simple}}
|
||||
|
||||
do_execsql_test 8.0 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts4(order=desc);
|
||||
BEGIN;
|
||||
INSERT INTO t0(rowid, content) VALUES(1, 'abc');
|
||||
UPDATE t0 SET docid=5 WHERE docid=1;
|
||||
INSERT INTO t0(rowid, content) VALUES(6, 'abc');
|
||||
}
|
||||
do_execsql_test 8.1 {
|
||||
SELECT docid FROM t0 WHERE t0 MATCH 'abc';
|
||||
} {6 5}
|
||||
do_execsql_test 8.2 {
|
||||
SELECT docid FROM t0 WHERE t0 MATCH '"abc abc"';
|
||||
} {}
|
||||
do_execsql_test 8.3 { COMMIT }
|
||||
do_execsql_test 8.4 {
|
||||
SELECT docid FROM t0 WHERE t0 MATCH 'abc';
|
||||
} {6 5}
|
||||
do_execsql_test 8.5 {
|
||||
SELECT docid FROM t0 WHERE t0 MATCH '"abc abc"';
|
||||
} {}
|
||||
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
# 2006 September 9
|
||||
#
|
||||
# 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 script is testing the FTS3 module.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix fts3expr5
|
||||
|
||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||
ifcapable !fts3 {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Various forms of empty phrase expressions.
|
||||
#
|
||||
do_execsql_test 1.0 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts3(x);
|
||||
SELECT rowid FROM t0 WHERE x MATCH '';
|
||||
} {}
|
||||
do_execsql_test 1.1 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '""';
|
||||
} {}
|
||||
do_execsql_test 1.2 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '"" ""';
|
||||
} {}
|
||||
do_execsql_test 1.3 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '"" OR ""';
|
||||
} {}
|
||||
do_execsql_test 1.4 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '"" NOT ""';
|
||||
} {}
|
||||
do_execsql_test 1.5 {
|
||||
SELECT rowid FROM t0 WHERE x MATCH '""""';
|
||||
} {}
|
||||
|
||||
finish_test
|
|
@ -179,5 +179,35 @@ do_test 4.2 {
|
|||
} {1 {database disk image is malformed}}
|
||||
reset_db
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Test case 5.*
|
||||
#
|
||||
# Test that the integrity-check works if there is uncommitted data.
|
||||
#
|
||||
do_execsql_test 5.0 {
|
||||
BEGIN;
|
||||
CREATE VIRTUAL TABLE t5 USING fts4(a, prefix="1,2,3");
|
||||
INSERT INTO t5 VALUES('And down by Kosiosko, where the reed-banks sweep');
|
||||
INSERT INTO t5 VALUES('and sway, and the rolling plains are wide, the');
|
||||
INSERT INTO t5 VALUES('man from snowy river is a household name today,');
|
||||
INSERT INTO t5 VALUES('and the stockmen tell the story of his ride');
|
||||
}
|
||||
|
||||
do_execsql_test 5.1 {
|
||||
INSERT INTO t5(t5) VALUES('integrity-check');
|
||||
} {}
|
||||
|
||||
do_catchsql_test 5.2 {
|
||||
INSERT INTO t5_content VALUES(5, 'his hardy mountain pony');
|
||||
INSERT INTO t5(t5) VALUES('integrity-check');
|
||||
} {1 {database disk image is malformed}}
|
||||
|
||||
do_execsql_test 5.3 ROLLBACK
|
||||
|
||||
do_execsql_test 5.4 {
|
||||
CREATE VIRTUAL TABLE t5 USING fts4(a, prefix="1,2,3");
|
||||
INSERT INTO t5(t5) VALUES('integrity-check');
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
||||
|
|
|
@ -51,6 +51,6 @@ do_test index3-99.1 {
|
|||
db close
|
||||
catch { sqlite3 db test.db }
|
||||
catchsql { DROP INDEX i1 }
|
||||
} {1 {malformed database schema (t1) - near "nonsense": syntax error}}
|
||||
} {1 {malformed database schema (t1)}}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -311,5 +311,9 @@ do_eqp_test index7-6.4 {
|
|||
} {
|
||||
0 0 0 {SEARCH TABLE t4 USING INDEX i4 (c=?)}
|
||||
}
|
||||
do_catchsql_test index7-6.5 {
|
||||
CREATE INDEX t5a ON t5(a) WHERE a=#1;
|
||||
} {1 {near "#1": syntax error}}
|
||||
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix insert2
|
||||
|
||||
# Create some tables with data that we can select against
|
||||
#
|
||||
|
@ -275,4 +276,23 @@ ifcapable subquery {
|
|||
} {1 2 1 3 1 4}
|
||||
}
|
||||
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE t5(a, b, c DEFAULT 'c', d);
|
||||
}
|
||||
do_execsql_test 6.1 {
|
||||
INSERT INTO t5(a) SELECT 456 UNION ALL SELECT 123 ORDER BY 1;
|
||||
SELECT * FROM t5 ORDER BY rowid;
|
||||
} {123 {} c {} 456 {} c {}}
|
||||
|
||||
ifcapable fts3 {
|
||||
do_execsql_test 6.2 {
|
||||
CREATE VIRTUAL TABLE t0 USING fts4(a);
|
||||
}
|
||||
do_execsql_test 6.3 {
|
||||
INSERT INTO t0 SELECT 0 UNION SELECT 0 AS 'x' ORDER BY x;
|
||||
SELECT * FROM t0;
|
||||
} {0}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -560,5 +560,10 @@ do_test insert4-8.25 {
|
|||
}
|
||||
} {1 3}
|
||||
|
||||
do_catchsql_test insert4-9.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(x);
|
||||
INSERT INTO t1(x) VALUES(5 COLLATE xyzzy) UNION SELECT 0;
|
||||
} {1 {no such collation sequence: xyzzy}}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -644,4 +644,44 @@ do_execsql_test misc1-22.1 {
|
|||
SELECT ""+3 FROM (SELECT ""+5);
|
||||
} {3}
|
||||
|
||||
# 2015-04-19: NULL pointer dereference on a corrupt schema
|
||||
#
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
do_execsql_test misc1-23.1 {
|
||||
CREATE TABLE t1(x);
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_master SET sql='CREATE table t(d CHECK(T(#0)';
|
||||
BEGIN;
|
||||
CREATE TABLE t2(y);
|
||||
ROLLBACK;
|
||||
DROP TABLE IF EXISTS t3;
|
||||
} {}
|
||||
|
||||
# 2015-04-19: Faulty assert() statement
|
||||
#
|
||||
db close
|
||||
database_may_be_corrupt
|
||||
sqlite3 db :memory:
|
||||
do_catchsql_test misc1-23.2 {
|
||||
CREATE TABLE t1(x UNIQUE);
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_master SET sql='CREATE TABLE IF not EXISTS t(c)';
|
||||
BEGIN;
|
||||
CREATE TABLE t2(x);
|
||||
ROLLBACK;
|
||||
DROP TABLE F;
|
||||
} {1 {no such table: F}}
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
do_catchsql_test misc1-23.3 {
|
||||
CREATE TABLE t1(x UNIQUE);
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_master SET sql='CREATE table y(a TEXT, a TEXT)';
|
||||
BEGIN;
|
||||
CREATE TABLE t2(y);
|
||||
ROLLBACK;
|
||||
DROP TABLE IF EXISTS t;
|
||||
} {0 {}}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -583,6 +583,24 @@ do_test misc5-7.1 {
|
|||
catchsql $sql
|
||||
} {1 {parser stack overflow}}
|
||||
|
||||
# Parser stack overflow is silently ignored when it occurs while parsing the
|
||||
# schema and PRAGMA writable_schema is turned on.
|
||||
#
|
||||
do_test misc5-7.2 {
|
||||
sqlite3 db2 :memory:
|
||||
catchsql {
|
||||
CREATE TABLE t1(x UNIQUE);
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_master SET sql='CREATE table t(o CHECK(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((;VALUES(o)';
|
||||
BEGIN;
|
||||
CREATE TABLE t2(y);
|
||||
ROLLBACK;
|
||||
DROP TABLE IF EXISTS D;
|
||||
} db2
|
||||
} {0 {}}
|
||||
db2 close
|
||||
|
||||
|
||||
# Ticket #1911
|
||||
#
|
||||
ifcapable compound {
|
||||
|
|
|
@ -219,6 +219,24 @@ do_test pragma-1.14 {
|
|||
PRAGMA synchronous;
|
||||
}
|
||||
} {2}
|
||||
do_test pragma-1.14.1 {
|
||||
execsql {
|
||||
PRAGMA synchronous=4;
|
||||
PRAGMA synchronous;
|
||||
}
|
||||
} {0}
|
||||
do_test pragma-1.14.2 {
|
||||
execsql {
|
||||
PRAGMA synchronous=3;
|
||||
PRAGMA synchronous;
|
||||
}
|
||||
} {0}
|
||||
do_test pragma-1.14.3 {
|
||||
execsql {
|
||||
PRAGMA synchronous=10;
|
||||
PRAGMA synchronous;
|
||||
}
|
||||
} {2}
|
||||
} ;# ifcapable pager_pragmas
|
||||
|
||||
# Test turning "flag" pragmas on and off.
|
||||
|
|
|
@ -14,6 +14,7 @@ optional) are:
|
|||
--config CONFIGNAME (Run only CONFIGNAME)
|
||||
--quick (Run "veryquick.test" only)
|
||||
--veryquick (Run "make smoketest" only)
|
||||
--msvc (Use MSVC as the compiler)
|
||||
--buildonly (Just build testfixture - do not run)
|
||||
--dryrun (Print what would have happened)
|
||||
--info (Show diagnostic info)
|
||||
|
@ -22,8 +23,9 @@ The default value for --srcdir is the parent of the directory holding
|
|||
this script.
|
||||
|
||||
The script determines the default value for --platform using the
|
||||
$tcl_platform(os) and $tcl_platform(machine) variables. Supported
|
||||
platforms are "Linux-x86", "Linux-x86_64" and "Darwin-i386".
|
||||
$tcl_platform(os) and $tcl_platform(machine) variables. Supported
|
||||
platforms are "Linux-x86", "Linux-x86_64", "Darwin-i386",
|
||||
"Darwin-x86_64", "Windows NT-intel", and "Windows NT-amd64".
|
||||
|
||||
Every test begins with a fresh run of the configure script at the top
|
||||
of the SQLite source tree.
|
||||
|
@ -239,6 +241,10 @@ array set ::Platforms [strip_comments {
|
|||
"Default" "mptest fulltestonly"
|
||||
"Have-Not" test
|
||||
}
|
||||
"Windows NT-amd64" {
|
||||
"Default" "mptest fulltestonly"
|
||||
"Have-Not" test
|
||||
}
|
||||
|
||||
# The Failure-Detection platform runs various tests that deliberately
|
||||
# fail. This is used as a test of this script to verify that this script
|
||||
|
@ -297,6 +303,13 @@ proc count_tests_and_errors {logfile rcVar errmsgVar} {
|
|||
set errmsg $msg
|
||||
}
|
||||
}
|
||||
if {[regexp {fatal error +(.*)} $line all msg]} {
|
||||
incr ::NERRCASE
|
||||
if {$rc==0} {
|
||||
set rc 1
|
||||
set errmsg $msg
|
||||
}
|
||||
}
|
||||
if {[regexp {ERROR SUMMARY: (\d+) errors.*} $line all cnt] && $cnt>0} {
|
||||
incr ::NERRCASE
|
||||
if {$rc==0} {
|
||||
|
@ -315,7 +328,13 @@ proc count_tests_and_errors {logfile rcVar errmsgVar} {
|
|||
}
|
||||
}
|
||||
close $fd
|
||||
if {!$seen} {
|
||||
if {$::BUILDONLY} {
|
||||
if {$rc==0} {
|
||||
set errmsg "Build complete"
|
||||
} else {
|
||||
set errmsg "Build failed"
|
||||
}
|
||||
} elseif {!$seen} {
|
||||
set rc 1
|
||||
set errmsg "Test did not complete"
|
||||
if {[file readable core]} {
|
||||
|
@ -330,7 +349,7 @@ proc run_test_suite {name testtarget config} {
|
|||
# CFLAGS. The makefile will pass OPTS to both gcc and lemon, but
|
||||
# CFLAGS is only passed to gcc.
|
||||
#
|
||||
set cflags "-g"
|
||||
set cflags [expr {$::MSVC ? "-Zi" : "-g"}]
|
||||
set opts ""
|
||||
set title ${name}($testtarget)
|
||||
set configOpts ""
|
||||
|
@ -350,7 +369,14 @@ proc run_test_suite {name testtarget config} {
|
|||
|
||||
set cflags [join $cflags " "]
|
||||
set opts [join $opts " "]
|
||||
append opts " -DSQLITE_NO_SYNC=1 -DHAVE_USLEEP"
|
||||
append opts " -DSQLITE_NO_SYNC=1"
|
||||
|
||||
# Some configurations already set HAVE_USLEEP; in that case, skip it.
|
||||
#
|
||||
if {![regexp { -DHAVE_USLEEP$} $opts]
|
||||
&& ![regexp { -DHAVE_USLEEP[ =]+} $opts]} {
|
||||
append opts " -DHAVE_USLEEP=1"
|
||||
}
|
||||
|
||||
# Set the sub-directory to use.
|
||||
#
|
||||
|
@ -391,10 +417,10 @@ proc run_test_suite {name testtarget config} {
|
|||
if {$rc} {
|
||||
puts " FAIL $tm"
|
||||
incr ::NERR
|
||||
if {$errmsg!=""} {puts " $errmsg"}
|
||||
} else {
|
||||
puts " Ok $tm"
|
||||
}
|
||||
if {$errmsg!=""} {puts " $errmsg"}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -402,6 +428,7 @@ proc run_test_suite {name testtarget config} {
|
|||
# the current platform, which may be Windows (via MinGW, etc).
|
||||
#
|
||||
proc configureCommand {opts} {
|
||||
if {$::MSVC} return [list]; # This is not needed for MSVC.
|
||||
set result [list trace_cmd exec]
|
||||
if {$::tcl_platform(platform)=="windows"} {
|
||||
lappend result sh
|
||||
|
@ -415,7 +442,14 @@ proc configureCommand {opts} {
|
|||
# specified targets, compiler flags, and options.
|
||||
#
|
||||
proc makeCommand { targets cflags opts } {
|
||||
set result [list trace_cmd exec make clean]
|
||||
set result [list trace_cmd exec]
|
||||
if {$::MSVC} {
|
||||
set nmakeDir [file nativename $::SRCDIR]
|
||||
set nmakeFile [file join $nmakeDir Makefile.msc]
|
||||
lappend result nmake /f $nmakeFile TOP=$nmakeDir clean
|
||||
} else {
|
||||
lappend result make clean
|
||||
}
|
||||
foreach target $targets {
|
||||
lappend result $target
|
||||
}
|
||||
|
@ -444,6 +478,7 @@ proc trace_cmd {args} {
|
|||
proc process_options {argv} {
|
||||
set ::SRCDIR [file normalize [file dirname [file dirname $::argv0]]]
|
||||
set ::QUICK 0
|
||||
set ::MSVC 0
|
||||
set ::BUILDONLY 0
|
||||
set ::DRYRUN 0
|
||||
set ::EXEC exec
|
||||
|
@ -477,6 +512,10 @@ proc process_options {argv} {
|
|||
set config [lindex $argv $i]
|
||||
}
|
||||
|
||||
-msvc {
|
||||
set ::MSVC 1
|
||||
}
|
||||
|
||||
-buildonly {
|
||||
set ::BUILDONLY 1
|
||||
}
|
||||
|
@ -495,6 +534,7 @@ proc process_options {argv} {
|
|||
puts " --platform [list $platform]"
|
||||
puts " --config [list $config]"
|
||||
if {$::QUICK} {puts " --quick"}
|
||||
if {$::MSVC} {puts " --msvc"}
|
||||
if {$::BUILDONLY} {puts " --buildonly"}
|
||||
if {$::DRYRUN} {puts " --dryrun"}
|
||||
if {$::TRACE} {puts " --trace"}
|
||||
|
@ -508,7 +548,15 @@ proc process_options {argv} {
|
|||
}
|
||||
exit
|
||||
}
|
||||
-g -
|
||||
|
||||
-g {
|
||||
if {$::MSVC} {
|
||||
lappend ::EXTRACONFIG -Zi
|
||||
} else {
|
||||
lappend ::EXTRACONFIG [lindex $argv $i]
|
||||
}
|
||||
}
|
||||
|
||||
-D* -
|
||||
-O* -
|
||||
-enable-* -
|
||||
|
@ -548,6 +596,7 @@ proc process_options {argv} {
|
|||
puts -nonewline "Flags:"
|
||||
if {$::DRYRUN} {puts -nonewline " --dryrun"}
|
||||
if {$::BUILDONLY} {puts -nonewline " --buildonly"}
|
||||
if {$::MSVC} {puts -nonewline " --msvc"}
|
||||
switch -- $::QUICK {
|
||||
1 {puts -nonewline " --quick"}
|
||||
2 {puts -nonewline " --veryquick"}
|
||||
|
@ -571,12 +620,20 @@ proc main {argv} {
|
|||
set ::SQLITE_VERSION {}
|
||||
set STARTTIME [clock seconds]
|
||||
foreach {zConfig target} $::CONFIGLIST {
|
||||
if {$::MSVC && ($zConfig eq "Sanitize" || "checksymbols" in $target
|
||||
|| "valgrindtest" in $target)} {
|
||||
puts "Skipping $zConfig / $target for MSVC..."
|
||||
continue
|
||||
}
|
||||
if {$target ne "checksymbols"} {
|
||||
switch -- $::QUICK {
|
||||
1 {set target test}
|
||||
2 {set target smoketest}
|
||||
}
|
||||
if {$::BUILDONLY} {set target testfixture}
|
||||
if {$::BUILDONLY} {
|
||||
set target testfixture
|
||||
if {$::MSVC} {append target .exe}
|
||||
}
|
||||
}
|
||||
set config_options [concat $::Configs($zConfig) $::EXTRACONFIG]
|
||||
|
||||
|
|
|
@ -11,10 +11,12 @@
|
|||
#
|
||||
# This file tests features of the name resolver (the component that
|
||||
# figures out what identifiers in the SQL statement refer to) that
|
||||
# were fixed by ticket [2500cdb9be]
|
||||
# were fixed by ticket [2500cdb9be].
|
||||
#
|
||||
# See also tickets [1c69be2daf] and [f617ea3125] from 2013-08-14.
|
||||
#
|
||||
# Also a fuzzer-discovered problem on 2015-04-23.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
@ -201,6 +203,12 @@ do_execsql_test resolver01-6.3 {
|
|||
GROUP BY lower(name);
|
||||
} {1 {} 1 {}}
|
||||
|
||||
do_execsql_test resolver01-7.1 {
|
||||
SELECT 2 AS x WHERE (SELECT x AS y WHERE 3>y);
|
||||
} {2}
|
||||
do_execsql_test resolver01-7.2 {
|
||||
SELECT 2 AS x WHERE (SELECT x AS y WHERE 1>y);
|
||||
} {}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -307,6 +307,9 @@ do_test select1-4.4 {
|
|||
set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1)}} msg]
|
||||
lappend v $msg
|
||||
} {1 {misuse of aggregate: min()}}
|
||||
do_catchsql_test select1-4.5 {
|
||||
INSERT INTO test1(f1) SELECT f1 FROM test1 ORDER BY min(f1);
|
||||
} {1 {misuse of aggregate: min()}}
|
||||
|
||||
# The restriction not allowing constants in the ORDER BY clause
|
||||
# has been removed. See ticket #1768
|
||||
|
@ -1072,5 +1075,10 @@ if {[db one {PRAGMA locking_mode}]=="normal"} {
|
|||
do_test select1-16.1 {
|
||||
catchsql {SELECT 1 FROM (SELECT *)}
|
||||
} {1 {no tables specified}}
|
||||
|
||||
# 2015-04-17: assertion fix.
|
||||
do_catchsql_test select1-16.2 {
|
||||
SELECT 1 FROM sqlite_master LIMIT 1,#1;
|
||||
} {1 {near "#1": syntax error}}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -118,6 +118,10 @@ do_test select4-1.3 {
|
|||
}} msg]
|
||||
lappend v $msg
|
||||
} {1 {ORDER BY clause should come after UNION ALL not before}}
|
||||
do_catchsql_test select4-1.4 {
|
||||
SELECT (VALUES(0) INTERSECT SELECT(0) UNION SELECT(0) ORDER BY 1 UNION
|
||||
SELECT 0 UNION SELECT 0 ORDER BY 1);
|
||||
} {1 {ORDER BY clause should come after UNION not before}}
|
||||
|
||||
# Union operator
|
||||
#
|
||||
|
@ -148,6 +152,12 @@ do_test select4-2.3 {
|
|||
}} msg]
|
||||
lappend v $msg
|
||||
} {1 {ORDER BY clause should come after UNION not before}}
|
||||
do_test select4-2.4 {
|
||||
set v [catch {execsql {
|
||||
SELECT 0 ORDER BY (SELECT 0) UNION SELECT 0;
|
||||
}} msg]
|
||||
lappend v $msg
|
||||
} {1 {ORDER BY clause should come after UNION not before}}
|
||||
|
||||
# Except operator
|
||||
#
|
||||
|
@ -874,6 +884,17 @@ do_execsql_test select4-14.10 {
|
|||
do_execsql_test select4-14.11 {
|
||||
SELECT (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4)
|
||||
} {1}
|
||||
|
||||
do_execsql_test select4-14.12 {
|
||||
VALUES(1) UNION VALUES(2);
|
||||
} {1 2}
|
||||
do_execsql_test select4-14.13 {
|
||||
VALUES(1),(2),(3) EXCEPT VALUES(2);
|
||||
} {1 3}
|
||||
do_execsql_test select4-14.14 {
|
||||
VALUES(1),(2),(3) EXCEPT VALUES(1),(3);
|
||||
} {2}
|
||||
do_execsql_test select4-14.15 {
|
||||
SELECT * FROM (SELECT 123), (SELECT 456) ON likely(0 OR 1) OR 0;
|
||||
} {123 456}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -584,4 +584,14 @@ do_test subquery-7.11 {
|
|||
} {30303}
|
||||
} ;############# Disabled
|
||||
|
||||
# 2015-04-21.
|
||||
# Verify that a memory leak in the table column type and collation analysis
|
||||
# is plugged.
|
||||
#
|
||||
do_execsql_test subquery-8.1 {
|
||||
CREATE TABLE t8(a TEXT, b INT);
|
||||
SELECT (SELECT 0 FROM (SELECT * FROM t1)) AS x WHERE x;
|
||||
SELECT (SELECT 0 FROM (SELECT * FROM (SELECT 0))) AS x WHERE x;
|
||||
} {}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -272,6 +272,25 @@ do_test table-5.2.1 {
|
|||
}
|
||||
} {}
|
||||
|
||||
do_test table-5.2.2 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t0(a,b);
|
||||
CREATE INDEX t ON t0(a);
|
||||
PRAGMA writable_schema=ON;
|
||||
UPDATE sqlite_master SET sql='CREATE TABLE a.b(a UNIQUE';
|
||||
BEGIN;
|
||||
CREATE TABLE t1(x);
|
||||
ROLLBACK;
|
||||
DROP TABLE IF EXISTS t99;
|
||||
}
|
||||
} {}
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
|
||||
# Make sure an EXPLAIN does not really create a new table
|
||||
#
|
||||
do_test table-5.3 {
|
||||
|
|
|
@ -143,7 +143,7 @@ ifcapable fts3 {
|
|||
INSERT INTO x1(x1) VALUES('optimize');
|
||||
} {
|
||||
"INSERT INTO x1(x1) VALUES('optimize');"
|
||||
"-- SELECT DISTINCT level / (1024 * ?) FROM 'main'.'x1_segdir'"
|
||||
"-- SELECT ? UNION SELECT level / (1024 * ?) FROM 'main'.'x1_segdir'"
|
||||
"-- SELECT idx, start_block, leaves_end_block, end_block, root FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ?ORDER BY level DESC, idx ASC"
|
||||
"-- SELECT max(level) FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ?"
|
||||
"-- SELECT coalesce((SELECT max(blockid) FROM 'main'.'x1_segments') + 1, 1)"
|
||||
|
|
|
@ -114,6 +114,6 @@ do_test trigger7-99.1 {
|
|||
db close
|
||||
catch { sqlite3 db test.db }
|
||||
catchsql { DROP TRIGGER t2r5 }
|
||||
} {1 {malformed database schema (t2r12) - near "nonsense": syntax error}}
|
||||
} {1 {malformed database schema (t2r12)}}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix triggerC
|
||||
ifcapable {!trigger} {
|
||||
finish_test
|
||||
return
|
||||
|
@ -993,4 +994,52 @@ reset_db
|
|||
optimization_control db factor-constants 0
|
||||
do_execsql_test triggerC-14.2 $SQL {1 2 3}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that table names used by trigger programs are dequoted exactly
|
||||
# once.
|
||||
#
|
||||
do_execsql_test 15.1.1 {
|
||||
PRAGMA recursive_triggers = 1;
|
||||
CREATE TABLE node(
|
||||
id int not null primary key,
|
||||
pid int not null default 0 references node,
|
||||
key varchar not null,
|
||||
path varchar default '',
|
||||
unique(pid, key)
|
||||
);
|
||||
CREATE TRIGGER node_delete_referencing AFTER DELETE ON "node"
|
||||
BEGIN
|
||||
DELETE FROM "node" WHERE pid = old."id";
|
||||
END;
|
||||
}
|
||||
do_execsql_test 15.1.2 {
|
||||
INSERT INTO node(id, pid, key) VALUES(9, 0, 'test');
|
||||
INSERT INTO node(id, pid, key) VALUES(90, 9, 'test1');
|
||||
INSERT INTO node(id, pid, key) VALUES(900, 90, 'test2');
|
||||
DELETE FROM node WHERE id=9;
|
||||
SELECT * FROM node;
|
||||
}
|
||||
|
||||
do_execsql_test 15.2.1 {
|
||||
CREATE TABLE x1 (x);
|
||||
|
||||
CREATE TABLE x2 (a, b);
|
||||
CREATE TABLE '"x2"'(a, b);
|
||||
|
||||
INSERT INTO x2 VALUES(1, 2);
|
||||
INSERT INTO x2 VALUES(3, 4);
|
||||
INSERT INTO '"x2"' SELECT * FROM x2;
|
||||
|
||||
CREATE TRIGGER x1ai AFTER INSERT ON x1 BEGIN
|
||||
INSERT INTO """x2""" VALUES('x', 'y');
|
||||
DELETE FROM """x2""" WHERE a=1;
|
||||
UPDATE """x2""" SET b = 11 WHERE a = 3;
|
||||
END;
|
||||
|
||||
INSERT INTO x1 VALUES('go!');
|
||||
}
|
||||
|
||||
do_execsql_test 15.2.2 { SELECT * FROM x2; } {1 2 3 4}
|
||||
do_execsql_test 15.2.3 { SELECT * FROM """x2"""; } {3 11 x y}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -1491,4 +1491,41 @@ do_test 23.3.1 {
|
|||
} {1 {database table is locked}}
|
||||
do_execsql_test 23.3.2 { SELECT * FROM t1e } {1 2 3 4}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# At one point SQL like this:
|
||||
#
|
||||
# SAVEPOINT xyz; -- Opens SQL transaction
|
||||
# INSERT INTO vtab -- Write to virtual table
|
||||
# ROLLBACK TO xyz;
|
||||
# RELEASE xyz;
|
||||
#
|
||||
# was not invoking the xRollbackTo() callback for the ROLLBACK TO
|
||||
# operation. Which meant that virtual tables like FTS3 would incorrectly
|
||||
# commit the results of the INSERT as part of the "RELEASE xyz" command.
|
||||
#
|
||||
# The following tests check that this has been fixed.
|
||||
#
|
||||
ifcapable fts3 {
|
||||
do_execsql_test 24.0 {
|
||||
CREATE VIRTUAL TABLE t4 USING fts3();
|
||||
SAVEPOINT a;
|
||||
INSERT INTO t4 VALUES('a b c');
|
||||
ROLLBACK TO a;
|
||||
RELEASE a;
|
||||
SELECT * FROM t4;
|
||||
} {}
|
||||
|
||||
do_execsql_test 24.1 { SELECT * FROM t4 WHERE t4 MATCH 'b' } {}
|
||||
do_execsql_test 24.2 { INSERT INTO t4(t4) VALUES('integrity-check') } {}
|
||||
|
||||
do_execsql_test 24.3 {
|
||||
SAVEPOINT a;
|
||||
CREATE VIRTUAL TABLE t5 USING fts3();
|
||||
SAVEPOINT b;
|
||||
ROLLBACK TO a;
|
||||
SAVEPOINT c;
|
||||
RELEASE a;
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
|
|
@ -74,28 +74,39 @@ do_test vtabA-1.6 {
|
|||
SELECT * FROM t1e;
|
||||
}
|
||||
} {{value a} {value c}}
|
||||
do_execsql_test vtabA-1.7 {
|
||||
DELETE FROM t1e;
|
||||
INSERT INTO t1e SELECT 'abc','def';
|
||||
} {}
|
||||
do_execsql_test vtabA-1.8 {
|
||||
INSERT INTO t1e VALUES('ghi','jkl'),('mno','pqr'),('stu','vwx');
|
||||
} {}
|
||||
do_execsql_test vtabA-1.9 {
|
||||
SELECT a,b,c, '|' FROM t1e ORDER BY 1;
|
||||
} {abc {} def | ghi {} jkl | mno {} pqr | stu {} vwx |}
|
||||
|
||||
|
||||
# Test that the expansion of a '*' expression in the result set of
|
||||
# a SELECT does not include the hidden column.
|
||||
#
|
||||
do_test vtabA-1.7 {
|
||||
do_test vtabA-1.20 {
|
||||
execsql {
|
||||
INSERT INTO t1e SELECT * FROM t1e;
|
||||
}
|
||||
} {}
|
||||
do_test vtabA-1.8 {
|
||||
do_test vtabA-1.21 {
|
||||
execsql {
|
||||
SELECT * FROM t1e;
|
||||
SELECT * FROM t1e ORDER BY 1;
|
||||
}
|
||||
} {{value a} {value c} {value a} {value c}}
|
||||
} {abc def abc def ghi jkl ghi jkl mno pqr mno pqr stu vwx stu vwx}
|
||||
|
||||
# Test that the declaration type of the hidden column does not include
|
||||
# the token "HIDDEN".
|
||||
#
|
||||
do_test vtabA-1.9 {
|
||||
do_test vtabA-1.22 {
|
||||
get_decltype t1e b
|
||||
} {VARCHAR}
|
||||
do_test vtabA-1.10 {
|
||||
do_test vtabA-1.23 {
|
||||
get_collist t1e
|
||||
} {a c}
|
||||
|
||||
|
|
|
@ -28,6 +28,11 @@ REM In the example above, "C:\dev\sqlite\core" represents the root of the
|
|||
REM source tree for SQLite and "C:\Temp" represents the final destination
|
||||
REM directory for the generated output files.
|
||||
REM
|
||||
REM Please note that the SQLite build process performed by the Makefile
|
||||
REM associated with this batch script requires both Gawk ^(gawk.exe^) and Tcl
|
||||
REM 8.5 ^(tclsh85.exe^) to be present in a directory contained in the PATH
|
||||
REM environment variable unless a pre-existing amalgamation file is used.
|
||||
REM
|
||||
REM There are several environment variables that may be set to modify the
|
||||
REM behavior of this batch script and its associated Makefile. The list of
|
||||
REM platforms to build may be overriden by using the PLATFORMS environment
|
||||
|
@ -37,17 +42,58 @@ REM being used. The list of configurations to build may be overridden by
|
|||
REM setting the CONFIGURATIONS environment variable, which should contain a
|
||||
REM list of configurations to build ^(e.g. Debug Retail^). Neither of these
|
||||
REM variable values may contain any double quotes, surrounding or embedded.
|
||||
REM Finally, the NCRTLIBPATH and NSDKLIBPATH environment variables may be set
|
||||
REM to specify the location of the CRT and SDK, respectively, needed to compile
|
||||
REM executables native to the architecture of the build machine during any
|
||||
REM cross-compilation that may be necessary, depending on the platforms to be
|
||||
REM built. These values in these two variables should be surrounded by double
|
||||
REM quotes if they contain spaces.
|
||||
REM
|
||||
REM Please note that the SQLite build process performed by the Makefile
|
||||
REM associated with this batch script requires both Gawk ^(gawk.exe^) and Tcl
|
||||
REM 8.5 ^(tclsh85.exe^) to be present in a directory contained in the PATH
|
||||
REM environment variable unless a pre-existing amalgamation file is used.
|
||||
REM Finally, the NCRTLIBPATH, NUCRTLIBPATH, and NSDKLIBPATH environment
|
||||
REM variables may be set to specify the location of the CRT, Universal CRT, and
|
||||
REM Windows SDK, respectively, that may be needed to compile executables native
|
||||
REM to the architecture of the build machine during any cross-compilation that
|
||||
REM may be necessary, depending on the platforms to be built. These values in
|
||||
REM these three variables should be surrounded by double quotes if they contain
|
||||
REM spaces.
|
||||
REM
|
||||
REM There are a few other environment variables that impact the build process
|
||||
REM when set ^(to anything^), they are:
|
||||
REM
|
||||
REM NOCLEAN
|
||||
REM
|
||||
REM When set, the "clean" target will not be used during each build iteration.
|
||||
REM However, the target binaries, if any, will still be deleted manually prior
|
||||
REM to being rebuilt. Setting this environment variable is only rarely needed
|
||||
REM and could cause issues in some circumstances; therefore, setting it is not
|
||||
REM recommended.
|
||||
REM
|
||||
REM NOSYMBOLS
|
||||
REM
|
||||
REM When set, copying of symbol files ^(*.pdb^) created during the build will
|
||||
REM be skipped and they will not appear in the final destination directory.
|
||||
REM Setting this environment variable is never strictly needed and could cause
|
||||
REM issues in some circumstances; therefore, setting it is not recommended.
|
||||
REM
|
||||
REM BUILD_ALL_SHELL
|
||||
REM
|
||||
REM When set, the command line shell will be built for each selected platform
|
||||
REM and configuration as well. In addition, the command line shell binaries
|
||||
REM will be copied, with their symbols, to the final destination directory.
|
||||
REM
|
||||
REM USE_WINV63_NSDKLIBPATH
|
||||
REM
|
||||
REM When set, modifies how the NSDKLIBPATH environment variable is built, based
|
||||
REM on the WindowsSdkDir environment variable. It forces this batch script to
|
||||
REM assume the Windows 8.1 SDK location should be used.
|
||||
REM
|
||||
REM USE_WINV100_NSDKLIBPATH
|
||||
REM
|
||||
REM When set, modifies how the NSDKLIBPATH environment variable is built, based
|
||||
REM on the WindowsSdkDir environment variable. It causes this batch script to
|
||||
REM assume the Windows 10.0 SDK location should be used.
|
||||
REM
|
||||
REM NMAKE_ARGS
|
||||
REM
|
||||
REM When set, the value is expanded and passed to the NMAKE command line, after
|
||||
REM its other arguments. This is used to specify additional NMAKE options, for
|
||||
REM example:
|
||||
REM
|
||||
REM SET NMAKE_ARGS=FOR_WINRT=1
|
||||
REM
|
||||
SETLOCAL
|
||||
|
||||
|
@ -217,8 +263,20 @@ SET TOOLPATH=%gawk.exe_PATH%;%tclsh85.exe_PATH%
|
|||
%_VECHO% ToolPath = '%TOOLPATH%'
|
||||
|
||||
REM
|
||||
REM NOTE: Check for MSVC 2012/2013 because the Windows SDK directory handling
|
||||
REM is slightly different for those versions.
|
||||
REM NOTE: Setting the Windows SDK library path is only required for MSVC
|
||||
REM 2012, 2013, and 2015.
|
||||
REM
|
||||
CALL :fn_UnsetVariable SET_NSDKLIBPATH
|
||||
|
||||
REM
|
||||
REM NOTE: Setting the Universal CRT library path is only required for MSVC
|
||||
REM 2015.
|
||||
REM
|
||||
CALL :fn_UnsetVariable SET_NUCRTLIBPATH
|
||||
|
||||
REM
|
||||
REM NOTE: Check for MSVC 2012, 2013, and 2015 specially because the Windows
|
||||
REM SDK directory handling is slightly different for those versions.
|
||||
REM
|
||||
IF "%VisualStudioVersion%" == "11.0" (
|
||||
REM
|
||||
|
@ -236,8 +294,22 @@ IF "%VisualStudioVersion%" == "11.0" (
|
|||
IF NOT DEFINED NSDKLIBPATH (
|
||||
SET SET_NSDKLIBPATH=1
|
||||
)
|
||||
) ELSE (
|
||||
CALL :fn_UnsetVariable SET_NSDKLIBPATH
|
||||
) ELSE IF "%VisualStudioVersion%" == "14.0" (
|
||||
REM
|
||||
REM NOTE: If the Windows SDK library path has already been set, do not set
|
||||
REM it to something else later on.
|
||||
REM
|
||||
IF NOT DEFINED NSDKLIBPATH (
|
||||
SET SET_NSDKLIBPATH=1
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: If the Universal CRT library path has already been set, do not set
|
||||
REM it to something else later on.
|
||||
REM
|
||||
IF NOT DEFINED NUCRTLIBPATH (
|
||||
SET SET_NUCRTLIBPATH=1
|
||||
)
|
||||
)
|
||||
|
||||
REM
|
||||
|
@ -294,6 +366,7 @@ FOR %%P IN (%PLATFORMS%) DO (
|
|||
CALL :fn_UnsetVariable LIB
|
||||
CALL :fn_UnsetVariable LIBPATH
|
||||
CALL :fn_UnsetVariable Platform
|
||||
CALL :fn_UnsetVariable UniversalCRTSdkDir
|
||||
REM CALL :fn_UnsetVariable VCINSTALLDIR
|
||||
CALL :fn_UnsetVariable VSINSTALLDIR
|
||||
CALL :fn_UnsetVariable WindowsPhoneKitDir
|
||||
|
@ -385,8 +458,8 @@ FOR %%P IN (%PLATFORMS%) DO (
|
|||
)
|
||||
|
||||
REM
|
||||
REM NOTE: When using MSVC 2012 and/or 2013, the native SDK path cannot
|
||||
REM simply use the "lib" sub-directory beneath the location
|
||||
REM NOTE: When using MSVC 2012, 2013, or 2015, the native SDK path
|
||||
REM cannot simply be the "lib" sub-directory beneath the location
|
||||
REM specified in the WindowsSdkDir environment variable because
|
||||
REM that location does not actually contain the necessary library
|
||||
REM files for x86. This must be done for each iteration because
|
||||
|
@ -405,19 +478,39 @@ FOR %%P IN (%PLATFORMS%) DO (
|
|||
CALL :fn_CopyVariable WindowsSdkDir NSDKLIBPATH
|
||||
|
||||
REM
|
||||
REM NOTE: The Windows 8.1 SDK has a slightly different directory
|
||||
REM naming convention.
|
||||
REM NOTE: The Windows 8.x and Windows 10.0 SDKs have a slightly
|
||||
REM different directory naming conventions.
|
||||
REM
|
||||
IF DEFINED USE_WINV63_NSDKLIBPATH (
|
||||
IF DEFINED USE_WINV100_NSDKLIBPATH (
|
||||
CALL :fn_AppendVariable NSDKLIBPATH \..\10\lib\10.0.10030.0\um\x86
|
||||
CALL :fn_CopyVariable UniversalCRTSdkDir PSDKLIBPATH
|
||||
CALL :fn_AppendVariable PSDKLIBPATH Lib\10.0.10030.0\um\%%D
|
||||
) ELSE IF DEFINED USE_WINV63_NSDKLIBPATH (
|
||||
CALL :fn_AppendVariable NSDKLIBPATH \lib\winv6.3\um\x86
|
||||
) ELSE IF "%VisualStudioVersion%" == "12.0" (
|
||||
CALL :fn_AppendVariable NSDKLIBPATH \..\8.0\lib\win8\um\x86
|
||||
) ELSE IF "%VisualStudioVersion%" == "14.0" (
|
||||
CALL :fn_AppendVariable NSDKLIBPATH \..\8.0\lib\win8\um\x86
|
||||
) ELSE (
|
||||
CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: When using MSVC 2015, setting the Universal CRT library path
|
||||
REM for x86 may be required as well. This must also be done for
|
||||
REM each iteration because it relies upon the UniversalCRTSdkDir
|
||||
REM environment variable being set by the batch file used to
|
||||
REM setup the MSVC environment.
|
||||
REM
|
||||
IF DEFINED SET_NUCRTLIBPATH (
|
||||
IF DEFINED UniversalCRTSdkDir (
|
||||
CALL :fn_CopyVariable UniversalCRTSdkDir NUCRTLIBPATH
|
||||
CALL :fn_AppendVariable NUCRTLIBPATH \lib\winv10.0\ucrt\x86
|
||||
)
|
||||
)
|
||||
|
||||
REM
|
||||
REM NOTE: Unless prevented from doing so, invoke NMAKE with the MSVC
|
||||
REM makefile to clean any stale build output from previous
|
||||
|
@ -575,6 +668,19 @@ REM NOTE: If we get to this point, we have succeeded.
|
|||
REM
|
||||
GOTO no_errors
|
||||
|
||||
:fn_ShowVariable
|
||||
SETLOCAL
|
||||
SET __ECHO_CMD=ECHO %%%2%%
|
||||
FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
|
||||
IF NOT "%%V" == "" (
|
||||
IF NOT "%%V" == "%%%2%%" (
|
||||
%_VECHO% %1 = '%%V'
|
||||
)
|
||||
)
|
||||
)
|
||||
ENDLOCAL
|
||||
GOTO :EOF
|
||||
|
||||
:fn_ResetErrorLevel
|
||||
VERIFY > NUL
|
||||
GOTO :EOF
|
||||
|
|
|
@ -0,0 +1,567 @@
|
|||
/*
|
||||
** 2015-04-17
|
||||
**
|
||||
** 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 is a utility program designed to aid running the SQLite library
|
||||
** against an external fuzzer, such as American Fuzzy Lop (AFL)
|
||||
** (http://lcamtuf.coredump.cx/afl/). Basically, this program reads
|
||||
** SQL text from standard input and passes it through to SQLite for evaluation,
|
||||
** just like the "sqlite3" command-line shell. Differences from the
|
||||
** command-line shell:
|
||||
**
|
||||
** (1) The complex "dot-command" extensions are omitted. This
|
||||
** prevents the fuzzer from discovering that it can run things
|
||||
** like ".shell rm -rf ~"
|
||||
**
|
||||
** (2) The database is opened with the SQLITE_OPEN_MEMORY flag so that
|
||||
** no disk I/O from the database is permitted. The ATTACH command
|
||||
** with a filename still uses an in-memory database.
|
||||
**
|
||||
** (3) The main in-memory database can be initialized from a template
|
||||
** disk database so that the fuzzer starts with a database containing
|
||||
** content.
|
||||
**
|
||||
** (4) The eval() SQL function is added, allowing the fuzzer to do
|
||||
** interesting recursive operations.
|
||||
**
|
||||
** 2015-04-20: The input text can be divided into separate SQL chunks using
|
||||
** lines of the form:
|
||||
**
|
||||
** |****<...>****|
|
||||
**
|
||||
** where the "..." is arbitrary text, except the "|" should really be "/".
|
||||
** ("|" is used here to avoid compiler warnings about nested comments.)
|
||||
** Each such SQL comment is printed as it is encountered. A separate
|
||||
** in-memory SQLite database is created to run each chunk of SQL. This
|
||||
** feature allows the "queue" of AFL to be captured into a single big
|
||||
** file using a command like this:
|
||||
**
|
||||
** (for i in id:*; do echo '|****<'$i'>****|'; cat $i; done) >~/all-queue.txt
|
||||
**
|
||||
** (Once again, change the "|" to "/") Then all elements of the AFL queue
|
||||
** can be run in a single go (for regression testing, for example) by typing:
|
||||
**
|
||||
** fuzzershell -f ~/all-queue.txt >out.txt
|
||||
**
|
||||
** After running each chunk of SQL, the database connection is closed. The
|
||||
** program aborts if the close fails or if there is any unfreed memory after
|
||||
** the close.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include "sqlite3.h"
|
||||
|
||||
/*
|
||||
** All global variables are gathered into the "g" singleton.
|
||||
*/
|
||||
struct GlobalVars {
|
||||
const char *zArgv0; /* Name of program */
|
||||
} g;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Print an error message and abort in such a way to indicate to the
|
||||
** fuzzer that this counts as a crash.
|
||||
*/
|
||||
static void abendError(const char *zFormat, ...){
|
||||
va_list ap;
|
||||
fprintf(stderr, "%s: ", g.zArgv0);
|
||||
va_start(ap, zFormat);
|
||||
vfprintf(stderr, zFormat, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
abort();
|
||||
}
|
||||
/*
|
||||
** Print an error message and quit, but not in a way that would look
|
||||
** like a crash.
|
||||
*/
|
||||
static void fatalError(const char *zFormat, ...){
|
||||
va_list ap;
|
||||
fprintf(stderr, "%s: ", g.zArgv0);
|
||||
va_start(ap, zFormat);
|
||||
vfprintf(stderr, zFormat, ap);
|
||||
va_end(ap);
|
||||
fprintf(stderr, "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Evaluate some SQL. Abort if unable.
|
||||
*/
|
||||
static void sqlexec(sqlite3 *db, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
char *zSql;
|
||||
char *zErrMsg = 0;
|
||||
int rc;
|
||||
va_start(ap, zFormat);
|
||||
zSql = sqlite3_vmprintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
|
||||
if( rc ) abendError("failed sql [%s]: %s", zSql, zErrMsg);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
|
||||
/*
|
||||
** This callback is invoked by sqlite3_log().
|
||||
*/
|
||||
static void shellLog(void *pNotUsed, int iErrCode, const char *zMsg){
|
||||
printf("LOG: (%d) %s\n", iErrCode, zMsg);
|
||||
}
|
||||
|
||||
/*
|
||||
** This callback is invoked by sqlite3_exec() to return query results.
|
||||
*/
|
||||
static int execCallback(void *NotUsed, int argc, char **argv, char **colv){
|
||||
int i;
|
||||
static unsigned cnt = 0;
|
||||
printf("ROW #%u:\n", ++cnt);
|
||||
for(i=0; i<argc; i++){
|
||||
printf(" %s=", colv[i]);
|
||||
if( argv[i] ){
|
||||
printf("[%s]\n", argv[i]);
|
||||
}else{
|
||||
printf("NULL\n");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This callback is invoked by sqlite3_trace() as each SQL statement
|
||||
** starts.
|
||||
*/
|
||||
static void traceCallback(void *NotUsed, const char *zMsg){
|
||||
printf("TRACE: %s\n", zMsg);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
** eval() implementation copied from ../ext/misc/eval.c
|
||||
*/
|
||||
/*
|
||||
** Structure used to accumulate the output
|
||||
*/
|
||||
struct EvalResult {
|
||||
char *z; /* Accumulated output */
|
||||
const char *zSep; /* Separator */
|
||||
int szSep; /* Size of the separator string */
|
||||
sqlite3_int64 nAlloc; /* Number of bytes allocated for z[] */
|
||||
sqlite3_int64 nUsed; /* Number of bytes of z[] actually used */
|
||||
};
|
||||
|
||||
/*
|
||||
** Callback from sqlite_exec() for the eval() function.
|
||||
*/
|
||||
static int callback(void *pCtx, int argc, char **argv, char **colnames){
|
||||
struct EvalResult *p = (struct EvalResult*)pCtx;
|
||||
int i;
|
||||
for(i=0; i<argc; i++){
|
||||
const char *z = argv[i] ? argv[i] : "";
|
||||
size_t sz = strlen(z);
|
||||
if( (sqlite3_int64)sz+p->nUsed+p->szSep+1 > p->nAlloc ){
|
||||
char *zNew;
|
||||
p->nAlloc = p->nAlloc*2 + sz + p->szSep + 1;
|
||||
/* Using sqlite3_realloc64() would be better, but it is a recent
|
||||
** addition and will cause a segfault if loaded by an older version
|
||||
** of SQLite. */
|
||||
zNew = p->nAlloc<=0x7fffffff ? sqlite3_realloc(p->z, (int)p->nAlloc) : 0;
|
||||
if( zNew==0 ){
|
||||
sqlite3_free(p->z);
|
||||
memset(p, 0, sizeof(*p));
|
||||
return 1;
|
||||
}
|
||||
p->z = zNew;
|
||||
}
|
||||
if( p->nUsed>0 ){
|
||||
memcpy(&p->z[p->nUsed], p->zSep, p->szSep);
|
||||
p->nUsed += p->szSep;
|
||||
}
|
||||
memcpy(&p->z[p->nUsed], z, sz);
|
||||
p->nUsed += sz;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the eval(X) and eval(X,Y) SQL functions.
|
||||
**
|
||||
** Evaluate the SQL text in X. Return the results, using string
|
||||
** Y as the separator. If Y is omitted, use a single space character.
|
||||
*/
|
||||
static void sqlEvalFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const char *zSql;
|
||||
sqlite3 *db;
|
||||
char *zErr = 0;
|
||||
int rc;
|
||||
struct EvalResult x;
|
||||
|
||||
memset(&x, 0, sizeof(x));
|
||||
x.zSep = " ";
|
||||
zSql = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zSql==0 ) return;
|
||||
if( argc>1 ){
|
||||
x.zSep = (const char*)sqlite3_value_text(argv[1]);
|
||||
if( x.zSep==0 ) return;
|
||||
}
|
||||
x.szSep = (int)strlen(x.zSep);
|
||||
db = sqlite3_context_db_handle(context);
|
||||
rc = sqlite3_exec(db, zSql, callback, &x, &zErr);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
}else if( x.zSep==0 ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
sqlite3_free(x.z);
|
||||
}else{
|
||||
sqlite3_result_text(context, x.z, (int)x.nUsed, sqlite3_free);
|
||||
}
|
||||
}
|
||||
/* End of the eval() implementation
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
** Print sketchy documentation for this utility program
|
||||
*/
|
||||
static void showHelp(void){
|
||||
printf("Usage: %s [options]\n", g.zArgv0);
|
||||
printf(
|
||||
"Read SQL text from standard input and evaluate it.\n"
|
||||
"Options:\n"
|
||||
" --autovacuum Enable AUTOVACUUM mode\n"
|
||||
" -f FILE Read SQL text from FILE instead of standard input\n"
|
||||
" --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n"
|
||||
" --help Show this help text\n"
|
||||
" --initdb DBFILE Initialize the in-memory database using template DBFILE\n"
|
||||
" --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n"
|
||||
" --pagesize N Set the page size to N\n"
|
||||
" --pcache N SZ Configure N pages of pagecache each of size SZ bytes\n"
|
||||
" --scratch N SZ Configure scratch memory for N slots of SZ bytes each\n"
|
||||
" --utf16be Set text encoding to UTF-16BE\n"
|
||||
" --utf16le Set text encoding to UTF-16LE\n"
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the value of a hexadecimal digit. Return -1 if the input
|
||||
** is not a hex digit.
|
||||
*/
|
||||
static int hexDigitValue(char c){
|
||||
if( c>='0' && c<='9' ) return c - '0';
|
||||
if( c>='a' && c<='f' ) return c - 'a' + 10;
|
||||
if( c>='A' && c<='F' ) return c - 'A' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Interpret zArg as an integer value, possibly with suffixes.
|
||||
*/
|
||||
static int integerValue(const char *zArg){
|
||||
sqlite3_int64 v = 0;
|
||||
static const struct { char *zSuffix; int iMult; } aMult[] = {
|
||||
{ "KiB", 1024 },
|
||||
{ "MiB", 1024*1024 },
|
||||
{ "GiB", 1024*1024*1024 },
|
||||
{ "KB", 1000 },
|
||||
{ "MB", 1000000 },
|
||||
{ "GB", 1000000000 },
|
||||
{ "K", 1000 },
|
||||
{ "M", 1000000 },
|
||||
{ "G", 1000000000 },
|
||||
};
|
||||
int i;
|
||||
int isNeg = 0;
|
||||
if( zArg[0]=='-' ){
|
||||
isNeg = 1;
|
||||
zArg++;
|
||||
}else if( zArg[0]=='+' ){
|
||||
zArg++;
|
||||
}
|
||||
if( zArg[0]=='0' && zArg[1]=='x' ){
|
||||
int x;
|
||||
zArg += 2;
|
||||
while( (x = hexDigitValue(zArg[0]))>=0 ){
|
||||
v = (v<<4) + x;
|
||||
zArg++;
|
||||
}
|
||||
}else{
|
||||
while( isdigit(zArg[0]) ){
|
||||
v = v*10 + zArg[0] - '0';
|
||||
zArg++;
|
||||
}
|
||||
}
|
||||
for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){
|
||||
if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){
|
||||
v *= aMult[i].iMult;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( v>0x7fffffff ) abendError("parameter too large - max 2147483648");
|
||||
return (int)(isNeg? -v : v);
|
||||
}
|
||||
|
||||
/*
|
||||
** Various operating modes
|
||||
*/
|
||||
#define FZMODE_Generic 1
|
||||
#define FZMODE_Strftime 2
|
||||
#define FZMODE_Printf 3
|
||||
#define FZMODE_Glob 4
|
||||
|
||||
|
||||
int main(int argc, char **argv){
|
||||
char *zIn = 0; /* Input text */
|
||||
int nAlloc = 0; /* Number of bytes allocated for zIn[] */
|
||||
int nIn = 0; /* Number of bytes of zIn[] used */
|
||||
size_t got; /* Bytes read from input */
|
||||
FILE *in = stdin; /* Where to read SQL text from */
|
||||
int rc = SQLITE_OK; /* Result codes from API functions */
|
||||
int i; /* Loop counter */
|
||||
int iNext; /* Next block of SQL */
|
||||
sqlite3 *db; /* Open database */
|
||||
sqlite3 *dbInit = 0; /* On-disk database used to initialize the in-memory db */
|
||||
const char *zInitDb = 0;/* Name of the initialization database file */
|
||||
char *zErrMsg = 0; /* Error message returned from sqlite3_exec() */
|
||||
const char *zEncoding = 0; /* --utf16be or --utf16le */
|
||||
int nHeap = 0, mnHeap = 0; /* Heap size from --heap */
|
||||
int nLook = 0, szLook = 0; /* --lookaside configuration */
|
||||
int nPCache = 0, szPCache = 0;/* --pcache configuration */
|
||||
int nScratch = 0, szScratch=0;/* --scratch configuration */
|
||||
int pageSize = 0; /* Desired page size. 0 means default */
|
||||
void *pHeap = 0; /* Allocated heap space */
|
||||
void *pLook = 0; /* Allocated lookaside space */
|
||||
void *pPCache = 0; /* Allocated storage for pcache */
|
||||
void *pScratch = 0; /* Allocated storage for scratch */
|
||||
int doAutovac = 0; /* True for --autovacuum */
|
||||
char *zSql; /* SQL to run */
|
||||
char *zToFree = 0; /* Call sqlite3_free() on this afte running zSql */
|
||||
int iMode = FZMODE_Generic; /* Operating mode */
|
||||
const char *zCkGlob = 0; /* Inputs must match this glob */
|
||||
|
||||
|
||||
g.zArgv0 = argv[0];
|
||||
for(i=1; i<argc; i++){
|
||||
const char *z = argv[i];
|
||||
if( z[0]=='-' ){
|
||||
z++;
|
||||
if( z[0]=='-' ) z++;
|
||||
if( strcmp(z,"autovacuum")==0 ){
|
||||
doAutovac = 1;
|
||||
}else
|
||||
if( strcmp(z, "f")==0 && i+1<argc ){
|
||||
if( in!=stdin ) abendError("only one -f allowed");
|
||||
in = fopen(argv[++i],"rb");
|
||||
if( in==0 ) abendError("cannot open input file \"%s\"", argv[i]);
|
||||
}else
|
||||
if( strcmp(z,"heap")==0 ){
|
||||
if( i>=argc-2 ) abendError("missing arguments on %s\n", argv[i]);
|
||||
nHeap = integerValue(argv[i+1]);
|
||||
mnHeap = integerValue(argv[i+2]);
|
||||
i += 2;
|
||||
}else
|
||||
if( strcmp(z,"help")==0 ){
|
||||
showHelp();
|
||||
return 0;
|
||||
}else
|
||||
if( strcmp(z, "initdb")==0 && i+1<argc ){
|
||||
if( zInitDb!=0 ) abendError("only one --initdb allowed");
|
||||
zInitDb = argv[++i];
|
||||
}else
|
||||
if( strcmp(z,"lookaside")==0 ){
|
||||
if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
|
||||
nLook = integerValue(argv[i+1]);
|
||||
szLook = integerValue(argv[i+2]);
|
||||
i += 2;
|
||||
}else
|
||||
if( strcmp(z,"mode")==0 ){
|
||||
if( i>=argc-1 ) abendError("missing argument on %s", argv[i]);
|
||||
z = argv[++i];
|
||||
if( strcmp(z,"generic")==0 ){
|
||||
iMode = FZMODE_Printf;
|
||||
zCkGlob = 0;
|
||||
}else if( strcmp(z, "glob")==0 ){
|
||||
iMode = FZMODE_Glob;
|
||||
zCkGlob = "'*','*'";
|
||||
}else if( strcmp(z, "printf")==0 ){
|
||||
iMode = FZMODE_Printf;
|
||||
zCkGlob = "'*',*";
|
||||
}else if( strcmp(z, "strftime")==0 ){
|
||||
iMode = FZMODE_Strftime;
|
||||
zCkGlob = "'*',*";
|
||||
}else{
|
||||
abendError("unknown --mode: %s", z);
|
||||
}
|
||||
}else
|
||||
if( strcmp(z,"pagesize")==0 ){
|
||||
if( i>=argc-1 ) abendError("missing argument on %s", argv[i]);
|
||||
pageSize = integerValue(argv[++i]);
|
||||
}else
|
||||
if( strcmp(z,"pcache")==0 ){
|
||||
if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
|
||||
nPCache = integerValue(argv[i+1]);
|
||||
szPCache = integerValue(argv[i+2]);
|
||||
i += 2;
|
||||
}else
|
||||
if( strcmp(z,"scratch")==0 ){
|
||||
if( i>=argc-2 ) abendError("missing arguments on %s", argv[i]);
|
||||
nScratch = integerValue(argv[i+1]);
|
||||
szScratch = integerValue(argv[i+2]);
|
||||
i += 2;
|
||||
}else
|
||||
if( strcmp(z,"utf16le")==0 ){
|
||||
zEncoding = "utf16le";
|
||||
}else
|
||||
if( strcmp(z,"utf16be")==0 ){
|
||||
zEncoding = "utf16be";
|
||||
}else
|
||||
{
|
||||
abendError("unknown option: %s", argv[i]);
|
||||
}
|
||||
}else{
|
||||
abendError("unknown argument: %s", argv[i]);
|
||||
}
|
||||
}
|
||||
sqlite3_config(SQLITE_CONFIG_LOG, shellLog, 0);
|
||||
if( nHeap>0 ){
|
||||
pHeap = malloc( nHeap );
|
||||
if( pHeap==0 ) fatalError("cannot allocate %d-byte heap\n", nHeap);
|
||||
rc = sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nHeap, mnHeap);
|
||||
if( rc ) abendError("heap configuration failed: %d\n", rc);
|
||||
}
|
||||
if( nLook>0 ){
|
||||
sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
|
||||
if( szLook>0 ){
|
||||
pLook = malloc( nLook*szLook );
|
||||
if( pLook==0 ) fatalError("out of memory");
|
||||
}
|
||||
}
|
||||
if( nScratch>0 && szScratch>0 ){
|
||||
pScratch = malloc( nScratch*(sqlite3_int64)szScratch );
|
||||
if( pScratch==0 ) fatalError("cannot allocate %lld-byte scratch",
|
||||
nScratch*(sqlite3_int64)szScratch);
|
||||
rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, pScratch, szScratch, nScratch);
|
||||
if( rc ) abendError("scratch configuration failed: %d\n", rc);
|
||||
}
|
||||
if( nPCache>0 && szPCache>0 ){
|
||||
pPCache = malloc( nPCache*(sqlite3_int64)szPCache );
|
||||
if( pPCache==0 ) fatalError("cannot allocate %lld-byte pcache",
|
||||
nPCache*(sqlite3_int64)szPCache);
|
||||
rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, pPCache, szPCache, nPCache);
|
||||
if( rc ) abendError("pcache configuration failed: %d", rc);
|
||||
}
|
||||
while( !feof(in) ){
|
||||
nAlloc += nAlloc+1000;
|
||||
zIn = realloc(zIn, nAlloc);
|
||||
if( zIn==0 ) fatalError("out of memory");
|
||||
got = fread(zIn+nIn, 1, nAlloc-nIn-1, in);
|
||||
nIn += (int)got;
|
||||
zIn[nIn] = 0;
|
||||
if( got==0 ) break;
|
||||
}
|
||||
if( zInitDb ){
|
||||
rc = sqlite3_open_v2(zInitDb, &dbInit, SQLITE_OPEN_READONLY, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
abendError("unable to open initialization database \"%s\"", zInitDb);
|
||||
}
|
||||
}
|
||||
for(i=0; i<nIn; i=iNext){
|
||||
char cSaved;
|
||||
if( strncmp(&zIn[i], "/****<",6)==0 ){
|
||||
char *z = strstr(&zIn[i], ">****/");
|
||||
if( z ){
|
||||
z += 6;
|
||||
printf("%.*s\n", (int)(z-&zIn[i]), &zIn[i]);
|
||||
i += (int)(z-&zIn[i]);
|
||||
}
|
||||
}
|
||||
for(iNext=i; iNext<nIn && strncmp(&zIn[iNext],"/****<",6)!=0; iNext++){}
|
||||
cSaved = zIn[iNext];
|
||||
zIn[iNext] = 0;
|
||||
if( zCkGlob && sqlite3_strglob(zCkGlob,&zIn[i])!=0 ){
|
||||
zIn[iNext] = cSaved;
|
||||
continue;
|
||||
}
|
||||
rc = sqlite3_open_v2(
|
||||
"main.db", &db,
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MEMORY,
|
||||
0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
abendError("Unable to open the in-memory database");
|
||||
}
|
||||
if( pLook ){
|
||||
rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, pLook, szLook, nLook);
|
||||
if( rc!=SQLITE_OK ) abendError("lookaside configuration filed: %d", rc);
|
||||
}
|
||||
if( zInitDb ){
|
||||
sqlite3_backup *pBackup;
|
||||
pBackup = sqlite3_backup_init(db, "main", dbInit, "main");
|
||||
rc = sqlite3_backup_step(pBackup, -1);
|
||||
if( rc!=SQLITE_DONE ){
|
||||
abendError("attempt to initialize the in-memory database failed (rc=%d)",
|
||||
rc);
|
||||
}
|
||||
sqlite3_backup_finish(pBackup);
|
||||
}
|
||||
sqlite3_trace(db, traceCallback, 0);
|
||||
sqlite3_create_function(db, "eval", 1, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
|
||||
sqlite3_create_function(db, "eval", 2, SQLITE_UTF8, 0, sqlEvalFunc, 0, 0);
|
||||
sqlite3_limit(db, SQLITE_LIMIT_LENGTH, 1000000);
|
||||
if( zEncoding ) sqlexec(db, "PRAGMA encoding=%s", zEncoding);
|
||||
if( pageSize ) sqlexec(db, "PRAGMA pagesize=%d", pageSize);
|
||||
if( doAutovac ) sqlexec(db, "PRAGMA auto_vacuum=FULL");
|
||||
printf("INPUT (offset: %d, size: %d): [%s]\n",
|
||||
i, (int)strlen(&zIn[i]), &zIn[i]);
|
||||
zSql = &zIn[i];
|
||||
switch( iMode ){
|
||||
case FZMODE_Glob:
|
||||
zSql = zToFree = sqlite3_mprintf("SELECT glob(%s);", zSql);
|
||||
break;
|
||||
case FZMODE_Printf:
|
||||
zSql = zToFree = sqlite3_mprintf("SELECT printf(%s);", zSql);
|
||||
break;
|
||||
case FZMODE_Strftime:
|
||||
zSql = zToFree = sqlite3_mprintf("SELECT strftime(%s);", zSql);
|
||||
break;
|
||||
}
|
||||
rc = sqlite3_exec(db, zSql, execCallback, 0, &zErrMsg);
|
||||
if( zToFree ){
|
||||
sqlite3_free(zToFree);
|
||||
zToFree = 0;
|
||||
}
|
||||
zIn[iNext] = cSaved;
|
||||
|
||||
printf("RESULT-CODE: %d\n", rc);
|
||||
if( zErrMsg ){
|
||||
printf("ERROR-MSG: [%s]\n", zErrMsg);
|
||||
sqlite3_free(zErrMsg);
|
||||
}
|
||||
rc = sqlite3_close(db);
|
||||
if( rc ){
|
||||
abendError("sqlite3_close() failed with rc=%d", rc);
|
||||
}
|
||||
if( sqlite3_memory_used()>0 ){
|
||||
abendError("memory in use after close: %lld bytes", sqlite3_memory_used());
|
||||
}
|
||||
}
|
||||
free(zIn);
|
||||
free(pHeap);
|
||||
free(pLook);
|
||||
free(pScratch);
|
||||
free(pPCache);
|
||||
return 0;
|
||||
}
|
72
tool/lemon.c
72
tool/lemon.c
|
@ -1114,7 +1114,6 @@ void FindActions(struct lemon *lemp)
|
|||
/* Resolve conflicts */
|
||||
for(i=0; i<lemp->nstate; i++){
|
||||
struct action *ap, *nap;
|
||||
struct state *stp;
|
||||
stp = lemp->sorted[i];
|
||||
/* assert( stp->ap ); */
|
||||
stp->ap = Action_sort(stp->ap);
|
||||
|
@ -3748,9 +3747,9 @@ void ReportTable(
|
|||
/* Generate the include code, if any */
|
||||
tplt_print(out,lemp,lemp->include,&lineno);
|
||||
if( mhflag ){
|
||||
char *name = file_makename(lemp, ".h");
|
||||
fprintf(out,"#include \"%s\"\n", name); lineno++;
|
||||
free(name);
|
||||
char *incName = file_makename(lemp, ".h");
|
||||
fprintf(out,"#include \"%s\"\n", incName); lineno++;
|
||||
free(incName);
|
||||
}
|
||||
tplt_xfer(lemp->name,in,out,&lineno);
|
||||
|
||||
|
@ -3791,7 +3790,6 @@ void ReportTable(
|
|||
}
|
||||
name = lemp->name ? lemp->name : "Parse";
|
||||
if( lemp->arg && lemp->arg[0] ){
|
||||
int i;
|
||||
i = lemonStrlen(lemp->arg);
|
||||
while( i>=1 && isspace(lemp->arg[i-1]) ) i--;
|
||||
while( i>=1 && (isalnum(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--;
|
||||
|
@ -4479,18 +4477,18 @@ int Strsafe_insert(const char *data)
|
|||
}
|
||||
if( x1a->count>=x1a->size ){
|
||||
/* Need to make the hash table bigger */
|
||||
int i,size;
|
||||
int i,arrSize;
|
||||
struct s_x1 array;
|
||||
array.size = size = x1a->size*2;
|
||||
array.size = arrSize = x1a->size*2;
|
||||
array.count = x1a->count;
|
||||
array.tbl = (x1node*)calloc(size, sizeof(x1node) + sizeof(x1node*));
|
||||
array.tbl = (x1node*)calloc(arrSize, sizeof(x1node) + sizeof(x1node*));
|
||||
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
||||
array.ht = (x1node**)&(array.tbl[size]);
|
||||
for(i=0; i<size; i++) array.ht[i] = 0;
|
||||
array.ht = (x1node**)&(array.tbl[arrSize]);
|
||||
for(i=0; i<arrSize; i++) array.ht[i] = 0;
|
||||
for(i=0; i<x1a->count; i++){
|
||||
x1node *oldnp, *newnp;
|
||||
oldnp = &(x1a->tbl[i]);
|
||||
h = strhash(oldnp->data) & (size-1);
|
||||
h = strhash(oldnp->data) & (arrSize-1);
|
||||
newnp = &(array.tbl[i]);
|
||||
if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
|
||||
newnp->next = array.ht[h];
|
||||
|
@ -4646,18 +4644,18 @@ int Symbol_insert(struct symbol *data, const char *key)
|
|||
}
|
||||
if( x2a->count>=x2a->size ){
|
||||
/* Need to make the hash table bigger */
|
||||
int i,size;
|
||||
int i,arrSize;
|
||||
struct s_x2 array;
|
||||
array.size = size = x2a->size*2;
|
||||
array.size = arrSize = x2a->size*2;
|
||||
array.count = x2a->count;
|
||||
array.tbl = (x2node*)calloc(size, sizeof(x2node) + sizeof(x2node*));
|
||||
array.tbl = (x2node*)calloc(arrSize, sizeof(x2node) + sizeof(x2node*));
|
||||
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
||||
array.ht = (x2node**)&(array.tbl[size]);
|
||||
for(i=0; i<size; i++) array.ht[i] = 0;
|
||||
array.ht = (x2node**)&(array.tbl[arrSize]);
|
||||
for(i=0; i<arrSize; i++) array.ht[i] = 0;
|
||||
for(i=0; i<x2a->count; i++){
|
||||
x2node *oldnp, *newnp;
|
||||
oldnp = &(x2a->tbl[i]);
|
||||
h = strhash(oldnp->key) & (size-1);
|
||||
h = strhash(oldnp->key) & (arrSize-1);
|
||||
newnp = &(array.tbl[i]);
|
||||
if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
|
||||
newnp->next = array.ht[h];
|
||||
|
@ -4722,12 +4720,12 @@ int Symbol_count()
|
|||
struct symbol **Symbol_arrayof()
|
||||
{
|
||||
struct symbol **array;
|
||||
int i,size;
|
||||
int i,arrSize;
|
||||
if( x2a==0 ) return 0;
|
||||
size = x2a->count;
|
||||
array = (struct symbol **)calloc(size, sizeof(struct symbol *));
|
||||
arrSize = x2a->count;
|
||||
array = (struct symbol **)calloc(arrSize, sizeof(struct symbol *));
|
||||
if( array ){
|
||||
for(i=0; i<size; i++) array[i] = x2a->tbl[i].data;
|
||||
for(i=0; i<arrSize; i++) array[i] = x2a->tbl[i].data;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
@ -4843,18 +4841,18 @@ int State_insert(struct state *data, struct config *key)
|
|||
}
|
||||
if( x3a->count>=x3a->size ){
|
||||
/* Need to make the hash table bigger */
|
||||
int i,size;
|
||||
int i,arrSize;
|
||||
struct s_x3 array;
|
||||
array.size = size = x3a->size*2;
|
||||
array.size = arrSize = x3a->size*2;
|
||||
array.count = x3a->count;
|
||||
array.tbl = (x3node*)calloc(size, sizeof(x3node) + sizeof(x3node*));
|
||||
array.tbl = (x3node*)calloc(arrSize, sizeof(x3node) + sizeof(x3node*));
|
||||
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
||||
array.ht = (x3node**)&(array.tbl[size]);
|
||||
for(i=0; i<size; i++) array.ht[i] = 0;
|
||||
array.ht = (x3node**)&(array.tbl[arrSize]);
|
||||
for(i=0; i<arrSize; i++) array.ht[i] = 0;
|
||||
for(i=0; i<x3a->count; i++){
|
||||
x3node *oldnp, *newnp;
|
||||
oldnp = &(x3a->tbl[i]);
|
||||
h = statehash(oldnp->key) & (size-1);
|
||||
h = statehash(oldnp->key) & (arrSize-1);
|
||||
newnp = &(array.tbl[i]);
|
||||
if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
|
||||
newnp->next = array.ht[h];
|
||||
|
@ -4901,12 +4899,12 @@ struct state *State_find(struct config *key)
|
|||
struct state **State_arrayof()
|
||||
{
|
||||
struct state **array;
|
||||
int i,size;
|
||||
int i,arrSize;
|
||||
if( x3a==0 ) return 0;
|
||||
size = x3a->count;
|
||||
array = (struct state **)calloc(size, sizeof(struct state *));
|
||||
arrSize = x3a->count;
|
||||
array = (struct state **)calloc(arrSize, sizeof(struct state *));
|
||||
if( array ){
|
||||
for(i=0; i<size; i++) array[i] = x3a->tbl[i].data;
|
||||
for(i=0; i<arrSize; i++) array[i] = x3a->tbl[i].data;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
@ -4983,18 +4981,18 @@ int Configtable_insert(struct config *data)
|
|||
}
|
||||
if( x4a->count>=x4a->size ){
|
||||
/* Need to make the hash table bigger */
|
||||
int i,size;
|
||||
int i,arrSize;
|
||||
struct s_x4 array;
|
||||
array.size = size = x4a->size*2;
|
||||
array.size = arrSize = x4a->size*2;
|
||||
array.count = x4a->count;
|
||||
array.tbl = (x4node*)calloc(size, sizeof(x4node) + sizeof(x4node*));
|
||||
array.tbl = (x4node*)calloc(arrSize, sizeof(x4node) + sizeof(x4node*));
|
||||
if( array.tbl==0 ) return 0; /* Fail due to malloc failure */
|
||||
array.ht = (x4node**)&(array.tbl[size]);
|
||||
for(i=0; i<size; i++) array.ht[i] = 0;
|
||||
array.ht = (x4node**)&(array.tbl[arrSize]);
|
||||
for(i=0; i<arrSize; i++) array.ht[i] = 0;
|
||||
for(i=0; i<x4a->count; i++){
|
||||
x4node *oldnp, *newnp;
|
||||
oldnp = &(x4a->tbl[i]);
|
||||
h = confighash(oldnp->data) & (size-1);
|
||||
h = confighash(oldnp->data) & (arrSize-1);
|
||||
newnp = &(array.tbl[i]);
|
||||
if( array.ht[h] ) array.ht[h]->from = &(newnp->next);
|
||||
newnp->next = array.ht[h];
|
||||
|
|
|
@ -174,6 +174,9 @@ proc writeFile { fileName data } {
|
|||
return ""
|
||||
}
|
||||
|
||||
#
|
||||
# TODO: Modify this procedure when a new version of Visual Studio is released.
|
||||
#
|
||||
proc getMinVsVersionXmlChunk { vsVersion } {
|
||||
switch -exact $vsVersion {
|
||||
2012 {
|
||||
|
@ -184,17 +187,26 @@ proc getMinVsVersionXmlChunk { vsVersion } {
|
|||
return [appendArgs \
|
||||
"\r\n " {MinVSVersion="12.0"}]
|
||||
}
|
||||
2015 {
|
||||
return [appendArgs \
|
||||
"\r\n " {MinVSVersion="14.0"}]
|
||||
}
|
||||
default {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# TODO: Modify this procedure when a new version of Visual Studio is released.
|
||||
#
|
||||
proc getMaxPlatformVersionXmlChunk { packageFlavor vsVersion } {
|
||||
#
|
||||
# NOTE: Only Visual Studio 2013 supports this SDK manifest attribute.
|
||||
# NOTE: Only Visual Studio 2013 and later support this attribute within the
|
||||
# SDK manifest.
|
||||
#
|
||||
if {![string equal $vsVersion 2013]} then {
|
||||
if {![string equal $vsVersion 2013] && \
|
||||
![string equal $vsVersion 2015]} then {
|
||||
return ""
|
||||
}
|
||||
|
||||
|
@ -221,6 +233,9 @@ proc getMaxPlatformVersionXmlChunk { packageFlavor vsVersion } {
|
|||
}
|
||||
}
|
||||
|
||||
#
|
||||
# TODO: Modify this procedure when a new version of Visual Studio is released.
|
||||
#
|
||||
proc getExtraFileListXmlChunk { packageFlavor vsVersion } {
|
||||
#
|
||||
# NOTE: Windows Phone 8.0 does not require any extra attributes in its VSIX
|
||||
|
@ -245,6 +260,14 @@ proc getExtraFileListXmlChunk { packageFlavor vsVersion } {
|
|||
"\r\n " AppliesTo=\" $appliesTo \" \
|
||||
"\r\n " {DependsOn="Microsoft.VCLibs, version=12.0"}]
|
||||
}
|
||||
2015 {
|
||||
#
|
||||
# TODO: Is the ".AppLocal" suffix always needed here?
|
||||
#
|
||||
return [appendArgs \
|
||||
"\r\n " AppliesTo=\" $appliesTo \" \
|
||||
"\r\n " {DependsOn="Microsoft.VCLibs.AppLocal, version=14.0"}]
|
||||
}
|
||||
default {
|
||||
return ""
|
||||
}
|
||||
|
@ -354,10 +377,11 @@ if {[string length $vsVersion] == 0} then {
|
|||
fail "invalid Visual Studio version"
|
||||
}
|
||||
|
||||
if {![string equal $vsVersion 2012] && ![string equal $vsVersion 2013]} then {
|
||||
if {![string equal $vsVersion 2012] && ![string equal $vsVersion 2013] && \
|
||||
![string equal $vsVersion 2015]} then {
|
||||
fail [appendArgs \
|
||||
"unsupported Visual Studio version, must be one of: " \
|
||||
[list 2012 2013]]
|
||||
[list 2012 2013 2015]]
|
||||
}
|
||||
|
||||
set shortNames(WinRT,2012) SQLite.WinRT
|
||||
|
@ -368,6 +392,7 @@ set shortNames(WP80,2013) SQLite.WP80.2013
|
|||
set shortNames(WP81,2013) SQLite.WP81
|
||||
set shortNames(Win32,2012) SQLite.Win32
|
||||
set shortNames(Win32,2013) SQLite.Win32.2013
|
||||
set shortNames(UAP,2015) SQLite.UAP.2015
|
||||
|
||||
set displayNames(WinRT,2012) "SQLite for Windows Runtime"
|
||||
set displayNames(WinRT,2013) "SQLite for Windows Runtime"
|
||||
|
@ -377,6 +402,7 @@ set displayNames(WP80,2013) "SQLite for Windows Phone"
|
|||
set displayNames(WP81,2013) "SQLite for Windows Phone 8.1"
|
||||
set displayNames(Win32,2012) "SQLite for Windows"
|
||||
set displayNames(Win32,2013) "SQLite for Windows"
|
||||
set displayNames(UAP,2015) "SQLite for Universal App Platform"
|
||||
|
||||
if {[string equal $packageFlavor WinRT]} then {
|
||||
set shortName $shortNames($packageFlavor,$vsVersion)
|
||||
|
@ -432,6 +458,22 @@ if {[string equal $packageFlavor WinRT]} then {
|
|||
set extraSdkPath "\\..\\$targetPlatformIdentifier"
|
||||
set extraFileListAttributes \
|
||||
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
|
||||
} elseif {[string equal $packageFlavor UAP]} then {
|
||||
if {$vsVersion ne "2015"} then {
|
||||
fail [appendArgs \
|
||||
"unsupported combination, package flavor " $packageFlavor \
|
||||
" is only supported with Visual Studio 2015"]
|
||||
}
|
||||
set shortName $shortNames($packageFlavor,$vsVersion)
|
||||
set displayName $displayNames($packageFlavor,$vsVersion)
|
||||
set targetPlatformIdentifier UAP
|
||||
set targetPlatformVersion v0.8.0.0
|
||||
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
|
||||
set maxPlatformVersion \
|
||||
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
|
||||
set extraSdkPath "\\..\\$targetPlatformIdentifier"
|
||||
set extraFileListAttributes \
|
||||
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
|
||||
} elseif {[string equal $packageFlavor Win32]} then {
|
||||
set shortName $shortNames($packageFlavor,$vsVersion)
|
||||
set displayName $displayNames($packageFlavor,$vsVersion)
|
||||
|
@ -446,7 +488,7 @@ if {[string equal $packageFlavor WinRT]} then {
|
|||
} else {
|
||||
fail [appendArgs \
|
||||
"unsupported package flavor, must be one of: " \
|
||||
[list WinRT WinRT81 WP80 WP81 Win32]]
|
||||
[list WinRT WinRT81 WP80 WP81 UAP Win32]]
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
|
|
|
@ -64,11 +64,13 @@ static void out_of_memory(void){
|
|||
*/
|
||||
static unsigned char *getContent(int ofst, int nByte){
|
||||
unsigned char *aData;
|
||||
int got;
|
||||
aData = malloc(nByte+32);
|
||||
if( aData==0 ) out_of_memory();
|
||||
memset(aData, 0, nByte+32);
|
||||
lseek(db, ofst, SEEK_SET);
|
||||
if( read(db, aData, nByte)<nByte ) memset(aData, 0, nByte);
|
||||
got = read(db, aData, nByte);
|
||||
if( got>0 && got<nByte ) memset(aData+got, 0, nByte-got);
|
||||
return aData;
|
||||
}
|
||||
|
||||
|
@ -981,7 +983,7 @@ int main(int argc, char **argv){
|
|||
if( pagesize==0 ) pagesize = 1024;
|
||||
printf("Pagesize: %d\n", pagesize);
|
||||
fstat(db, &sbuf);
|
||||
mxPage = sbuf.st_size/pagesize;
|
||||
mxPage = (sbuf.st_size+pagesize-1)/pagesize;
|
||||
printf("Available pages: 1..%d\n", mxPage);
|
||||
if( argc==2 ){
|
||||
int i;
|
||||
|
|
|
@ -10,8 +10,13 @@
|
|||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This is a utility problem that computes the differences in content
|
||||
** This is a utility program that computes the differences in content
|
||||
** between two SQLite databases.
|
||||
**
|
||||
** To compile, simply link against SQLite.
|
||||
**
|
||||
** See the showHelp() routine below for a brief description of how to
|
||||
** run the utility.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
Loading…
Reference in New Issue