Index: VERSION ================================================================== --- VERSION +++ VERSION @@ -1,1 +1,1 @@ -3.30.0 +3.30.1 Index: configure ================================================================== --- configure +++ configure @@ -1,8 +1,8 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for sqlite 3.30.0. +# Generated by GNU Autoconf 2.69 for sqlite 3.30.1. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # @@ -724,12 +724,12 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' -PACKAGE_VERSION='3.30.0' -PACKAGE_STRING='sqlite 3.30.0' +PACKAGE_VERSION='3.30.1' +PACKAGE_STRING='sqlite 3.30.1' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ @@ -1464,11 +1464,11 @@ # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sqlite 3.30.0 to adapt to many kinds of systems. +\`configure' configures sqlite 3.30.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. @@ -1529,11 +1529,11 @@ _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sqlite 3.30.0:";; + short | recursive ) echo "Configuration of sqlite 3.30.1:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options @@ -1655,11 +1655,11 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sqlite configure 3.30.0 +sqlite configure 3.30.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. @@ -2074,11 +2074,11 @@ } # ac_fn_c_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sqlite $as_me 3.30.0, which was +It was created by sqlite $as_me 3.30.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF @@ -12230,11 +12230,11 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sqlite $as_me 3.30.0, which was +This file was extended by sqlite $as_me 3.30.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS @@ -12296,11 +12296,11 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sqlite config.status 3.30.0 +sqlite config.status 3.30.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation Index: ext/fts5/test/fts5misc.test ================================================================== --- ext/fts5/test/fts5misc.test +++ ext/fts5/test/fts5misc.test @@ -56,8 +56,56 @@ do_catchsql_test 1.3.3 { SELECT a FROM t1 WHERE rank = (SELECT highlight(t1, 4, '', '') FROM t1('*reads')); } {1 {no such cursor: 1}} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 2.0 { + CREATE TABLE t0(c0); + CREATE VIRTUAL TABLE vt0 USING fts5(c0); +} +do_execsql_test 2.1.1 { + BEGIN TRANSACTION; + INSERT INTO vt0(c0) VALUES ('xyz'); +} +do_execsql_test 2.1.2 { + ALTER TABLE t0 ADD COLUMN c5; +} +do_execsql_test 2.1.3 { + INSERT INTO vt0(vt0) VALUES('integrity-check'); +} +do_execsql_test 2.1.4 { + INSERT INTO vt0(c0) VALUES ('abc'); + COMMIT +} +do_execsql_test 2.1.5 { + INSERT INTO vt0(vt0) VALUES('integrity-check'); +} + +reset_db +do_execsql_test 2.2.1 { + CREATE TABLE t0(c0); + CREATE VIRTUAL TABLE vt0 USING fts5(c0); + BEGIN TRANSACTION; + INSERT INTO vt0(c0) VALUES ('xyz'); +} + +breakpoint +do_execsql_test 2.2.2 { + ALTER TABLE t0 RENAME TO t1; +} +do_execsql_test 2.2.3 { + INSERT INTO vt0(vt0) VALUES('integrity-check'); +} +do_execsql_test 2.2.4 { + INSERT INTO vt0(c0) VALUES ('abc'); + COMMIT; +} +do_execsql_test 2.2.5 { + INSERT INTO vt0(vt0) VALUES('integrity-check'); +} + finish_test Index: src/alter.c ================================================================== --- src/alter.c +++ src/alter.c @@ -433,10 +433,11 @@ } if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){ goto exit_begin_add_column; } + sqlite3MayAbort(pParse); assert( pTab->addColOffset>0 ); iDb = sqlite3SchemaToIndex(db, pTab->pSchema); /* Put a copy of the Table struct in Parse.pNewTable for the ** sqlite3AddColumn() function and friends to modify. But modify Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -5144,18 +5144,20 @@ case TK_IS: case TK_OR: case TK_CASE: case TK_IN: case TK_FUNCTION: + case TK_TRUTH: testcase( pExpr->op==TK_ISNOT ); testcase( pExpr->op==TK_ISNULL ); testcase( pExpr->op==TK_NOTNULL ); testcase( pExpr->op==TK_IS ); testcase( pExpr->op==TK_OR ); testcase( pExpr->op==TK_CASE ); testcase( pExpr->op==TK_IN ); testcase( pExpr->op==TK_FUNCTION ); + testcase( pExpr->op==TK_TRUTH ); return WRC_Prune; case TK_COLUMN: if( pWalker->u.iCur==pExpr->iTable ){ pWalker->eCode = 1; return WRC_Abort; Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -98,13 +98,13 @@ sqlite3ExprDelete(db, p->pLimit); #ifndef SQLITE_OMIT_WINDOWFUNC if( OK_IF_ALWAYS_TRUE(p->pWinDefn) ){ sqlite3WindowListDelete(db, p->pWinDefn); } -#endif - if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith); assert( p->pWin==0 ); +#endif + if( OK_IF_ALWAYS_TRUE(p->pWith) ) sqlite3WithDelete(db, p->pWith); if( bFree ) sqlite3DbFreeNN(db, p); p = pPrior; bFree = 1; } } @@ -3501,10 +3501,18 @@ if( ExprHasProperty(pExpr, EP_xIsSelect) ){ substSelect(pSubst, pExpr->x.pSelect, 1); }else{ substExprList(pSubst, pExpr->x.pList); } +#ifndef SQLITE_OMIT_WINDOWFUNC + if( ExprHasProperty(pExpr, EP_WinFunc) ){ + Window *pWin = pExpr->y.pWin; + pWin->pFilter = substExpr(pSubst, pWin->pFilter); + substExprList(pSubst, pWin->pPartition); + substExprList(pSubst, pWin->pOrderBy); + } +#endif } return pExpr; } static void substExprList( SubstContext *pSubst, /* Description of the substitution */ Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -2603,13 +2603,17 @@ /* ** True if the expression passed as an argument was a function with ** an OVER() clause (a window function). */ -#define IsWindowFunc(p) ( \ +#ifdef SQLITE_OMIT_WINDOWFUNC +# define IsWindowFunc(p) 0 +#else +# define IsWindowFunc(p) ( \ ExprHasProperty((p), EP_WinFunc) && p->y.pWin->eFrmType!=TK_FILTER \ -) + ) +#endif /* ** A list of expressions. Each expression may optionally have a ** name. An expr/name combination can be used in several ways, such ** as the list of "expr AS ID" fields following a "SELECT" or in the Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -4536,27 +4536,31 @@ u64 iKey; pIn3 = &aMem[pOp->p3]; testcase( pIn3->flags & MEM_Int ); testcase( pIn3->flags & MEM_IntReal ); + testcase( pIn3->flags & MEM_Real ); + testcase( (pIn3->flags & (MEM_Str|MEM_Int))==MEM_Str ); if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){ - /* Make sure pIn3->u.i contains a valid integer representation of - ** the key value, but do not change the datatype of the register, as - ** other parts of the perpared statement might be depending on the - ** current datatype. */ - u16 origFlags = pIn3->flags; - int isNotInt; - applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding); - isNotInt = (pIn3->flags & MEM_Int)==0; - pIn3->flags = origFlags; - if( isNotInt ) goto jump_to_p2; + /* If pIn3->u.i does not contain an integer, compute iKey as the + ** integer value of pIn3. Jump to P2 if pIn3 cannot be converted + ** into an integer without loss of information. Take care to avoid + ** changing the datatype of pIn3, however, as it is used by other + ** parts of the prepared statement. */ + Mem x = pIn3[0]; + applyAffinity(&x, SQLITE_AFF_NUMERIC, encoding); + if( (x.flags & MEM_Int)==0 ) goto jump_to_p2; + iKey = x.u.i; + goto notExistsWithKey; } /* Fall through into OP_NotExists */ case OP_NotExists: /* jump, in3 */ pIn3 = &aMem[pOp->p3]; assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid ); assert( pOp->p1>=0 && pOp->p1nCursor ); + iKey = pIn3->u.i; +notExistsWithKey: pC = p->apCsr[pOp->p1]; assert( pC!=0 ); #ifdef SQLITE_DEBUG if( pOp->opcode==OP_SeekRowid ) pC->seekOp = OP_SeekRowid; #endif @@ -4563,11 +4567,10 @@ assert( pC->isTable ); assert( pC->eCurType==CURTYPE_BTREE ); pCrsr = pC->uc.pCursor; assert( pCrsr!=0 ); res = 0; - iKey = pIn3->u.i; rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res); assert( rc==SQLITE_OK || res==0 ); pC->movetoTarget = iKey; /* Used by OP_Delete */ pC->nullRow = 0; pC->cacheStatus = CACHE_STALE; Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -640,11 +640,11 @@ while( (pOp = opIterNext(&sIter))!=0 ){ int opcode = pOp->opcode; if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename || opcode==OP_VDestroy - || (opcode==OP_Function0 && pOp->p4.pFunc->funcFlags&SQLITE_FUNC_INTERNAL) + || (opcode==OP_ParseSchema && pOp->p4.z==0) || ((opcode==OP_Halt || opcode==OP_HaltIfNull) && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort)) ){ hasAbort = 1; break; Index: test/filter1.test ================================================================== --- test/filter1.test +++ test/filter1.test @@ -161,8 +161,28 @@ SELECT a, avg(c) FILTER (WHERE b!=1) AS h FROM t1 GROUP BY a ORDER BY avg(c); } {c 2.0 a 10.0 b 5.0} do_execsql_test 4.4 { SELECT a, avg(c) FILTER (WHERE b!=1) FROM t1 GROUP BY a ORDER BY 2 } {c 2.0 b 5.0 a 10.0} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 5.0 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES(1, 3); +} + +do_execsql_test 5.1 { + SELECT count(*) FILTER (WHERE b>2) FROM (SELECT * FROM t1) +} {1} + +do_execsql_test 5.2 { + SELECT count(*) FILTER (WHERE b>2) OVER () FROM (SELECT * FROM t1) +} {1 1} + +do_execsql_test 5.3 { + SELECT count(*) FILTER (WHERE b>2) OVER (ORDER BY b) FROM (SELECT * FROM t1) +} {0 1} finish_test Index: test/join.test ================================================================== --- test/join.test +++ test/join.test @@ -881,7 +881,29 @@ } {1 1 1 1} do_execsql_test join-17.110 { SELECT * FROM t1 LEFT JOIN (SELECT abs(1)+2 AS y FROM t1) ON x WHERE NOT(y='a'); } {1 3 1 3} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test join-18.1 { + CREATE TABLE t0(a); + CREATE TABLE t1(b); + CREATE VIEW v0 AS SELECT a FROM t1 LEFT JOIN t0; + INSERT INTO t1 VALUES (1); +} {} + +do_execsql_test join-18.2 { + SELECT * FROM v0 WHERE NOT(v0.a IS FALSE); +} {{}} + +do_execsql_test join-18.3 { + SELECT * FROM t1 LEFT JOIN t0 WHERE NOT(a IS FALSE); +} {1 {}} + +do_execsql_test join-18.4 { + SELECT NOT(v0.a IS FALSE) FROM v0 +} {1} finish_test + Index: test/window1.test ================================================================== --- test/window1.test +++ test/window1.test @@ -1187,7 +1187,51 @@ WINDOW win1 AS (ORDER BY a GROUPS BETWEEN 4 PRECEDING AND 1 FOLLOWING EXCLUDE CURRENT ROW), win2 AS (PARTITION BY b ORDER BY a), win3 AS (win2 RANGE BETWEEN 5.2 PRECEDING AND true PRECEDING ); } {1 1} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 31.1 { + CREATE TABLE t1(a, b); + CREATE TABLE t2(c, d); + CREATE TABLE t3(e, f); + + INSERT INTO t1 VALUES(1, 1); + INSERT INTO t2 VALUES(1, 1); + INSERT INTO t3 VALUES(1, 1); +} + +do_execsql_test 31.2 { + SELECT d IN (SELECT sum(c) OVER (ORDER BY e+c) FROM t3) FROM ( + SELECT * FROM t2 + ); +} {1} + +do_execsql_test 31.3 { + SELECT d IN (SELECT sum(c) OVER (PARTITION BY d ORDER BY e+c) FROM t3) FROM ( + SELECT * FROM t2 + ); +} {1} + +do_catchsql_test 31.3 { + SELECT d IN ( + SELECT sum(c) OVER ( ROWS BETWEEN d FOLLOWING AND UNBOUNDED FOLLOWING) + FROM t3 + ) + FROM ( + SELECT * FROM t2 + ); +} {1 {frame starting offset must be a non-negative integer}} + +do_catchsql_test 31.3 { + SELECT d IN ( + SELECT sum(c) OVER ( ROWS BETWEEN CURRENT ROW AND c FOLLOWING) + FROM t3 + ) + FROM ( + SELECT * FROM t2 + ); +} {1 {frame ending offset must be a non-negative integer}} finish_test