Index: Makefile.in ================================================================== --- Makefile.in +++ Makefile.in @@ -30,10 +30,11 @@ # CC = @CC@ CFLAGS = @CPPFLAGS@ @CFLAGS@ TCC = ${CC} ${CFLAGS} -I. -I${TOP}/src -I${TOP}/ext/rtree -I${TOP}/ext/icu TCC += -I${TOP}/ext/fts3 -I${TOP}/ext/async -I${TOP}/ext/session +TCC += -I${TOP}/ext/userauth # Define this for the autoconf-based build, so that the code knows it can # include the generated config.h # TCC += -D_HAVE_SQLITE_CONFIG_H -DBUILD_sqlite @@ -185,11 +186,11 @@ notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \ pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \ random.lo resolve.lo rowset.lo rtree.lo \ sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \ table.lo threads.lo tokenize.lo treeview.lo trigger.lo \ - update.lo upsert.lo util.lo vacuum.lo \ + update.lo userauth.lo upsert.lo util.lo vacuum.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ vdbetrace.lo wal.lo walker.lo where.lo wherecode.lo whereexpr.lo \ window.lo utf.lo vtab.lo # Object files for the amalgamation. @@ -354,10 +355,13 @@ $(TOP)/ext/rtree/geopoly.c SRC += \ $(TOP)/ext/session/sqlite3session.c \ $(TOP)/ext/session/sqlite3session.h SRC += \ + $(TOP)/ext/userauth/userauth.c \ + $(TOP)/ext/userauth/sqlite3userauth.h +SRC += \ $(TOP)/ext/rbu/sqlite3rbu.h \ $(TOP)/ext/rbu/sqlite3rbu.c SRC += \ $(TOP)/ext/misc/json1.c \ $(TOP)/ext/misc/stmt.c @@ -453,11 +457,12 @@ $(TOP)/ext/misc/series.c \ $(TOP)/ext/misc/spellfix.c \ $(TOP)/ext/misc/totype.c \ $(TOP)/ext/misc/unionvtab.c \ $(TOP)/ext/misc/wholenumber.c \ - $(TOP)/ext/misc/zipfile.c + $(TOP)/ext/misc/zipfile.c \ + $(TOP)/ext/userauth/userauth.c # Source code to the library files needed by the test fixture # TESTSRC2 = \ $(TOP)/src/attach.c \ @@ -469,10 +474,11 @@ $(TOP)/src/date.c \ $(TOP)/src/dbpage.c \ $(TOP)/src/dbstat.c \ $(TOP)/src/expr.c \ $(TOP)/src/func.c \ + $(TOP)/src/global.c \ $(TOP)/src/insert.c \ $(TOP)/src/wal.c \ $(TOP)/src/main.c \ $(TOP)/src/mem5.c \ $(TOP)/src/os.c \ @@ -558,10 +564,12 @@ $(TOP)/ext/rtree/geopoly.c EXTHDR += \ $(TOP)/ext/icu/sqliteicu.h EXTHDR += \ $(TOP)/ext/rtree/sqlite3rtree.h +EXTHDR += \ + $(TOP)/ext/userauth/sqlite3userauth.h # executables needed for testing # TESTPROGS = \ testfixture$(TEXE) \ @@ -1115,11 +1123,14 @@ $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/fts3/fts3_write.c rtree.lo: $(TOP)/ext/rtree/rtree.c $(HDR) $(EXTHDR) $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/rtree/rtree.c -sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR) +sqlite3session.lo: $(TOP)/ext/userauth/userauth.c $(HDR) $(EXTHDR) + $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/userauth/userauth.c + +userauth.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR) $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/session/sqlite3session.c json1.lo: $(TOP)/ext/misc/json1.c $(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c Index: Makefile.msc ================================================================== --- Makefile.msc +++ Makefile.msc @@ -343,10 +343,11 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1 OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1 !ENDIF OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1 !ENDIF # Should the session extension be enabled? If so, add compilation options Index: doc/lemon.html ================================================================== --- doc/lemon.html +++ doc/lemon.html @@ -774,10 +774,13 @@ %include {#include <unistd.h>}

This might be needed, for example, if some of the C actions in the grammar call functions that are prototyped in unistd.h.

+ +

Use the %code directive to add code to +the end of the generated parser.

The %left directive

