Index: Makefile.msc ================================================================== --- Makefile.msc +++ Makefile.msc @@ -74,11 +74,11 @@ # cross-compiling, it is suggested that this macro be modified via the command # line (since nmake itself does not provide a built-in method to guess it). # For example, to use the x86 compiler when cross-compiling for x64, a command # line similar to the following could be used (all on one line): # -# nmake /f Makefile.msc +# nmake /f Makefile.msc sqlite3.dll # "NCC=""%VCINSTALLDIR%\bin\cl.exe""" # USE_NATIVE_LIBPATHS=1 # !IFDEF NCC NCC = $(NCC:\\=\) Index: ext/fts3/fts3.c ================================================================== --- ext/fts3/fts3.c +++ ext/fts3/fts3.c @@ -4434,10 +4434,11 @@ /* Allocate a MultiSegReader for each token in the expression. */ fts3EvalAllocateReaders(pCsr, pCsr->pExpr, &nToken, &nOr, &rc); /* Determine which, if any, tokens in the expression should be deferred. */ +#ifndef SQLITE_DISABLE_FTS4_DEFERRED if( rc==SQLITE_OK && nToken>1 && pTab->bFts4 ){ Fts3TokenAndCost *aTC; Fts3Expr **apOr; aTC = (Fts3TokenAndCost *)sqlite3_malloc( sizeof(Fts3TokenAndCost) * nToken @@ -4464,10 +4465,11 @@ } sqlite3_free(aTC); } } +#endif fts3EvalStartReaders(pCsr, pCsr->pExpr, 1, &rc); return rc; } @@ -4847,10 +4849,11 @@ && !fts3EvalTestExpr(pCsr, pExpr->pRight, pRc) ); break; default: { +#ifndef SQLITE_DISABLE_FTS4_DEFERRED if( pCsr->pDeferred && (pExpr->iDocid==pCsr->iPrevId || pExpr->bDeferred) ){ Fts3Phrase *pPhrase = pExpr->pPhrase; assert( pExpr->bDeferred || pPhrase->doclist.bFreeList==0 ); @@ -4858,11 +4861,13 @@ fts3EvalInvalidatePoslist(pPhrase); } *pRc = fts3EvalDeferredPhrase(pCsr, pPhrase); bHit = (pPhrase->doclist.pList!=0); pExpr->iDocid = pCsr->iPrevId; - }else{ + }else +#endif + { bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId); } break; } } Index: ext/fts3/fts3Int.h ================================================================== --- ext/fts3/fts3Int.h +++ ext/fts3/fts3Int.h @@ -425,14 +425,24 @@ int sqlite3Fts3ReadBlock(Fts3Table*, sqlite3_int64, char **, int*, int*); int sqlite3Fts3SelectDoctotal(Fts3Table *, sqlite3_stmt **); int sqlite3Fts3SelectDocsize(Fts3Table *, sqlite3_int64, sqlite3_stmt **); +#ifndef SQLITE_DISABLE_FTS4_DEFERRED void sqlite3Fts3FreeDeferredTokens(Fts3Cursor *); int sqlite3Fts3DeferToken(Fts3Cursor *, Fts3PhraseToken *, int); int sqlite3Fts3CacheDeferredDoclists(Fts3Cursor *); void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *); +int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *); +#else +# define sqlite3Fts3FreeDeferredTokens(x) +# define sqlite3Fts3DeferToken(x,y,z) SQLITE_OK +# define sqlite3Fts3CacheDeferredDoclists(x) SQLITE_OK +# define sqlite3Fts3FreeDeferredDoclists(x) +# define sqlite3Fts3DeferredTokenList(x,y,z) SQLITE_OK +#endif + void sqlite3Fts3SegmentsClose(Fts3Table *); int sqlite3Fts3MaxLevel(Fts3Table *, int *); /* Special values interpreted by sqlite3SegReaderCursor() */ #define FTS3_SEGCURSOR_PENDING -1 @@ -537,16 +547,14 @@ Fts3Table *, Fts3MultiSegReader *, sqlite3_int64 *, char **, int *); int sqlite3Fts3EvalPhrasePoslist(Fts3Cursor *, Fts3Expr *, int iCol, char **); int sqlite3Fts3MsrOvfl(Fts3Cursor *, Fts3MultiSegReader *, int *); int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr); -int sqlite3Fts3DeferredTokenList(Fts3DeferredToken *, char **, int *); - /* fts3_unicode2.c (functions generated by parsing unicode text files) */ #ifdef SQLITE_ENABLE_FTS4_UNICODE61 int sqlite3FtsUnicodeFold(int, int); int sqlite3FtsUnicodeIsalnum(int); int sqlite3FtsUnicodeIsdiacritic(int); #endif #endif /* !SQLITE_CORE || SQLITE_ENABLE_FTS3 */ #endif /* _FTSINT_H */ Index: ext/fts3/fts3_write.c ================================================================== --- ext/fts3/fts3_write.c +++ ext/fts3/fts3_write.c @@ -5044,10 +5044,11 @@ } return rc; } +#ifndef SQLITE_DISABLE_FTS4_DEFERRED /* ** Delete all cached deferred doclists. Deferred doclists are cached ** (allocated) by the sqlite3Fts3CacheDeferredDoclists() function. */ void sqlite3Fts3FreeDeferredDoclists(Fts3Cursor *pCsr){ @@ -5181,10 +5182,11 @@ assert( pToken->pDeferred==0 ); pToken->pDeferred = pDeferred; return SQLITE_OK; } +#endif /* ** SQLite value pRowid contains the rowid of a row that may or may not be ** present in the FTS3 table. If it is, delete it and adjust the contents ** of subsiduary data structures accordingly. Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -1459,11 +1459,11 @@ } next = get2byte(&data[pc]); size = get2byte(&data[pc+2]); if( (next>0 && next<=pc+size+3) || pc+size>usableSize ){ /* Free blocks must be in ascending order. And the last byte of - ** the free-block must lie on the database page. */ + ** the free-block must lie on the database page. */ return SQLITE_CORRUPT_BKPT; } nFree = nFree + size; pc = next; } @@ -2633,11 +2633,11 @@ if( rc==SQLITE_OK ){ if( p->inTrans==TRANS_NONE ){ pBt->nTransaction++; #ifndef SQLITE_OMIT_SHARED_CACHE if( p->sharable ){ - assert( p->lock.pBtree==p && p->lock.iTable==1 ); + assert( p->lock.pBtree==p && p->lock.iTable==1 ); p->lock.eLock = READ_LOCK; p->lock.pNext = pBt->pLock; pBt->pLock = &p->lock; } #endif Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -532,11 +532,11 @@ pNext = pIndex->pNext; assert( pIndex->pSchema==pTable->pSchema ); if( !db || db->pnBytesFreed==0 ){ char *zName = pIndex->zName; TESTONLY ( Index *pOld = ) sqlite3HashInsert( - &pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0 + &pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0 ); assert( db==0 || sqlite3SchemaMutexHeld(db, 0, pIndex->pSchema) ); assert( pOld==pIndex || pOld==0 ); } freeIndex(db, pIndex); Index: src/mem1.c ================================================================== --- src/mem1.c +++ src/mem1.c @@ -229,18 +229,18 @@ /* defer MT decisions to system malloc */ _sqliteZone_ = malloc_default_zone(); }else{ /* only 1 core, use our own zone to contention over global locks, ** e.g. we have our own dedicated locks */ - bool success; + bool success; malloc_zone_t* newzone = malloc_create_zone(4096, 0); malloc_set_zone_name(newzone, "Sqlite_Heap"); do{ success = OSAtomicCompareAndSwapPtrBarrier(NULL, newzone, (void * volatile *)&_sqliteZone_); }while(!_sqliteZone_); - if( !success ){ + if( !success ){ /* somebody registered a zone first */ malloc_destroy_zone(newzone); } } #endif Index: src/os_unix.c ================================================================== --- src/os_unix.c +++ src/os_unix.c @@ -713,13 +713,13 @@ return SQLITE_BUSY; case EACCES: /* EACCES is like EAGAIN during locking operations, but not any other time*/ if( (sqliteIOErr == SQLITE_IOERR_LOCK) || - (sqliteIOErr == SQLITE_IOERR_UNLOCK) || - (sqliteIOErr == SQLITE_IOERR_RDLOCK) || - (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){ + (sqliteIOErr == SQLITE_IOERR_UNLOCK) || + (sqliteIOErr == SQLITE_IOERR_RDLOCK) || + (sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) ){ return SQLITE_BUSY; } /* else fall through */ case EPERM: return SQLITE_PERM; @@ -1762,11 +1762,11 @@ lock.l_start = lock.l_len = 0L; if( unixFileLock(pFile, &lock)==0 ){ pInode->eFileLock = NO_LOCK; }else{ rc = SQLITE_IOERR_UNLOCK; - pFile->lastErrno = errno; + pFile->lastErrno = errno; pInode->eFileLock = NO_LOCK; pFile->eFileLock = NO_LOCK; } } @@ -1778,11 +1778,11 @@ assert( pInode->nLock>=0 ); if( pInode->nLock==0 ){ closePendingFds(pFile); } } - + end_unlock: unixLeaveMutex(); if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock; return rc; } @@ -2045,11 +2045,11 @@ char *zLockFile = (char *)pFile->lockingContext; int rc; assert( pFile ); OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock, - pFile->eFileLock, getpid())); + pFile->eFileLock, getpid())); assert( eFileLock<=SHARED_LOCK ); /* no-op if possible */ if( pFile->eFileLock==eFileLock ){ return SQLITE_OK; @@ -2432,11 +2432,11 @@ sem_t *pSem = pFile->pInode->pSem; assert( pFile ); assert( pSem ); OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock, - pFile->eFileLock, getpid())); + pFile->eFileLock, getpid())); assert( eFileLock<=SHARED_LOCK ); /* no-op if possible */ if( pFile->eFileLock==eFileLock ){ return SQLITE_OK; @@ -3022,11 +3022,11 @@ SimulateIOError( newOffset-- ); if( newOffset!=offset ){ if( newOffset == -1 ){ ((unixFile*)id)->lastErrno = errno; }else{ - ((unixFile*)id)->lastErrno = 0; + ((unixFile*)id)->lastErrno = 0; } return -1; } got = osRead(id->h, pBuf, cnt); #endif @@ -3110,11 +3110,11 @@ SimulateIOError( newOffset-- ); if( newOffset!=offset ){ if( newOffset == -1 ){ ((unixFile*)id)->lastErrno = errno; }else{ - ((unixFile*)id)->lastErrno = 0; + ((unixFile*)id)->lastErrno = 0; } return -1; } got = osWrite(id->h, pBuf, cnt); }while( got<0 && errno==EINTR ); @@ -5624,11 +5624,11 @@ ** with _IOWR('z', 23, struct ByteRangeLockPB2) to track the same 5 states. ** To simulate a F_RDLCK on the shared range, on AFP a randomly selected ** address in the shared range is taken for a SHARED lock, the entire ** shared range is taken for an EXCLUSIVE lock): ** -** PENDING_BYTE 0x40000000 +** PENDING_BYTE 0x40000000 ** RESERVED_BYTE 0x40000001 ** SHARED_RANGE 0x40000002 -> 0x40000200 ** ** This works well on the local file system, but shows a nearly 100x ** slowdown in read performance on AFP because the AFP client disables Index: src/os_win.c ================================================================== --- src/os_win.c +++ src/os_win.c @@ -44,13 +44,15 @@ #ifndef FILE_ATTRIBUTE_MASK # define FILE_ATTRIBUTE_MASK (0x0003FFF7) #endif +#ifndef SQLITE_OMIT_WAL /* Forward references */ typedef struct winShm winShm; /* A connection to shared-memory */ typedef struct winShmNode winShmNode; /* A region of shared-memory */ +#endif /* ** WinCE lacks native support for file locking so we have to fake it ** with some code of our own. */ @@ -74,11 +76,13 @@ HANDLE h; /* Handle for accessing the file */ u8 locktype; /* Type of lock currently held on this file */ short sharedLockByte; /* Randomly chosen byte used as a shared lock */ u8 ctrlFlags; /* Flags. See WINFILE_* below */ DWORD lastErrno; /* The Windows errno from the last I/O error */ +#ifndef SQLITE_OMIT_WAL winShm *pShm; /* Instance of shared memory on this file */ +#endif const char *zPath; /* Full pathname of this file */ int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */ #if SQLITE_OS_WINCE LPWSTR zDeleteOnClose; /* Name of file to delete when closing */ HANDLE hMutex; /* Mutex used to control access to shared lock */ @@ -1935,11 +1939,13 @@ static int winClose(sqlite3_file *id){ int rc, cnt = 0; winFile *pFile = (winFile*)id; assert( id!=0 ); +#ifndef SQLITE_OMIT_WAL assert( pFile->pShm==0 ); +#endif OSTRACE(("CLOSE %d\n", pFile->h)); do{ rc = osCloseHandle(pFile->h); /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */ }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) ); @@ -3685,11 +3691,13 @@ memset(pFile, 0, sizeof(*pFile)); pFile->pMethod = &winIoMethod; pFile->h = h; pFile->lastErrno = NO_ERROR; pFile->pVfs = pVfs; +#ifndef SQLITE_OMIT_WAL pFile->pShm = 0; +#endif pFile->zPath = zName; if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){ pFile->ctrlFlags |= WINFILE_PSOW; } Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -3152,12 +3152,15 @@ ** ^The third argument is the value to bind to the parameter. ** ** ^(In those routines that have a fourth argument, its value is the ** number of bytes in the parameter. To be clear: the value is the ** number of bytes in the value, not the number of characters.)^ -** ^If the fourth parameter is negative, the length of the string is +** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16() +** is negative, then the length of the string is ** the number of bytes up to the first zero terminator. +** If the fourth parameter to sqlite3_bind_blob() is negative, then +** the behavior is undefined. ** If a non-negative fourth parameter is provided to sqlite3_bind_text() ** or sqlite3_bind_text16() then that parameter must be the byte offset ** where the NUL terminator would occur assuming the string were NUL ** terminated. If any NUL characters occur at byte offsets less than ** the value of the fourth parameter then the resulting string value will Index: src/test1.c ================================================================== --- src/test1.c +++ src/test1.c @@ -5926,11 +5926,11 @@ ){ int i; sqlite3 *db; const char *zOpt; int onoff; - int mask; + int mask = 0; static const struct { const char *zOptName; int mask; } aOpt[] = { { "all", SQLITE_OptMask }, Index: src/test_config.c ================================================================== --- src/test_config.c +++ src/test_config.c @@ -316,10 +316,16 @@ #if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_ENABLE_FTS4_UNICODE61) Tcl_SetVar2(interp, "sqlite_options", "fts3_unicode", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "fts3_unicode", "0", TCL_GLOBAL_ONLY); #endif + +#ifdef SQLITE_DISABLE_FTS4_DEFERRED + Tcl_SetVar2(interp, "sqlite_options", "fts4_deferred", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "fts4_deferred", "1", TCL_GLOBAL_ONLY); +#endif #ifdef SQLITE_OMIT_GET_TABLE Tcl_SetVar2(interp, "sqlite_options", "gettable", "0", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "gettable", "1", TCL_GLOBAL_ONLY); Index: src/test_multiplex.c ================================================================== --- src/test_multiplex.c +++ src/test_multiplex.c @@ -500,15 +500,15 @@ int flags, /* Flags to control the opening */ int *pOutFlags /* Flags showing results of opening */ ){ int rc = SQLITE_OK; /* Result code */ multiplexConn *pMultiplexOpen; /* The new multiplex file descriptor */ - multiplexGroup *pGroup; /* Corresponding multiplexGroup object */ + multiplexGroup *pGroup = 0; /* Corresponding multiplexGroup object */ sqlite3_file *pSubOpen = 0; /* Real file descriptor */ sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs; /* Real VFS */ - int nName; - int sz; + int nName = 0; + int sz = 0; char *zToFree = 0; UNUSED_PARAMETER(pVfs); memset(pConn, 0, pVfs->szOsFile); assert( zName || (flags & SQLITE_OPEN_DELETEONCLOSE) ); Index: src/test_spellfix.c ================================================================== --- src/test_spellfix.c +++ src/test_spellfix.c @@ -657,11 +657,11 @@ ){ sqlite3_stmt *pStmt; int rc, rc2; char *zSql; int iLangPrev = -9999; - EditDist3Lang *pLang; + EditDist3Lang *pLang = 0; zSql = sqlite3_mprintf("SELECT iLang, cFrom, cTo, iCost" " FROM \"%w\" WHERE iLang>=0 ORDER BY iLang", zTable); if( zSql==0 ) return SQLITE_NOMEM; rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); @@ -678,11 +678,11 @@ assert( zFrom!=0 || nFrom==0 ); assert( zTo!=0 || nTo==0 ); if( nFrom>100 || nTo>100 ) continue; if( iCost<0 ) continue; - if( iLang!=iLangPrev ){ + if( pLang==0 || iLang!=iLangPrev ){ EditDist3Lang *pNew; pNew = sqlite3_realloc(p->a, (p->nLang+1)*sizeof(p->a[0])); if( pNew==0 ){ rc = SQLITE_NOMEM; break; } p->a = pNew; pLang = &p->a[p->nLang]; @@ -861,13 +861,13 @@ unsigned int *m, int i, int j, int iCost ){ - int b; + assert( iCost>=0 ); if( iCost<10000 ){ - b = m[j] + iCost; + unsigned int b = m[j] + iCost; if( biRow < pCur->nRow ){ if( pCur->pFullScan ){ - int rc = sqlite3_step(pCur->pFullScan); + rc = sqlite3_step(pCur->pFullScan); if( rc!=SQLITE_ROW ) pCur->iRow = pCur->nRow; + if( rc==SQLITE_ROW || rc==SQLITE_DONE ) rc = SQLITE_OK; }else{ pCur->iRow++; } } - return SQLITE_OK; + return rc; } /* ** Return TRUE if we are at the end-of-file */ @@ -2771,29 +2773,39 @@ /* ** Register the various functions and the virtual table. */ static int spellfix1Register(sqlite3 *db){ - int nErr = 0; + int rc = SQLITE_OK; int i; - nErr += sqlite3_create_function(db, "spellfix1_translit", 1, SQLITE_UTF8, 0, + rc = sqlite3_create_function(db, "spellfix1_translit", 1, SQLITE_UTF8, 0, transliterateSqlFunc, 0, 0); - nErr += sqlite3_create_function(db, "spellfix1_editdist", 2, SQLITE_UTF8, 0, + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "spellfix1_editdist", 2, SQLITE_UTF8, 0, editdistSqlFunc, 0, 0); - nErr += sqlite3_create_function(db, "spellfix1_phonehash", 1, SQLITE_UTF8, 0, + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "spellfix1_phonehash", 1, SQLITE_UTF8, 0, phoneticHashSqlFunc, 0, 0); - nErr += sqlite3_create_function(db, "spellfix1_scriptcode", 1, SQLITE_UTF8, 0, + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "spellfix1_scriptcode", 1, SQLITE_UTF8, 0, scriptCodeSqlFunc, 0, 0); - nErr += sqlite3_create_module(db, "spellfix1", &spellfix1Module, 0); - nErr += editDist3Install(db); + } + if( rc==SQLITE_OK ){ + rc = sqlite3_create_module(db, "spellfix1", &spellfix1Module, 0); + } + if( rc==SQLITE_OK ){ + rc = editDist3Install(db); + } /* Verify sanity of the translit[] table */ for(i=0; i0} + ifcapable fts4_deferred { + expr {[fts3_zero_long_segments t1 $limit]>0} + } else { + expr 1 + } } {1} do_fts3query_test 4.$tn.3.1 -deferred five t1 {one AND five} do_fts3query_test 4.$tn.3.2 -deferred five t1 {one NEAR five} do_fts3query_test 4.$tn.3.3 -deferred five t1 {one NEAR/1 five} Index: test/fts3defer.test ================================================================== --- test/fts3defer.test +++ test/fts3defer.test @@ -11,11 +11,11 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl -ifcapable !fts3 { +ifcapable !fts3||!fts4_deferred { finish_test return } set sqlite_fts3_enable_parentheses 1 Index: test/fts3defer2.test ================================================================== --- test/fts3defer2.test +++ test/fts3defer2.test @@ -11,11 +11,14 @@ # set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl -ifcapable !fts3 { finish_test ; return } +ifcapable !fts3||!fts4_deferred { + finish_test + return +} set testprefix fts3defer2 proc mit {blob} { set scan(littleEndian) i* Index: test/fts3matchinfo.test ================================================================== --- test/fts3matchinfo.test +++ test/fts3matchinfo.test @@ -273,15 +273,18 @@ do_matchinfo_test 4.3.3 t5 {t5 MATCH 'a b a'} { s {3} } do_matchinfo_test 4.3.4 t5 {t5 MATCH 'a a a'} { s {3 1} } do_matchinfo_test 4.3.5 t5 {t5 MATCH '"a b" "a b"'} { s {2} } do_matchinfo_test 4.3.6 t5 {t5 MATCH 'a OR b'} { s {1 2 1 1} } -do_execsql_test 4.4.0 { - INSERT INTO t5(t5) VALUES('optimize'); - UPDATE t5_segments - SET block = zeroblob(length(block)) - WHERE length(block)>10000; +do_execsql_test 4.4.0.1 { INSERT INTO t5(t5) VALUES('optimize') } + +ifcapable fts4_deferred { + do_execsql_test 4.4.0.2 { + UPDATE t5_segments + SET block = zeroblob(length(block)) + WHERE length(block)>10000; + } } do_matchinfo_test 4.4.2 t5 {t5 MATCH 'a b'} { s {2} } do_matchinfo_test 4.4.1 t5 {t5 MATCH 'a a'} { s {2 1} } do_matchinfo_test 4.4.2 t5 {t5 MATCH 'a b'} { s {2} } Index: test/fts4aa.test ================================================================== --- test/fts4aa.test +++ test/fts4aa.test @@ -1653,18 +1653,20 @@ do_test fts4aa-1.8 { db eval { SELECT docid FROM t1_docsize EXCEPT SELECT docid FROM t1 } } {} -do_test fts4aa-1.9 { - # Note: Token 'in' is being deferred in the following query. - db eval { - SELECT docid, mit(matchinfo(t1, 'pcxnal')) FROM t1 - WHERE t1 MATCH 'joseph died in egypt' - ORDER BY docid; - } -} {1050026 {4 1 1 1 1 1 1 1 2 1 1 1 1 1 1 23 23}} +ifcapable fts4_deferred { + do_test fts4aa-1.9 { + # Note: Token 'in' is being deferred in the following query. + db eval { + SELECT docid, mit(matchinfo(t1, 'pcxnal')) FROM t1 + WHERE t1 MATCH 'joseph died in egypt' + ORDER BY docid; + } + } {1050026 {4 1 1 1 1 1 1 1 2 1 1 1 1 1 1 23 23}} +} # Should get the same search results from FTS3 # do_test fts4aa-2.0 { db eval { Index: test/releasetest.tcl ================================================================== --- test/releasetest.tcl +++ test/releasetest.tcl @@ -149,10 +149,19 @@ } "Extra-Robustness" { -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1 -DSQLITE_MAX_ATTACHED=62 } + "Devkit" { + -DSQLITE_DEFAULT_FILE_FORMAT=4 + -DSQLITE_MAX_ATTACHED=30 + -DSQLITE_ENABLE_COLUMN_METADATA + -DSQLITE_ENABLE_FTS4 + -DSQLITE_ENABLE_FTS4_PARENTHESIS + -DSQLITE_DISABLE_FTS4_DEFERRED + -DSQLITE_ENABLE_RTREE + } } array set ::Platforms { Linux-x86_64 { "Debug-One" "checksymbols test" @@ -164,10 +173,11 @@ "Ftrapv" test "Default" "threadtest test" "Device-One" fulltest } Linux-i686 { + "Devkit" test "Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test" "Device-One" test "Device-Two" test "Default" "threadtest fulltest" } ADDED tool/checkSpacing.c Index: tool/checkSpacing.c ================================================================== --- /dev/null +++ tool/checkSpacing.c @@ -0,0 +1,84 @@ +/* +** This program checks for formatting problems in source code: +** +** * Any use of tab characters +** * White space at the end of a line +** * Blank lines at the end of a file +** +** Any violations are reported. +*/ +#include +#include +#include + +#define CR_OK 0x001 +#define WSEOL_OK 0x002 + +static void checkSpacing(const char *zFile, unsigned flags){ + FILE *in = fopen(zFile, "rb"); + int i; + int seenSpace; + int seenTab; + int ln = 0; + int lastNonspace = 0; + char zLine[2000]; + if( in==0 ){ + printf("cannot open %s\n", zFile); + return; + } + while( fgets(zLine, sizeof(zLine), in) ){ + seenSpace = 0; + seenTab = 0; + ln++; + for(i=0; zLine[i]; i++){ + if( zLine[i]=='\t' && seenTab==0 ){ + printf("%s:%d: tab (\\t) character\n", zFile, ln); + seenTab = 1; + }else if( zLine[i]=='\r' ){ + if( (flags & CR_OK)==0 ){ + printf("%s:%d: carriage-return (\\r) character\n", zFile, ln); + } + }else if( zLine[i]==' ' ){ + seenSpace = 1; + }else if( zLine[i]!='\n' ){ + lastNonspace = ln; + seenSpace = 0; + } + } + if( seenSpace && (flags & WSEOL_OK)==0 ){ + printf("%s:%d: whitespace at end-of-line\n", zFile, ln); + } + } + fclose(in); + if( lastNonspace #include #ifndef __WIN32__ # if defined(_WIN32) || defined(WIN32) -# define __WIN32__ +# define __WIN32__ # endif #endif #ifdef __WIN32__ #ifdef __cplusplus @@ -651,11 +651,11 @@ break; } } }else if( sp->prec>=0 ){ rp->precsym = rp->rhs[i]; - } + } } } } return; } @@ -709,16 +709,16 @@ }else if( s2->type==MULTITERMINAL ){ for(j=0; jnsubsym; j++){ progress += SetAdd(s1->firstset,s2->subsym[j]->index); } break; - }else if( s1==s2 ){ + }else if( s1==s2 ){ if( s1->lambda==LEMON_FALSE ) break; - }else{ + }else{ progress += SetUnion(s1->firstset,s2->firstset); if( s2->lambda==LEMON_FALSE ) break; - } + } } } }while( progress ); return; } @@ -957,12 +957,12 @@ for(plp=cfp->fplp; plp; plp=plp->next){ change = SetUnion(plp->cfp->fws,cfp->fws); if( change ){ plp->cfp->status = INCOMPLETE; progress = 1; - } - } + } + } cfp->status = COMPLETE; } } }while( progress ); } @@ -991,11 +991,11 @@ if( SetFind(cfp->fws,j) ){ /* Add a reduce action to the state "stp" which will reduce by the ** rule "cfp->rp" if the lookahead symbol is "lemp->symbols[j]" */ Action_add(&stp->ap,REDUCE,lemp->symbols[j],(char *)cfp->rp); } - } + } } } } /* Add the accepting token */ @@ -1260,15 +1260,15 @@ int k; for(k=0; knsubsym; k++){ SetAdd(newcfp->fws, xsp->subsym[k]->index); } break; - }else{ + }else{ SetUnion(newcfp->fws,xsp->firstset); if( xsp->lambda==LEMON_FALSE ) break; - } - } + } + } if( i==rp->nrhs ) Plink_add(&cfp->fplp,newcfp); } } } return; @@ -1994,19 +1994,19 @@ if( psp->prevrule==0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "There is no prior rule upon which to attach the code \ fragment which begins on this line."); psp->errorcnt++; - }else if( psp->prevrule->code!=0 ){ + }else if( psp->prevrule->code!=0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "Code fragment beginning on this line is not the first \ to follow the previous rule."); psp->errorcnt++; }else{ psp->prevrule->line = psp->tokenlineno; psp->prevrule->code = &x[1]; - } + } }else if( x[0]=='[' ){ psp->state = PRECEDENCE_MARK_1; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Token \"%s\" should be either \"%%\" or a nonterminal name.", @@ -2095,19 +2095,19 @@ if( rp==0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "Can't allocate enough memory for this rule."); psp->errorcnt++; psp->prevrule = 0; - }else{ + }else{ int i; rp->ruleline = psp->tokenlineno; rp->rhs = (struct symbol**)&rp[1]; rp->rhsalias = (const char**)&(rp->rhs[psp->nrhs]); for(i=0; inrhs; i++){ rp->rhs[i] = psp->rhs[i]; rp->rhsalias[i] = psp->alias[i]; - } + } rp->lhs = psp->lhs; rp->lhsalias = psp->lhsalias; rp->nrhs = psp->nrhs; rp->code = 0; rp->precsym = 0; @@ -2115,29 +2115,29 @@ rp->nextlhs = rp->lhs->rule; rp->lhs->rule = rp; rp->next = 0; if( psp->firstrule==0 ){ psp->firstrule = psp->lastrule = rp; - }else{ + }else{ psp->lastrule->next = rp; psp->lastrule = rp; - } + } psp->prevrule = rp; - } + } psp->state = WAITING_FOR_DECL_OR_RULE; }else if( isalpha(x[0]) ){ if( psp->nrhs>=MAXRHS ){ ErrorMsg(psp->filename,psp->tokenlineno, "Too many symbols on RHS of rule beginning at \"%s\".", x); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; - }else{ + }else{ psp->rhs[psp->nrhs] = Symbol_new(x); psp->alias[psp->nrhs] = 0; psp->nrhs++; - } + } }else if( (x[0]=='|' || x[0]=='/') && psp->nrhs>0 ){ struct symbol *msp = psp->rhs[psp->nrhs-1]; if( msp->type!=MULTITERMINAL ){ struct symbol *origsp = msp; msp = (struct symbol *) calloc(1,sizeof(*msp)); @@ -2197,28 +2197,28 @@ psp->insertLineMacro = 1; psp->state = WAITING_FOR_DECL_ARG; if( strcmp(x,"name")==0 ){ psp->declargslot = &(psp->gp->name); psp->insertLineMacro = 0; - }else if( strcmp(x,"include")==0 ){ + }else if( strcmp(x,"include")==0 ){ psp->declargslot = &(psp->gp->include); - }else if( strcmp(x,"code")==0 ){ + }else if( strcmp(x,"code")==0 ){ psp->declargslot = &(psp->gp->extracode); - }else if( strcmp(x,"token_destructor")==0 ){ + }else if( strcmp(x,"token_destructor")==0 ){ psp->declargslot = &psp->gp->tokendest; - }else if( strcmp(x,"default_destructor")==0 ){ + }else if( strcmp(x,"default_destructor")==0 ){ psp->declargslot = &psp->gp->vardest; - }else if( strcmp(x,"token_prefix")==0 ){ + }else if( strcmp(x,"token_prefix")==0 ){ psp->declargslot = &psp->gp->tokenprefix; psp->insertLineMacro = 0; - }else if( strcmp(x,"syntax_error")==0 ){ + }else if( strcmp(x,"syntax_error")==0 ){ psp->declargslot = &(psp->gp->error); - }else if( strcmp(x,"parse_accept")==0 ){ + }else if( strcmp(x,"parse_accept")==0 ){ psp->declargslot = &(psp->gp->accept); - }else if( strcmp(x,"parse_failure")==0 ){ + }else if( strcmp(x,"parse_failure")==0 ){ psp->declargslot = &(psp->gp->failure); - }else if( strcmp(x,"stack_overflow")==0 ){ + }else if( strcmp(x,"stack_overflow")==0 ){ psp->declargslot = &(psp->gp->overflow); }else if( strcmp(x,"extra_argument")==0 ){ psp->declargslot = &(psp->gp->arg); psp->insertLineMacro = 0; }else if( strcmp(x,"token_type")==0 ){ @@ -2243,13 +2243,13 @@ psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; }else if( strcmp(x,"nonassoc")==0 ){ psp->preccounter++; psp->declassoc = NONE; psp->state = WAITING_FOR_PRECEDENCE_SYMBOL; - }else if( strcmp(x,"destructor")==0 ){ + }else if( strcmp(x,"destructor")==0 ){ psp->state = WAITING_FOR_DESTRUCTOR_SYMBOL; - }else if( strcmp(x,"type")==0 ){ + }else if( strcmp(x,"type")==0 ){ psp->state = WAITING_FOR_DATATYPE_SYMBOL; }else if( strcmp(x,"fallback")==0 ){ psp->fallback = 0; psp->state = WAITING_FOR_FALLBACK_ID; }else if( strcmp(x,"wildcard")==0 ){ @@ -2257,11 +2257,11 @@ }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Unknown declaration keyword: \"%%%s\".",x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; - } + } }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Illegal declaration keyword: \"%s\".",x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; @@ -2312,14 +2312,14 @@ sp = Symbol_new(x); if( sp->prec>=0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "Symbol \"%s\" has already be given a precedence.",x); psp->errorcnt++; - }else{ + }else{ sp->prec = psp->preccounter; sp->assoc = psp->declassoc; - } + } }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Can't assign a precedence to \"%s\".",x); psp->errorcnt++; } @@ -2585,25 +2585,25 @@ prevc = 0; while( (c= *cp)!=0 && (c!='/' || prevc!='*') ){ if( c=='\n' ) lineno++; prevc = c; cp++; - } - }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */ + } + }else if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments too */ cp = &cp[2]; while( (c= *cp)!=0 && c!='\n' ) cp++; if( c ) lineno++; - }else if( c=='\'' || c=='\"' ){ /* String a character literals */ + }else if( c=='\'' || c=='\"' ){ /* String a character literals */ int startchar, prevc; startchar = c; prevc = 0; for(cp++; (c= *cp)!=0 && (c!=startchar || prevc=='\\'); cp++){ if( c=='\n' ) lineno++; if( prevc=='\\' ) prevc = 0; else prevc = c; - } - } + } + } } if( c==0 ){ ErrorMsg(ps.filename,ps.tokenlineno, "C code starting on this line is not terminated before the end of the file."); ps.errorcnt++;