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. @@ -357,10 +358,13 @@ $(TOP)/ext/sqlrr/sqlrr.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 @@ -456,11 +460,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 \ @@ -562,10 +567,12 @@ $(TOP)/ext/rtree/geopoly.c EXTHDR += \ $(TOP)/ext/icu/sqliteicu.h EXTHDR += \ $(TOP)/ext/rtree/sqlite3rtree.h +EXTHDR += \ + $(TOP)/ext/userauth/sqlite3userauth.h EXTHDR += \ $(TOP)/ext/sqlrr/sqlrr.h # If using the amalgamation, use sqlite3.c directly to build the test # fixture. Otherwise link against libsqlite3.la. (This distinction is @@ -1129,11 +1136,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: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -542,21 +542,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. */ @@ -1892,10 +1897,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 @@ -1917,10 +1923,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/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/pager.c ================================================================== --- src/pager.c +++ src/pager.c @@ -847,23 +847,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 @@ -7078,12 +7065,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 @@ -177,22 +177,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/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -3632,11 +3632,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. ** */ 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/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 @@ -122,12 +122,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 @@ -134,24 +134,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 @@ -160,52 +164,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); @@ -224,6 +243,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: 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);