The %left directive is used (along with the Index: ext/fts3/fts3.c ================================================================== --- ext/fts3/fts3.c +++ ext/fts3/fts3.c @@ -4164,10 +4164,11 @@ } return rc; } +#ifndef SQLITE_DISABLE_FTS4_DEFERRED /* ** This function is called on each phrase after the position lists for ** any deferred tokens have been loaded into memory. It updates the phrases ** current position list to include only those positions that are really ** instances of the phrase (after considering deferred tokens). If this @@ -4267,10 +4268,11 @@ } } return SQLITE_OK; } +#endif /* SQLITE_DISABLE_FTS4_DEFERRED */ /* ** Maximum number of tokens a phrase may have to be considered for the ** incremental doclists strategy. */ Index: ext/rtree/geopoly.c ================================================================== --- ext/rtree/geopoly.c +++ ext/rtree/geopoly.c @@ -542,19 +542,19 @@ } } #define GEOPOLY_PI 3.1415926535897932385 -/* Fast approximation for cosine(X) for X between -0.5*pi and 2*pi +/* Fast approximation for sine(X) for X between -0.5*pi and 2*pi */ -static double geopolyCosine(double r){ +static double geopolySine(double r){ assert( r>=-0.5*GEOPOLY_PI && r<=2.0*GEOPOLY_PI ); if( r>=1.5*GEOPOLY_PI ){ r -= 2.0*GEOPOLY_PI; } if( r>=0.5*GEOPOLY_PI ){ - return -geopolyCosine(r-GEOPOLY_PI); + return -geopolySine(r-GEOPOLY_PI); }else{ double r2 = r*r; double r3 = r2*r; double r5 = r3*r2; return 0.9996949*r - 0.1656700*r3 + 0.0075134*r5; @@ -591,12 +591,12 @@ p->hdr[1] = 0; p->hdr[2] = (n>>8)&0xff; p->hdr[3] = n&0xff; for(i=0; ia[i*2] = x - r*geopolyCosine(rAngle-0.5*GEOPOLY_PI); - p->a[i*2+1] = y + r*geopolyCosine(rAngle); + p->a[i*2] = x - r*geopolySine(rAngle-0.5*GEOPOLY_PI); + p->a[i*2+1] = y + r*geopolySine(rAngle); } sqlite3_result_blob(context, p->hdr, 4+8*n, SQLITE_TRANSIENT); sqlite3_free(p); } Index: ext/rtree/sqlite3rtree.h ================================================================== --- ext/rtree/sqlite3rtree.h +++ ext/rtree/sqlite3rtree.h @@ -94,11 +94,11 @@ int iLevel; /* Level of current node or entry */ int mxLevel; /* The largest iLevel value in the tree */ sqlite3_int64 iRowid; /* Rowid for current entry */ sqlite3_rtree_dbl rParentScore; /* Score of parent node */ int eParentWithin; /* Visibility of parent node */ - int eWithin; /* OUT: Visiblity */ + int eWithin; /* OUT: Visibility */ sqlite3_rtree_dbl rScore; /* OUT: Write the score here */ /* The following fields are only available in 3.8.11 and later */ sqlite3_value **apSqlParam; /* Original SQL values of parameters */ }; Index: main.mk ================================================================== --- main.mk +++ main.mk @@ -394,10 +394,11 @@ $(TOP)/src/date.c \ $(TOP)/src/dbpage.c \ $(TOP)/src/dbstat.c \ $(TOP)/src/expr.c \ $(TOP)/src/func.c \ + $(TOP)/src/global.c \ $(TOP)/src/insert.c \ $(TOP)/src/wal.c \ $(TOP)/src/main.c \ $(TOP)/src/mem5.c \ $(TOP)/src/os.c \ Index: src/alter.c ================================================================== --- src/alter.c +++ src/alter.c @@ -665,14 +665,20 @@ #else # define renameTokenCheckAll(x,y) #endif /* -** Add a new RenameToken object mapping parse tree element pPtr into -** token *pToken to the Parse object currently under construction. +** Remember that the parser tree element pPtr was created using +** the token pToken. +** +** In other words, construct a new RenameToken object and add it +** to the list of RenameToken objects currently being built up +** in pParse->pRename. ** -** Return a copy of pPtr. +** The pPtr argument is returned so that this routine can be used +** with tail recursion in tokenExpr() routine, for a small performance +** improvement. */ void *sqlite3RenameTokenMap(Parse *pParse, void *pPtr, Token *pToken){ RenameToken *pNew; assert( pPtr || pParse->db->mallocFailed ); renameTokenCheckAll(pParse, pPtr); @@ -1180,19 +1186,12 @@ ** Do a column rename operation on the CREATE statement given in zSql. ** The iCol-th column (left-most is 0) of table zTable is renamed from zCol ** into zNew. The name should be quoted if bQuote is true. ** ** This function is used internally by the ALTER TABLE RENAME COLUMN command. -** Though accessible to application code, it is not intended for use by -** applications. The existance of this function, and the way it works, -** is subject to change without notice. -** -** If any of the parameters are out-of-bounds, then simply return NULL. -** An out-of-bounds parameter can only occur when the application calls -** this function directly. The parameters will always be well-formed when -** this routine is invoked by the bytecode for a legitimate ALTER TABLE -** statement. +** It is only accessible to SQL created using sqlite3NestedParse(). It is +** not reachable from ordinary SQL passed into sqlite3_prepare(). */ static void renameColumnFunc( sqlite3_context *context, int NotUsed, sqlite3_value **argv @@ -1596,12 +1595,12 @@ /* ** Register built-in functions used to help implement ALTER TABLE */ void sqlite3AlterFunctions(void){ static FuncDef aAlterTableFuncs[] = { - FUNCTION(sqlite_rename_column, 9, 0, 0, renameColumnFunc), - FUNCTION(sqlite_rename_table, 7, 0, 0, renameTableFunc), - FUNCTION(sqlite_rename_test, 5, 0, 0, renameTableTest), + INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc), + INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc), + INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest), }; sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs)); } #endif /* SQLITE_ALTER_TABLE */ Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -544,21 +544,26 @@ ** "main" and "temp") for a single database connection. */ void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){ int i; sqlite3BtreeEnterAll(db); - assert( db->nSchemaLock==0 ); for(i=0; inDb; i++){ Db *pDb = &db->aDb[i]; if( pDb->pSchema ){ - sqlite3SchemaClear(pDb->pSchema); + if( db->nSchemaLock==0 ){ + sqlite3SchemaClear(pDb->pSchema); + }else{ + DbSetProperty(db, i, DB_ResetWanted); + } } } db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk); sqlite3VtabUnlockList(db); sqlite3BtreeLeaveAll(db); - sqlite3CollapseDatabaseArray(db); + if( db->nSchemaLock==0 ){ + sqlite3CollapseDatabaseArray(db); + } } /* ** This routine is called when a commit occurs. */ @@ -1894,10 +1899,11 @@ pPk->nColumn = pTab->nCol; } recomputeColumnsNotIndexed(pPk); } +#ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Return true if zName is a shadow table name in the current database ** connection. ** ** zName is temporarily modified while this routine is running, but is @@ -1919,10 +1925,13 @@ if( pMod==0 ) return 0; if( pMod->pModule->iVersion<3 ) return 0; if( pMod->pModule->xShadowName==0 ) return 0; return pMod->pModule->xShadowName(zTail+1); } +#else +# define isShadowTableName(x,y) 0 +#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ /* ** This routine is called to report the final ")" that terminates ** a CREATE TABLE statement. ** Index: src/delete.c ================================================================== --- src/delete.c +++ src/delete.c @@ -68,13 +68,15 @@ db = pParse->db; if( (pTab->tabFlags & TF_Readonly)!=0 ){ return sqlite3WritableSchema(db)==0 && pParse->nested==0; } assert( pTab->tabFlags & TF_Shadow ); - return (db->flags & SQLITE_Defensive)!=0 - && db->nVdbeExec==0 - && db->pVtabCtx==0; + return (db->flags & SQLITE_Defensive)!=0 +#ifndef SQLITE_OMIT_VIRTUALTABLE + && db->pVtabCtx==0 +#endif + && db->nVdbeExec==0; } /* ** Check to make sure the given table is writable. If it is not ** writable, generate an error message and return 1. If it is Index: src/global.c ================================================================== --- src/global.c +++ src/global.c @@ -238,10 +238,11 @@ #endif #ifndef SQLITE_UNTESTABLE 0, /* xTestCallback */ #endif 0, /* bLocaltimeFault */ + 0, /* bInternalFunctions */ 0x7ffffffe, /* iOnceResetThreshold */ SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */ }; /* Index: src/loadext.c ================================================================== --- src/loadext.c +++ src/loadext.c @@ -82,10 +82,11 @@ # define sqlite3_create_module 0 # define sqlite3_create_module_v2 0 # define sqlite3_declare_vtab 0 # define sqlite3_vtab_config 0 # define sqlite3_vtab_on_conflict 0 +# define sqlite3_vtab_collation 0 #endif #ifdef SQLITE_OMIT_SHARED_CACHE # define sqlite3_enable_shared_cache 0 #endif Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -3951,18 +3951,29 @@ break; } /* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff); ** - ** If parameter onoff is non-zero, configure the wrappers so that all - ** subsequent calls to localtime() and variants fail. If onoff is zero, - ** undo this setting. + ** If parameter onoff is non-zero, subsequent calls to localtime() + ** and its variants fail. If onoff is zero, undo this setting. */ case SQLITE_TESTCTRL_LOCALTIME_FAULT: { sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int); break; } + + /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCS, int onoff); + ** + ** If parameter onoff is non-zero, internal-use-only SQL functions + ** are visible to ordinary SQL. This is useful for testing but is + ** unsafe because invalid parameters to those internal-use-only functions + ** can result in crashes or segfaults. + */ + case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: { + sqlite3GlobalConfig.bInternalFunctions = va_arg(ap, int); + break; + } /* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int); ** ** Set or clear a flag that indicates that the database file is always well- ** formed and never corrupt. This flag is clear by default, indicating that Index: src/pager.c ================================================================== --- src/pager.c +++ src/pager.c @@ -850,23 +850,10 @@ #endif return 1; } #endif -/* -** Return true if this pager uses a write-ahead log to read page pgno. -** Return false if the pager reads pgno directly from the database. -*/ -#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_DIRECT_OVERFLOW_READ) -int sqlite3PagerUseWal(Pager *pPager, Pgno pgno){ - u32 iRead = 0; - int rc; - if( pPager->pWal==0 ) return 0; - rc = sqlite3WalFindFrame(pPager->pWal, pgno, &iRead); - return rc || iRead; -} -#endif #ifndef SQLITE_OMIT_WAL # define pagerUseWal(x) ((x)->pWal!=0) #else # define pagerUseWal(x) 0 # define pagerRollbackWal(x) 0 @@ -7198,12 +7185,15 @@ void *(*xCodec)(void*,void*,Pgno,int), void (*xCodecSizeChng)(void*,int,int), void (*xCodecFree)(void*), void *pCodec ){ - pager_reset(pPager); - if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec); + if( pPager->xCodecFree ){ + pPager->xCodecFree(pPager->pCodec); + }else{ + pager_reset(pPager); + } pPager->xCodec = pPager->memDb ? 0 : xCodec; pPager->xCodecSizeChng = xCodecSizeChng; pPager->xCodecFree = xCodecFree; pPager->pCodec = pCodec; setGetterMethod(pPager); Index: src/pager.h ================================================================== --- src/pager.h +++ src/pager.h @@ -178,22 +178,17 @@ int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*); int sqlite3PagerWalSupported(Pager *pPager); int sqlite3PagerWalCallback(Pager *pPager); int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen); int sqlite3PagerCloseWal(Pager *pPager, sqlite3*); -# ifdef SQLITE_DIRECT_OVERFLOW_READ - int sqlite3PagerUseWal(Pager *pPager, Pgno); -# endif # ifdef SQLITE_ENABLE_SNAPSHOT int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot); int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot); int sqlite3PagerSnapshotRecover(Pager *pPager); int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot); void sqlite3PagerSnapshotUnlock(Pager *pPager); # endif -#else -# define sqlite3PagerUseWal(x,y) 0 #endif #ifdef SQLITE_DIRECT_OVERFLOW_READ int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno); #endif Index: src/pcache1.c ================================================================== --- src/pcache1.c +++ src/pcache1.c @@ -103,11 +103,12 @@ PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */ PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */ }; /* -** A page is pinned if it is no on the LRU list +** A page is pinned if it is not on the LRU list. To be "pinned" means +** that the page is in active use and must not be deallocated. */ #define PAGE_IS_PINNED(p) ((p)->pLruNext==0) #define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0) /* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -1237,10 +1237,11 @@ HashElem *j; FuncDef *p; pParse->nMem = 2; for(i=0; iu.pHash ){ + if( p->funcFlags & SQLITE_FUNC_INTERNAL ) continue; sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1); } } for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){ p = (FuncDef*)sqliteHashData(j); Index: src/resolve.c ================================================================== --- src/resolve.c +++ src/resolve.c @@ -768,10 +768,19 @@ /* Date/time functions that use 'now', and other functions like ** sqlite_version() that might change over time cannot be used ** in an index. */ notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr|NC_PartIdx); + } + if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 + && pParse->nested==0 + && sqlite3Config.bInternalFunctions==0 + ){ + /* Internal-use-only functions are disallowed unless the + ** SQL is being compiled using sqlite3NestedParse() */ + no_such_func = 1; + pDef = 0; } } if( 0==IN_RENAME_OBJECT ){ #ifndef SQLITE_OMIT_WINDOWFUNC Index: src/shell.c.in ================================================================== --- src/shell.c.in +++ src/shell.c.in @@ -7675,10 +7675,11 @@ /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/ /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/ { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */ { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"}, + { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" }, { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" }, { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" }, { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" }, #ifdef YYCOVERAGE { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" }, @@ -7769,10 +7770,11 @@ break; /* sqlite3_test_control(int, int) */ case SQLITE_TESTCTRL_ASSERT: case SQLITE_TESTCTRL_ALWAYS: + case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: if( nArg==3 ){ int opt = booleanValue(azArg[2]); rc2 = sqlite3_test_control(testctrl, opt); isOk = 1; } Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -3631,11 +3631,11 @@ ** ** [[SQLITE_PREPARE_NORMALIZE]] ^(
SQLITE_PREPARE_NORMALIZE
**
The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized ** representation of the SQL statement should be calculated and then ** associated with the prepared statement, which can be obtained via -** the [sqlite3_normalized_sql()] interface. The semantics used to +** the [sqlite3_normalized_sql()] interface.)^ The semantics used to ** normalize a SQL statement are unspecified and subject to change. ** At a minimum, literal values will be replaced with suitable ** placeholders. ** */ @@ -7240,10 +7240,11 @@ #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ +#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17 #define SQLITE_TESTCTRL_LOCALTIME_FAULT 18 #define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */ #define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19 #define SQLITE_TESTCTRL_NEVER_CORRUPT 20 #define SQLITE_TESTCTRL_VDBE_COVERAGE 21 Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -1693,12 +1693,13 @@ #define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */ #define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a ** single query - might change over time */ #define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */ #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ -#define SQLITE_FUNC_WINDOW 0x10000 /* Built-in window-only function */ -#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */ +#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ +#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */ +#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are ** used to create the initializers for the FuncDef structures. ** @@ -1770,14 +1771,17 @@ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,0,#zName, {0}} #define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}} - #define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \ {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \ SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}} +#define INTERNAL_FUNCTION(zName, nArg, xFunc) \ + {nArg, SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \ + 0, 0, xFunc, 0, 0, 0, #zName, {0} } + /* ** All current savepoints are stored in a linked list starting at ** sqlite3.pSavepoint. The first element in the list is the most recently ** opened savepoint. Savepoints are added to the list by the vdbe @@ -3424,10 +3428,11 @@ #endif #ifndef SQLITE_UNTESTABLE int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */ #endif int bLocaltimeFault; /* True to fail localtime() calls */ + int bInternalFunctions; /* Internal SQL functions are visible */ int iOnceResetThreshold; /* When to reset OP_Once counters */ u32 szSorterRef; /* Min size in bytes to use sorter-refs */ }; /* Index: src/test1.c ================================================================== --- src/test1.c +++ src/test1.c @@ -6327,11 +6327,11 @@ } /* ** tclcmd: database_may_be_corrupt ** -** Indicate that database files might be corrupt. In other words, set the normal +** Indicate that database files might be corrupt. In other words, set the normal ** state of operation. */ static int SQLITE_TCLAPI database_may_be_corrupt( ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ @@ -6342,12 +6342,13 @@ return TCL_OK; } /* ** tclcmd: database_never_corrupt ** -** Indicate that database files are always well-formed. This enables extra assert() -** statements that test conditions that are always true for well-formed databases. +** Indicate that database files are always well-formed. This enables +** extra assert() statements that test conditions that are always true +** for well-formed databases. */ static int SQLITE_TCLAPI database_never_corrupt( ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ @@ -6709,13 +6710,14 @@ ){ struct Verb { const char *zName; int i; } aVerb[] = { - { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT }, - { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP }, - { "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER }, + { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT }, + { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP }, + { "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER }, + { "SQLITE_TESTCTRL_INTERNAL_FUNCTIONS", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS}, }; int iVerb; int iFlag; int rc; @@ -6729,18 +6731,19 @@ ); if( rc!=TCL_OK ) return rc; iFlag = aVerb[iVerb].i; switch( iFlag ){ + case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: case SQLITE_TESTCTRL_LOCALTIME_FAULT: { int val; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "ONOFF"); return TCL_ERROR; } if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; - sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val); + sqlite3_test_control(iFlag, val); break; } case SQLITE_TESTCTRL_SORTER_MMAP: { int val; Index: test/alter.test ================================================================== --- test/alter.test +++ test/alter.test @@ -682,10 +682,11 @@ #-------------------------------------------------------------------------- # alter-9.X - Special test: Make sure the sqlite_rename_column() and # rename_table() functions do not crash when handed bad input. # +sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test alter-9.1 { execsql {SELECT SQLITE_RENAME_COLUMN(0,0,0,0,0,0,0,0,0)} } {{}} foreach {tn sql} { 1 { SELECT SQLITE_RENAME_TABLE(0,0,0,0,0,0,0) } @@ -694,10 +695,18 @@ } { do_test alter-9.2.$tn { catch { execsql $sql } } 1 } +sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 + +# If the INTERNAL_FUNCTIONS test-control is disabled (which is the default), +# then the sqlite_rename_table() SQL function is not accessible to ordinary SQL. +# +do_catchsql_test alter-9.3 { + SELECT sqlite_rename_table(0,0,0,0,0,0,0); +} {1 {no such function: sqlite_rename_table}} #------------------------------------------------------------------------ # alter-10.X - Make sure ALTER TABLE works with multi-byte UTF-8 characters # in the names. # Index: test/altercol.test ================================================================== --- test/altercol.test +++ test/altercol.test @@ -616,10 +616,11 @@ } #------------------------------------------------------------------------- # Passing invalid parameters directly to sqlite_rename_column(). # +sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_execsql_test 14.1 { CREATE TABLE ddd(sql, type, object, db, tbl, icol, znew, bquote); INSERT INTO ddd VALUES( 'CREATE TABLE x1(i INTEGER, t TEXT)', 'table', 'x1', 'main', 'x1', -1, 'zzz', 0 @@ -638,10 +639,19 @@ do_execsql_test 14.2 { SELECT sqlite_rename_column(sql, type, object, db, tbl, icol, znew, bquote, 0) FROM ddd; } {{} {} {} {}} +sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 + +# If the INTERNAL_FUNCTIONS test-control is disabled (which is the default) +# then the sqlite_rename_table() SQL function is not accessible to +# ordinary SQL. +# +do_catchsql_test 14.3 { + SELECT sqlite_rename_column(0,0,0,0,0,0,0,0,0); +} {1 {no such function: sqlite_rename_column}} #------------------------------------------------------------------------- # reset_db do_execsql_test 15.0 { Index: test/altertab.test ================================================================== --- test/altertab.test +++ test/altertab.test @@ -238,15 +238,17 @@ ), ( 'main', NULL, 'ddd', 'eee', 0 ); } {} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_execsql_test 7.2 { SELECT sqlite_rename_table(db, 0, 0, sql, zOld, zNew, bTemp) FROM ddd; } {{} {} {}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 } #------------------------------------------------------------------------- # reset_db Index: test/attach.test ================================================================== --- test/attach.test +++ test/attach.test @@ -724,11 +724,11 @@ DELETE FROM t1 WHERE x<(SELECT min(x) FROM temp.t6); END; } db2 } {1 {trigger r5 cannot reference objects in database temp}} } ;# endif subquery -ifcapable json1 { +ifcapable json1&&vtab { do_test attach-5.10 { db close catch {db2 close} forcedelete test.db sqlite3 db test.db Index: test/fkey2.test ================================================================== --- test/fkey2.test +++ test/fkey2.test @@ -985,19 +985,21 @@ proc test_rename_parent {zCreate zOld zNew} { db eval {SELECT sqlite_rename_table( 'main', 'table', 't1', $zCreate, $zOld, $zNew, 0 )} } + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test fkey2-14.2.1.1 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} do_test fkey2-14.2.1.2 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3 } {{CREATE TABLE t1(a REFERENCES t2)}} do_test fkey2-14.2.1.3 { test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 # Test ALTER TABLE RENAME TABLE a bit. # do_test fkey2-14.2.2.1 { drop_all_tables @@ -1066,19 +1068,21 @@ PRAGMA foreign_keys = on; SELECT sql FROM temp.sqlite_master WHERE name='t2'; } } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test fkey2-14.2tmp.1.1 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} do_test fkey2-14.2tmp.1.2 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3 } {{CREATE TABLE t1(a REFERENCES t2)}} do_test fkey2-14.2tmp.1.3 { test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 # Test ALTER TABLE RENAME TABLE a bit. # do_test fkey2-14.2tmp.2.1 { drop_all_tables @@ -1148,19 +1152,21 @@ PRAGMA foreign_keys = on; SELECT sql FROM aux.sqlite_master WHERE name='t2'; } } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test fkey2-14.2aux.1.1 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} do_test fkey2-14.2aux.1.2 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3 } {{CREATE TABLE t1(a REFERENCES t2)}} do_test fkey2-14.2aux.1.3 { test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 # Test ALTER TABLE RENAME TABLE a bit. # do_test fkey2-14.2aux.2.1 { drop_all_tables Index: test/incrvacuum.test ================================================================== --- test/incrvacuum.test +++ test/incrvacuum.test @@ -786,49 +786,51 @@ #------------------------------------------------------------------------- # At one point it was unsafe to truncate a db file on windows while there # were outstanding xFetch() references. This test case attempts to hit # that case. # -reset_db -do_execsql_test incrvacuum-16.0 { - PRAGMA auto_vacuum = 2; - CREATE TABLE t3(a); - INSERT INTO t3 VALUES(1), (2), (3), (4); - - CREATE TABLE t2(x); - INSERT INTO t2 VALUES( randomblob(1000) ); - INSERT INTO t2 VALUES( randomblob(1000) ); - INSERT INTO t2 VALUES( randomblob(1000) ); - INSERT INTO t2 VALUES( randomblob(1000) ); - INSERT INTO t2 VALUES( randomblob(1000) ); - INSERT INTO t2 VALUES( randomblob(1000) ); -} {} - -# Reopen db to ensure the page-cache is empty. -# -db close -sqlite3 db test.db - -# Open db in mmap-mode. Open a transaction, delete some data, then run -# incremental-vacuum. Do not commit the transaction. -# -do_execsql_test incrvacuum-16.1 { - PRAGMA mmap_size = 1000000; - BEGIN; - DELETE FROM t2; - PRAGMA incremental_vacuum = 1000; -} {1000000} - -# Scan through table t3 (which is all clean pages - so mmap is used). Then, -# midway through, commit the transaction. This causes the db to be truncated -# while there are outstanding xFetch pages. -# -do_test incrvacuum-16.2 { - set res [list] - db eval { SELECT a FROM t3 } { - if {$a==3} { db eval COMMIT } - lappend res $a - } - set res -} {1 2 3 4} - +ifcapable mmap { + reset_db + do_execsql_test incrvacuum-16.0 { + PRAGMA auto_vacuum = 2; + CREATE TABLE t3(a); + INSERT INTO t3 VALUES(1), (2), (3), (4); + + CREATE TABLE t2(x); + INSERT INTO t2 VALUES( randomblob(1000) ); + INSERT INTO t2 VALUES( randomblob(1000) ); + INSERT INTO t2 VALUES( randomblob(1000) ); + INSERT INTO t2 VALUES( randomblob(1000) ); + INSERT INTO t2 VALUES( randomblob(1000) ); + INSERT INTO t2 VALUES( randomblob(1000) ); + } {} + + # Reopen db to ensure the page-cache is empty. + # + db close + sqlite3 db test.db + + # Open db in mmap-mode. Open a transaction, delete some data, then run + # incremental-vacuum. Do not commit the transaction. + # + do_execsql_test incrvacuum-16.1 { + PRAGMA mmap_size = 1000000; + BEGIN; + DELETE FROM t2; + PRAGMA incremental_vacuum = 1000; + } {1000000} + + # Scan through table t3 (which is all clean pages - so mmap is used). Then, + # midway through, commit the transaction. This causes the db to be truncated + # while there are outstanding xFetch pages. + # + do_test incrvacuum-16.2 { + set res [list] + db eval { SELECT a FROM t3 } { + if {$a==3} { db eval COMMIT } + lappend res $a + } + set res + } {1 2 3 4} +} + finish_test Index: test/indexexpr2.test ================================================================== --- test/indexexpr2.test +++ test/indexexpr2.test @@ -199,35 +199,37 @@ } {0} # Additional test cases to show that UPDATE does not modify indexes that # do not involve unchanged columns. # -load_static_extension db explain -do_execsql_test 4.200 { - CREATE TABLE t2(a,b,c,d,e,f); - INSERT INTO t2 VALUES(2,3,4,5,6,7); - CREATE INDEX t2abc ON t2(a+b+c); - CREATE INDEX t2cd ON t2(c*d); - CREATE INDEX t2def ON t2(d,e+25*f); - SELECT sqlite_master.name - FROM sqlite_master, explain('UPDATE t2 SET b=b+1') - WHERE explain.opcode LIKE 'Open%' - AND sqlite_master.rootpage=explain.p2 - ORDER BY 1; -} {t2 t2abc} -do_execsql_test 4.210 { - SELECT sqlite_master.name - FROM sqlite_master, explain('UPDATE t2 SET c=c+1') - WHERE explain.opcode LIKE 'Open%' - AND sqlite_master.rootpage=explain.p2 - ORDER BY 1; -} {t2 t2abc t2cd} -do_execsql_test 4.220 { - SELECT sqlite_master.name - FROM sqlite_master, explain('UPDATE t2 SET c=c+1, f=NULL') - WHERE explain.opcode LIKE 'Open%' - AND sqlite_master.rootpage=explain.p2 - ORDER BY 1; -} {t2 t2abc t2cd t2def} +ifcapable vtab { + load_static_extension db explain + do_execsql_test 4.200 { + CREATE TABLE t2(a,b,c,d,e,f); + INSERT INTO t2 VALUES(2,3,4,5,6,7); + CREATE INDEX t2abc ON t2(a+b+c); + CREATE INDEX t2cd ON t2(c*d); + CREATE INDEX t2def ON t2(d,e+25*f); + SELECT sqlite_master.name + FROM sqlite_master, explain('UPDATE t2 SET b=b+1') + WHERE explain.opcode LIKE 'Open%' + AND sqlite_master.rootpage=explain.p2 + ORDER BY 1; + } {t2 t2abc} + do_execsql_test 4.210 { + SELECT sqlite_master.name + FROM sqlite_master, explain('UPDATE t2 SET c=c+1') + WHERE explain.opcode LIKE 'Open%' + AND sqlite_master.rootpage=explain.p2 + ORDER BY 1; + } {t2 t2abc t2cd} + do_execsql_test 4.220 { + SELECT sqlite_master.name + FROM sqlite_master, explain('UPDATE t2 SET c=c+1, f=NULL') + WHERE explain.opcode LIKE 'Open%' + AND sqlite_master.rootpage=explain.p2 + ORDER BY 1; + } {t2 t2abc t2cd t2def} +} finish_test ADDED test/lemon-test01.y Index: test/lemon-test01.y ================================================================== --- /dev/null +++ test/lemon-test01.y @@ -0,0 +1,75 @@ +// A test case for the LEMON parser generator. Run as follows: +// +// lemon lemon-test01.y && gcc -g lemon-test01.c && ./a.out +// +%token_prefix TK_ +%token_type int +%default_type int +%include { + static int nSyntaxError = 0; + static int nAccept = 0; + static int nFailure = 0; +} + +all ::= A B. +all ::= error B. + +%syntax_error { + nSyntaxError++; +} +%parse_accept { + nAccept++; +} +%parse_failure { + nFailure++; +} +%code { + #include + #include "lemon-test01.h" + static int nTest = 0; + static int nErr = 0; + static int testCase(int testId, int shouldBe, int actual){ + nTest++; + if( shouldBe==actual ){ + printf("test %d: ok\n", testId); + }else{ + printf("test %d: got %d, expected %d\n", testId, actual, shouldBe); + nErr++; + } + } + int main(int argc, char **argv){ + yyParser xp; + ParseInit(&xp); + Parse(&xp, TK_A, 0); + Parse(&xp, TK_B, 0); + Parse(&xp, 0, 0); + ParseFinalize(&xp); + testCase(100, 0, nSyntaxError); + testCase(110, 1, nAccept); + testCase(120, 0, nFailure); + nSyntaxError = nAccept = nFailure = 0; + ParseInit(&xp); + Parse(&xp, TK_B, 0); + Parse(&xp, TK_B, 0); + Parse(&xp, 0, 0); + ParseFinalize(&xp); + testCase(200, 1, nSyntaxError); + testCase(210, 1, nAccept); + testCase(220, 0, nFailure); + nSyntaxError = nAccept = nFailure = 0; + ParseInit(&xp); + Parse(&xp, TK_A, 0); + Parse(&xp, TK_A, 0); + Parse(&xp, 0, 0); + ParseFinalize(&xp); + testCase(200, 1, nSyntaxError); + testCase(210, 0, nAccept); + testCase(220, 0, nFailure); + if( nErr==0 ){ + printf("%d tests pass\n", nTest); + }else{ + printf("%d errors out %d tests\n", nErr, nTest); + } + return nErr; + } +} Index: test/pragma4.test ================================================================== --- test/pragma4.test +++ test/pragma4.test @@ -120,12 +120,12 @@ sqlite3 db3 test.db sqlite3 db2 test.db2 execsql { DROP TABLE t1 } db3 execsql { DROP TABLE t2 } db2 } {} -do_execsql_test 4.1.5 { PRAGMA table_info = t1 } -do_execsql_test 4.1.6 { PRAGMA table_info = t2 } +do_execsql_test 4.1.5 { PRAGMA table_info(t1) } +do_execsql_test 4.1.6 { PRAGMA table_info(t2) } db2 close db3 close reset_db forcedelete test.db2 @@ -132,24 +132,28 @@ do_execsql_test 4.2.1 { CREATE TABLE t1(a, b, c); ATTACH 'test.db2' AS aux; CREATE TABLE aux.t2(d, e, f); } -do_execsql_test 4.2.2 { SELECT * FROM pragma_table_info('t1') } { - 0 a {} 0 {} 0 1 b {} 0 {} 0 2 c {} 0 {} 0 -} -do_execsql_test 4.2.3 { SELECT * FROM pragma_table_info('t2') } { - 0 d {} 0 {} 0 1 e {} 0 {} 0 2 f {} 0 {} 0 +ifcapable vtab { + do_execsql_test 4.2.2 { SELECT * FROM pragma_table_info('t1') } { + 0 a {} 0 {} 0 1 b {} 0 {} 0 2 c {} 0 {} 0 + } + do_execsql_test 4.2.3 { SELECT * FROM pragma_table_info('t2') } { + 0 d {} 0 {} 0 1 e {} 0 {} 0 2 f {} 0 {} 0 + } } do_test 4.2.4 { sqlite3 db3 test.db sqlite3 db2 test.db2 execsql { DROP TABLE t1 } db3 execsql { DROP TABLE t2 } db2 } {} -do_execsql_test 4.2.5 { SELECT * FROM pragma_table_info('t1') } -do_execsql_test 4.2.6 { SELECT * FROM pragma_table_info('t2') } +ifcapable vtab { + do_execsql_test 4.2.5 { SELECT * FROM pragma_table_info('t1') } + do_execsql_test 4.2.6 { SELECT * FROM pragma_table_info('t2') } +} db2 close db3 close reset_db forcedelete test.db2 @@ -158,52 +162,67 @@ CREATE INDEX i1 ON t1(b); ATTACH 'test.db2' AS aux; CREATE TABLE aux.t2(d, e, f); CREATE INDEX aux.i2 ON t2(e); } -do_execsql_test 4.3.2 { SELECT * FROM pragma_index_info('i1') } {0 1 b} -do_execsql_test 4.3.3 { SELECT * FROM pragma_index_info('i2') } {0 1 e} +ifcapable vtab { + do_execsql_test 4.3.2 { SELECT * FROM pragma_index_info('i1') } {0 1 b} + do_execsql_test 4.3.3 { SELECT * FROM pragma_index_info('i2') } {0 1 e} +} do_test 4.3.4 { sqlite3 db3 test.db sqlite3 db2 test.db2 execsql { DROP INDEX i1 } db3 execsql { DROP INDEX i2 } db2 } {} -do_execsql_test 4.3.5 { SELECT * FROM pragma_index_info('i1') } -do_execsql_test 4.3.6 { SELECT * FROM pragma_index_info('i2') } +ifcapable vtab { + do_execsql_test 4.3.5 { SELECT * FROM pragma_index_info('i1') } + do_execsql_test 4.3.6 { SELECT * FROM pragma_index_info('i2') } +} +execsql {SELECT * FROM main.sqlite_master, aux.sqlite_master} do_execsql_test 4.4.0 { CREATE INDEX main.i1 ON t1(b, c); CREATE INDEX aux.i2 ON t2(e, f); } -do_execsql_test 4.4.1 { SELECT * FROM pragma_index_list('t1') } {0 i1 0 c 0} -do_execsql_test 4.4.2 { SELECT * FROM pragma_index_list('t2') } {0 i2 0 c 0} +ifcapable vtab { + do_execsql_test 4.4.1 { SELECT * FROM pragma_index_list('t1') } {0 i1 0 c 0} + do_execsql_test 4.4.2 { SELECT * FROM pragma_index_list('t2') } {0 i2 0 c 0} +} do_test 4.4.3 { execsql { DROP INDEX i1 } db3 execsql { DROP INDEX i2 } db2 } {} -do_execsql_test 4.4.5 { SELECT * FROM pragma_index_list('t1') } {} -do_execsql_test 4.4.6 { SELECT * FROM pragma_index_list('t2') } {} +ifcapable vtab { + do_execsql_test 4.4.5 { SELECT * FROM pragma_index_list('t1') } {} + do_execsql_test 4.4.6 { SELECT * FROM pragma_index_list('t2') } {} +} +execsql {SELECT * FROM main.sqlite_master, aux.sqlite_master} do_execsql_test 4.5.0 { CREATE UNIQUE INDEX main.i1 ON t1(a); CREATE UNIQUE INDEX aux.i2 ON t2(d); CREATE TABLE main.c1 (a, b, c REFERENCES t1(a)); CREATE TABLE aux.c2 (d, e, r REFERENCES t2(d)); } -do_execsql_test 4.5.1 { SELECT * FROM pragma_foreign_key_list('c1') } { - 0 0 t1 c a {NO ACTION} {NO ACTION} NONE -} -do_execsql_test 4.5.2 { SELECT * FROM pragma_foreign_key_list('c2') } { - 0 0 t2 r d {NO ACTION} {NO ACTION} NONE +ifcapable vtab { + do_execsql_test 4.5.1 { SELECT * FROM pragma_foreign_key_list('c1') } { + 0 0 t1 c a {NO ACTION} {NO ACTION} NONE + } + do_execsql_test 4.5.2 { SELECT * FROM pragma_foreign_key_list('c2') } { + 0 0 t2 r d {NO ACTION} {NO ACTION} NONE + } } do_test 4.5.3 { execsql { DROP TABLE c1 } db3 execsql { DROP TABLE c2 } db2 } {} -do_execsql_test 4.5.1 { SELECT * FROM pragma_foreign_key_list('c1') } -do_execsql_test 4.5.2 { SELECT * FROM pragma_foreign_key_list('c2') } +ifcapable vtab { + do_execsql_test 4.5.4 { SELECT * FROM pragma_foreign_key_list('c1') } + do_execsql_test 4.5.5 { SELECT * FROM pragma_foreign_key_list('c2') } +} +execsql {SELECT * FROM main.sqlite_master, aux.sqlite_master} do_execsql_test 4.6.0 { CREATE TABLE main.c1 (a, b, c REFERENCES t1(a)); CREATE TABLE aux.c2 (d, e, r REFERENCES t2(d)); INSERT INTO main.c1 VALUES(1, 2, 3); @@ -222,6 +241,5 @@ do_catchsql_test 4.6.5 { pragma foreign_key_check('c2') } {1 {no such table: c2}} finish_test - Index: test/releasetest.tcl ================================================================== --- test/releasetest.tcl +++ test/releasetest.tcl @@ -77,10 +77,13 @@ "Unlock-Notify" { -O2 -DSQLITE_ENABLE_UNLOCK_NOTIFY -DSQLITE_THREADSAFE -DSQLITE_TCL_DEFAULT_FULLMUTEX=1 + } + "User-Auth" { + -O2 -DSQLITE_USER_AUTHENTICATION=1 } "Secure-Delete" { -O2 -DSQLITE_SECURE_DELETE=1 @@ -272,10 +275,11 @@ "Fast-One" "fuzztest test" "Debug-One" "mptest test" "Have-Not" test "Secure-Delete" test "Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test" + "User-Auth" tcltest "Update-Delete-Limit" test "Extra-Robustness" test "Device-Two" test "No-lookaside" test "Devkit" test Index: test/vtab_err.test ================================================================== --- test/vtab_err.test +++ test/vtab_err.test @@ -18,11 +18,10 @@ finish_test return } - unset -nocomplain echo_module_begin_fail do_ioerr_test vtab_err-1 -tclprep { register_echo_module [sqlite3_connection_pointer db] } -sqlbody { BEGIN; @@ -60,7 +59,29 @@ INSERT INTO e SELECT a||'x', b, c FROM r2; COMMIT; } sqlite3_memdebug_fail -1 + +reset_db +register_echo_module [sqlite3_connection_pointer db] +do_execsql_test vtab_err-3.0 { + CREATE TABLE r(a PRIMARY KEY, b, c); + CREATE VIRTUAL TABLE e USING echo(r); +} +faultsim_save_and_close + +do_faultsim_test vtab_err-3 -faults oom-t* -prep { + faultsim_restore_and_reopen + register_echo_module [sqlite3_connection_pointer db] +} -body { + execsql { + BEGIN; + CREATE TABLE xyz(x); + SELECT a FROM e; + COMMIT; + } +} -test { + faultsim_test_result {0 {}} +} finish_test Index: test/without_rowid3.test ================================================================== --- test/without_rowid3.test +++ test/without_rowid3.test @@ -951,19 +951,21 @@ proc test_rename_parent {zCreate zOld zNew} { db eval {SELECT sqlite_rename_table( 'main', 'table', 't1', $zCreate, $zOld, $zNew, 0 )} } + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test without_rowid3-14.2.1.1 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} do_test without_rowid3-14.2.1.2 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3 } {{CREATE TABLE t1(a REFERENCES t2)}} do_test without_rowid3-14.2.1.3 { test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 # Test ALTER TABLE RENAME TABLE a bit. # do_test without_rowid3-14.2.2.1 { drop_all_tables @@ -1035,19 +1037,21 @@ PRAGMA foreign_keys = on; SELECT sql FROM temp.sqlite_master WHERE name='t2'; } } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test without_rowid3-14.2tmp.1.1 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} do_test without_rowid3-14.2tmp.1.2 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3 } {{CREATE TABLE t1(a REFERENCES t2)}} do_test without_rowid3-14.2tmp.1.3 { test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 # Test ALTER TABLE RENAME TABLE a bit. # do_test without_rowid3-14.2tmp.2.1 { drop_all_tables @@ -1120,19 +1124,21 @@ PRAGMA foreign_keys = on; SELECT sql FROM aux.sqlite_master WHERE name='t2'; } } {{CREATE TABLE t2(a, b, c REFERENCES t1, d DEFAULT NULL REFERENCES t1, e REFERENCES t1 DEFAULT NULL, h DEFAULT 'text' REFERENCES t1)}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 1 do_test without_rowid3-14.2aux.1.1 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} do_test without_rowid3-14.2aux.1.2 { test_rename_parent {CREATE TABLE t1(a REFERENCES t2)} t4 t3 } {{CREATE TABLE t1(a REFERENCES t2)}} do_test without_rowid3-14.2aux.1.3 { test_rename_parent {CREATE TABLE t1(a REFERENCES "t2")} t2 t3 } {{CREATE TABLE t1(a REFERENCES "t3")}} + sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 0 # Test ALTER TABLE RENAME TABLE a bit. # do_test without_rowid3-14.2aux.2.1 { drop_all_tables Index: tool/lempar.c ================================================================== --- tool/lempar.c +++ tool/lempar.c @@ -21,10 +21,11 @@ ** ** The following is the concatenation of all %include directives from the ** input grammar file: */ #include +#include /************ Begin %include sections from the grammar ************************/ %% /**************** End of %include directives **********************************/ /* These constants specify the various numeric values for terminal symbols ** in a format understandable to "makeheaders". This section is blank unless @@ -985,14 +986,13 @@ #endif yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion); yymajor = YYNOCODE; }else{ while( yypParser->yytos >= yypParser->yystack - && yymx != YYERRORSYMBOL && (yyact = yy_find_reduce_action( yypParser->yytos->stateno, - YYERRORSYMBOL)) >= YY_MIN_REDUCE + YYERRORSYMBOL)) > YY_MAX_SHIFTREDUCE ){ yy_pop_parser_stack(yypParser); } if( yypParser->yytos < yypParser->yystack || yymajor==0 ){ yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);