diff --git a/Makefile.in b/Makefile.in index 7fe047b5dc..5981b912cb 100644 --- a/Makefile.in +++ b/Makefile.in @@ -611,7 +611,6 @@ SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC SHELL_OPT += -DSQLITE_ENABLE_DESERIALIZE -SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000 diff --git a/Makefile.linux-gcc b/Makefile.linux-gcc index 1491a4b02a..ad5d4dd093 100644 --- a/Makefile.linux-gcc +++ b/Makefile.linux-gcc @@ -19,7 +19,7 @@ TOP = ../sqlite #### C Compiler and options for use in building executables that # will run on the platform that is doing the build. # -BCC = gcc -g -O2 +BCC = gcc -g -O0 #BCC = /opt/ancic/bin/c89 -0 #### If the target operating system supports the "usleep()" system @@ -38,8 +38,8 @@ THREADSAFE = -DTHREADSAFE=0 #### Specify any extra linker options needed to make the library # thread safe # -#THREADLIB = -lpthread -THREADLIB = +THREADLIB = -lpthread -lm -ldl +#THREADLIB = #### Specify any extra libraries needed to access required functions. # @@ -54,11 +54,9 @@ TLIBS = # You can make the library go almost twice as fast if you compile # with -DNDEBUG=1 # -#OPTS = -DSQLITE_DEBUG=2 -#OPTS = -DSQLITE_DEBUG=1 -#OPTS = -OPTS = -DNDEBUG=1 -OPTS += -DHAVE_FDATASYNC=1 +OPTS += -DSQLITE_DEBUG=1 +OPTS += -DSQLITE_ENABLE_WHERETRACE +OPTS += -DSQLITE_ENABLE_SELECTTRACE #### The suffix to add to executable files. ".exe" for windows. # Nothing for unix. @@ -70,7 +68,7 @@ EXE = # will run on the target platform. This is usually the same # as BCC, unless you are cross-compiling. # -TCC = gcc -O6 +TCC = gcc -O0 #TCC = gcc -g -O0 -Wall #TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage #TCC = /opt/mingw/bin/i386-mingw32-gcc -O6 @@ -91,18 +89,12 @@ SHPREFIX = lib #### Extra compiler options needed for programs that use the TCL library. # -#TCL_FLAGS = -#TCL_FLAGS = -DSTATIC_BUILD=1 -TCL_FLAGS = -I/home/drh/tcltk/8.5linux -#TCL_FLAGS = -I/home/drh/tcltk/8.5win -DSTATIC_BUILD=1 -#TCL_FLAGS = -I/home/drh/tcltk/8.3hpux +TCL_FLAGS = -I/home/drh/tcl/include/tcl8.6 #### Linker options needed to link against the TCL library. # #LIBTCL = -ltcl -lm -ldl -LIBTCL = /home/drh/tcltk/8.5linux/libtcl8.5g.a -lm -ldl -#LIBTCL = /home/drh/tcltk/8.5win/libtcl85s.a -lmsvcrt -#LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc +LIBTCL = /home/drh/tcl/lib/libtcl8.6.a -lm -lpthread -ldl -lz #### Additional objects for SQLite library when TCL support is enabled. #TCLOBJ = diff --git a/Makefile.msc b/Makefile.msc index ddb2ff79b2..ec99b97f99 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -351,7 +351,6 @@ 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 diff --git a/ext/expert/expert1.test b/ext/expert/expert1.test index 912c074c60..a0a18f6374 100644 --- a/ext/expert/expert1.test +++ b/ext/expert/expert1.test @@ -134,6 +134,7 @@ do_setup_rec_test $tn.5 { SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?) } +if 0 { do_setup_rec_test $tn.6 { CREATE TABLE t1(a, b, c); } { @@ -142,6 +143,7 @@ do_setup_rec_test $tn.6 { CREATE INDEX t1_idx_00000061 ON t1(a); SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061 } +} do_setup_rec_test $tn.7 { CREATE TABLE t1(a, b, c); diff --git a/ext/fts3/fts3_snippet.c b/ext/fts3/fts3_snippet.c index d5ebda6a05..6db3fd7d96 100644 --- a/ext/fts3/fts3_snippet.c +++ b/ext/fts3/fts3_snippet.c @@ -433,10 +433,10 @@ static void fts3SnippetDetails( while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){ int j; - u64 mPhrase = (u64)1 << i; + u64 mPhrase = (u64)1 << (i%64); u64 mPos = (u64)1 << (iCsr - iStart); assert( iCsr>=iStart && (iCsr - iStart)<=64 ); - assert( i>=0 && i<=64 ); + assert( i>=0 ); if( (mCover|mCovered)&mPhrase ){ iScore++; }else{ diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index d0bb543e4c..c29b42b7ad 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -695,6 +695,7 @@ int sqlite3Fts5ExprEof(Fts5Expr*); i64 sqlite3Fts5ExprRowid(Fts5Expr*); void sqlite3Fts5ExprFree(Fts5Expr*); +int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2); /* Called during startup to register a UDF with SQLite */ int sqlite3Fts5ExprInit(Fts5Global*, sqlite3*); diff --git a/ext/fts5/fts5_config.c b/ext/fts5/fts5_config.c index 7a16e38c93..4e1707b3f4 100644 --- a/ext/fts5/fts5_config.c +++ b/ext/fts5/fts5_config.c @@ -683,7 +683,7 @@ int sqlite3Fts5ConfigDeclareVtab(Fts5Config *pConfig){ rc = sqlite3_declare_vtab(pConfig->db, zSql); sqlite3_free(zSql); } - + return rc; } diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index f1bf3f2abc..ce462af0f0 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -309,6 +309,42 @@ void sqlite3Fts5ExprFree(Fts5Expr *p){ } } +int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){ + Fts5Parse sParse; + memset(&sParse, 0, sizeof(sParse)); + + if( *pp1 ){ + Fts5Expr *p1 = *pp1; + int nPhrase = p1->nPhrase + p2->nPhrase; + + p1->pRoot = sqlite3Fts5ParseNode(&sParse, FTS5_AND, p1->pRoot, p2->pRoot,0); + p2->pRoot = 0; + + if( sParse.rc==SQLITE_OK ){ + Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc( + p1->apExprPhrase, nPhrase * sizeof(Fts5ExprPhrase*) + ); + if( ap==0 ){ + sParse.rc = SQLITE_NOMEM; + }else{ + int i; + memmove(&ap[p2->nPhrase], ap, p1->nPhrase*sizeof(Fts5ExprPhrase*)); + for(i=0; inPhrase; i++){ + ap[i] = p2->apExprPhrase[i]; + } + p1->nPhrase = nPhrase; + p1->apExprPhrase = ap; + } + } + sqlite3_free(p2->apExprPhrase); + sqlite3_free(p2); + }else{ + *pp1 = p2; + } + + return sParse.rc; +} + /* ** Argument pTerm must be a synonym iterator. Return the current rowid ** that it points to. diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c index 000ce98033..c0f7ac551a 100644 --- a/ext/fts5/fts5_index.c +++ b/ext/fts5/fts5_index.c @@ -4997,9 +4997,12 @@ static void fts5MergePrefixLists( Fts5PoslistWriter writer; memset(&writer, 0, sizeof(writer)); + /* See the earlier comment in this function for an explanation of why + ** corrupt input position lists might cause the output to consume + ** at most 20 bytes of unexpected space. */ fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid); fts5BufferZero(&tmp); - sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist); + sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist + 10 + 10); if( p->rc ) break; sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1); @@ -5047,6 +5050,12 @@ static void fts5MergePrefixLists( } /* WRITEPOSLISTSIZE */ + assert_nc( tmp.n<=i1.nPoslist+i2.nPoslist ); + assert( tmp.n<=i1.nPoslist+i2.nPoslist+10+10 ); + if( tmp.n>i1.nPoslist+i2.nPoslist ){ + if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT; + break; + } fts5BufferSafeAppendVarint(&out, tmp.n * 2); fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n); fts5DoclistIterNext(&i1); diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c index d44e95942c..fc4ec0c482 100644 --- a/ext/fts5/fts5_main.c +++ b/ext/fts5/fts5_main.c @@ -465,17 +465,39 @@ static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){ ** Implementation of the xBestIndex method for FTS5 tables. Within the ** WHERE constraint, it searches for the following: ** -** 1. A MATCH constraint against the special column. +** 1. A MATCH constraint against the table column. ** 2. A MATCH constraint against the "rank" column. -** 3. An == constraint against the rowid column. -** 4. A < or <= constraint against the rowid column. -** 5. A > or >= constraint against the rowid column. +** 3. A MATCH constraint against some other column. +** 4. An == constraint against the rowid column. +** 5. A < or <= constraint against the rowid column. +** 6. A > or >= constraint against the rowid column. ** -** Within the ORDER BY, either: +** Within the ORDER BY, the following are supported: ** ** 5. ORDER BY rank [ASC|DESC] ** 6. ORDER BY rowid [ASC|DESC] ** +** Information for the xFilter call is passed via both the idxNum and +** idxStr variables. Specifically, idxNum is a bitmask of the following +** flags used to encode the ORDER BY clause: +** +** FTS5_BI_ORDER_RANK +** FTS5_BI_ORDER_ROWID +** FTS5_BI_ORDER_DESC +** +** idxStr is used to encode data from the WHERE clause. For each argument +** passed to the xFilter method, the following is appended to idxStr: +** +** Match against table column: "m" +** Match against rank column: "r" +** Match against other column: "" +** Equality constraint against the rowid: "=" +** A < or <= against the rowid: "<" +** A > or >= against the rowid: ">" +** +** This function ensures that there is at most one "r" or "=". And that if +** there exists an "=" then there is no "<" or ">". +** ** Costs are assigned as follows: ** ** a) If an unusable MATCH operator is present in the WHERE clause, the @@ -503,32 +525,18 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ Fts5Config *pConfig = pTab->pConfig; const int nCol = pConfig->nCol; int idxFlags = 0; /* Parameter passed through to xFilter() */ - int bHasMatch; - int iNext; int i; - struct Constraint { - int op; /* Mask against sqlite3_index_constraint.op */ - int fts5op; /* FTS5 mask for idxFlags */ - int iCol; /* 0==rowid, 1==tbl, 2==rank */ - int omit; /* True to omit this if found */ - int iConsIndex; /* Index in pInfo->aConstraint[] */ - } aConstraint[] = { - {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ, - FTS5_BI_MATCH, 1, 1, -1}, - {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ, - FTS5_BI_RANK, 2, 1, -1}, - {SQLITE_INDEX_CONSTRAINT_EQ, FTS5_BI_ROWID_EQ, 0, 0, -1}, - {SQLITE_INDEX_CONSTRAINT_LT|SQLITE_INDEX_CONSTRAINT_LE, - FTS5_BI_ROWID_LE, 0, 0, -1}, - {SQLITE_INDEX_CONSTRAINT_GT|SQLITE_INDEX_CONSTRAINT_GE, - FTS5_BI_ROWID_GE, 0, 0, -1}, - }; + char *idxStr; + int iIdxStr = 0; + int iCons = 0; + + int bSeenEq = 0; + int bSeenGt = 0; + int bSeenLt = 0; + int bSeenMatch = 0; + int bSeenRank = 0; - int aColMap[3]; - aColMap[0] = -1; - aColMap[1] = nCol; - aColMap[2] = nCol+1; assert( SQLITE_INDEX_CONSTRAINT_EQnConstraint * 6 + 1); + if( idxStr==0 ) return SQLITE_NOMEM; + pInfo->idxStr = idxStr; + pInfo->needToFreeIdxStr = 1; + for(i=0; inConstraint; i++){ struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; int iCol = p->iColumn; - - if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol) - || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol) + if( p->op==SQLITE_INDEX_CONSTRAINT_MATCH + || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol>=nCol) ){ /* A MATCH operator or equivalent */ - if( p->usable ){ - idxFlags = (idxFlags & 0xFFFF) | FTS5_BI_MATCH | (iCol << 16); - aConstraint[0].iConsIndex = i; - }else{ + if( p->usable==0 || iCol<0 ){ /* As there exists an unusable MATCH constraint this is an ** unusable plan. Set a prohibitively high cost. */ pInfo->estimatedCost = 1e50; + assert( iIdxStr < pInfo->nConstraint*6 + 1 ); + idxStr[iIdxStr] = 0; return SQLITE_OK; + }else{ + if( iCol==nCol+1 ){ + if( bSeenRank ) continue; + idxStr[iIdxStr++] = 'r'; + bSeenRank = 1; + }else{ + bSeenMatch = 1; + idxStr[iIdxStr++] = 'm'; + if( iColaConstraintUsage[i].argvIndex = ++iCons; + pInfo->aConstraintUsage[i].omit = 1; } - }else if( p->op<=SQLITE_INDEX_CONSTRAINT_MATCH ){ - int j; - for(j=1; jiCol] && (p->op & pC->op) && p->usable ){ - pC->iConsIndex = i; - idxFlags |= pC->fts5op; + } + else if( p->usable && bSeenEq==0 + && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0 + ){ + idxStr[iIdxStr++] = '='; + bSeenEq = 1; + pInfo->aConstraintUsage[i].argvIndex = ++iCons; + } + } + + if( bSeenEq==0 ){ + for(i=0; inConstraint; i++){ + struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; + if( p->iColumn<0 && p->usable ){ + int op = p->op; + if( op==SQLITE_INDEX_CONSTRAINT_LT || op==SQLITE_INDEX_CONSTRAINT_LE ){ + if( bSeenLt ) continue; + idxStr[iIdxStr++] = '<'; + pInfo->aConstraintUsage[i].argvIndex = ++iCons; + bSeenLt = 1; + }else + if( op==SQLITE_INDEX_CONSTRAINT_GT || op==SQLITE_INDEX_CONSTRAINT_GE ){ + if( bSeenGt ) continue; + idxStr[iIdxStr++] = '>'; + pInfo->aConstraintUsage[i].argvIndex = ++iCons; + bSeenGt = 1; } } } } + idxStr[iIdxStr] = '\0'; /* Set idxFlags flags for the ORDER BY clause */ if( pInfo->nOrderBy==1 ){ int iSort = pInfo->aOrderBy[0].iColumn; - if( iSort==(pConfig->nCol+1) && BitFlagTest(idxFlags, FTS5_BI_MATCH) ){ + if( iSort==(pConfig->nCol+1) && bSeenMatch ){ idxFlags |= FTS5_BI_ORDER_RANK; }else if( iSort==-1 ){ idxFlags |= FTS5_BI_ORDER_ROWID; @@ -590,26 +636,15 @@ static int fts5BestIndexMethod(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){ } /* Calculate the estimated cost based on the flags set in idxFlags. */ - bHasMatch = BitFlagTest(idxFlags, FTS5_BI_MATCH); - if( BitFlagTest(idxFlags, FTS5_BI_ROWID_EQ) ){ - pInfo->estimatedCost = bHasMatch ? 100.0 : 10.0; - if( bHasMatch==0 ) fts5SetUniqueFlag(pInfo); - }else if( BitFlagAllTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){ - pInfo->estimatedCost = bHasMatch ? 500.0 : 250000.0; - }else if( BitFlagTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){ - pInfo->estimatedCost = bHasMatch ? 750.0 : 750000.0; + if( bSeenEq ){ + pInfo->estimatedCost = bSeenMatch ? 100.0 : 10.0; + if( bSeenMatch==0 ) fts5SetUniqueFlag(pInfo); + }else if( bSeenLt && bSeenGt ){ + pInfo->estimatedCost = bSeenMatch ? 500.0 : 250000.0; + }else if( bSeenLt || bSeenGt ){ + pInfo->estimatedCost = bSeenMatch ? 750.0 : 750000.0; }else{ - pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0; - } - - /* Assign argvIndex values to each constraint in use. */ - iNext = 1; - for(i=0; iiConsIndex>=0 ){ - pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++; - pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit; - } + pInfo->estimatedCost = bSeenMatch ? 1000.0 : 1000000.0; } pInfo->idxNum = idxFlags; @@ -932,7 +967,7 @@ static int fts5CursorFirstSorted( ** ** If SQLite a built-in statement cache, this wouldn't be a problem. */ rc = fts5PrepareStatement(&pSorter->pStmt, pConfig, - "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s", + "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(\"%w\"%s%s) %s", pConfig->zDb, pConfig->zName, zRank, pConfig->zName, (zRankArgs ? ", " : ""), (zRankArgs ? zRankArgs : ""), @@ -988,10 +1023,10 @@ static int fts5SpecialMatch( assert( pTab->p.base.zErrMsg==0 ); pCsr->ePlan = FTS5_PLAN_SPECIAL; - if( 0==sqlite3_strnicmp("reads", z, n) ){ + if( n==5 && 0==sqlite3_strnicmp("reads", z, n) ){ pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->p.pIndex); } - else if( 0==sqlite3_strnicmp("id", z, n) ){ + else if( n==2 && 0==sqlite3_strnicmp("id", z, n) ){ pCsr->iSpecial = pCsr->iCsrId; } else{ @@ -1132,7 +1167,7 @@ static i64 fts5GetRowidLimit(sqlite3_value *pVal, i64 iDefault){ static int fts5FilterMethod( sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */ int idxNum, /* Strategy index */ - const char *zUnused, /* Unused */ + const char *idxStr, /* Unused */ int nVal, /* Number of elements in apVal */ sqlite3_value **apVal /* Arguments for the indexing scheme */ ){ @@ -1140,19 +1175,17 @@ static int fts5FilterMethod( Fts5Config *pConfig = pTab->p.pConfig; Fts5Cursor *pCsr = (Fts5Cursor*)pCursor; int rc = SQLITE_OK; /* Error code */ - int iVal = 0; /* Counter for apVal[] */ int bDesc; /* True if ORDER BY [rank|rowid] DESC */ int bOrderByRank; /* True if ORDER BY rank */ - sqlite3_value *pMatch = 0; /* MATCH ? expression (or NULL) */ sqlite3_value *pRank = 0; /* rank MATCH ? expression (or NULL) */ sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */ sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */ sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */ int iCol; /* Column on LHS of MATCH operator */ char **pzErrmsg = pConfig->pzErrmsg; - - UNUSED_PARAM(zUnused); - UNUSED_PARAM(nVal); + int i; + int iIdxStr = 0; + Fts5Expr *pExpr = 0; if( pCsr->ePlan ){ fts5FreeCursorComponents(pCsr); @@ -1165,23 +1198,60 @@ static int fts5FilterMethod( assert( pCsr->pRank==0 ); assert( pCsr->zRank==0 ); assert( pCsr->zRankArgs==0 ); + assert( pTab->pSortCsr==0 || nVal==0 ); assert( pzErrmsg==0 || pzErrmsg==&pTab->p.base.zErrMsg ); pConfig->pzErrmsg = &pTab->p.base.zErrMsg; - /* Decode the arguments passed through to this function. - ** - ** Note: The following set of if(...) statements must be in the same - ** order as the corresponding entries in the struct at the top of - ** fts5BestIndexMethod(). */ - if( BitFlagTest(idxNum, FTS5_BI_MATCH) ) pMatch = apVal[iVal++]; - if( BitFlagTest(idxNum, FTS5_BI_RANK) ) pRank = apVal[iVal++]; - if( BitFlagTest(idxNum, FTS5_BI_ROWID_EQ) ) pRowidEq = apVal[iVal++]; - if( BitFlagTest(idxNum, FTS5_BI_ROWID_LE) ) pRowidLe = apVal[iVal++]; - if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++]; - iCol = (idxNum>>16); - assert( iCol>=0 && iCol<=pConfig->nCol ); - assert( iVal==nVal ); + /* Decode the arguments passed through to this function. */ + for(i=0; i='0' && idxStr[iIdxStr]<='9' ){ + iCol = 0; + do{ + iCol = iCol*10 + (idxStr[iIdxStr]-'0'); + iIdxStr++; + }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' ); + }else{ + iCol = pConfig->nCol; + } + + if( zText[0]=='*' ){ + /* The user has issued a query of the form "MATCH '*...'". This + ** indicates that the MATCH expression is not a full text query, + ** but a request for an internal parameter. */ + rc = fts5SpecialMatch(pTab, pCsr, &zText[1]); + goto filter_out; + }else{ + char **pzErr = &pTab->p.base.zErrMsg; + rc = sqlite3Fts5ExprNew(pConfig, iCol, zText, &pExpr, pzErr); + if( rc==SQLITE_OK ){ + rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr); + pExpr = 0; + } + if( rc!=SQLITE_OK ) goto filter_out; + } + + break; + } + case '=': + pRowidEq = apVal[i]; + break; + case '<': + pRowidLe = apVal[i]; + break; + default: assert( idxStr[iIdxStr-1]=='>' ); + pRowidGe = apVal[i]; + break; + } + } bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0); pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0); @@ -1208,7 +1278,7 @@ static int fts5FilterMethod( ** (pCursor) is used to execute the query issued by function ** fts5CursorFirstSorted() above. */ assert( pRowidEq==0 && pRowidLe==0 && pRowidGe==0 && pRank==0 ); - assert( nVal==0 && pMatch==0 && bOrderByRank==0 && bDesc==0 ); + assert( nVal==0 && bOrderByRank==0 && bDesc==0 ); assert( pCsr->iLastRowid==LARGEST_INT64 ); assert( pCsr->iFirstRowid==SMALLEST_INT64 ); if( pTab->pSortCsr->bDesc ){ @@ -1221,29 +1291,15 @@ static int fts5FilterMethod( pCsr->ePlan = FTS5_PLAN_SOURCE; pCsr->pExpr = pTab->pSortCsr->pExpr; rc = fts5CursorFirst(pTab, pCsr, bDesc); - }else if( pMatch ){ - const char *zExpr = (const char*)sqlite3_value_text(apVal[0]); - if( zExpr==0 ) zExpr = ""; - + }else if( pCsr->pExpr ){ rc = fts5CursorParseRank(pConfig, pCsr, pRank); if( rc==SQLITE_OK ){ - if( zExpr[0]=='*' ){ - /* The user has issued a query of the form "MATCH '*...'". This - ** indicates that the MATCH expression is not a full text query, - ** but a request for an internal parameter. */ - rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]); + if( bOrderByRank ){ + pCsr->ePlan = FTS5_PLAN_SORTED_MATCH; + rc = fts5CursorFirstSorted(pTab, pCsr, bDesc); }else{ - char **pzErr = &pTab->p.base.zErrMsg; - rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr); - if( rc==SQLITE_OK ){ - if( bOrderByRank ){ - pCsr->ePlan = FTS5_PLAN_SORTED_MATCH; - rc = fts5CursorFirstSorted(pTab, pCsr, bDesc); - }else{ - pCsr->ePlan = FTS5_PLAN_MATCH; - rc = fts5CursorFirst(pTab, pCsr, bDesc); - } - } + pCsr->ePlan = FTS5_PLAN_MATCH; + rc = fts5CursorFirst(pTab, pCsr, bDesc); } } }else if( pConfig->zContent==0 ){ @@ -1260,7 +1316,7 @@ static int fts5FilterMethod( ); if( rc==SQLITE_OK ){ if( pCsr->ePlan==FTS5_PLAN_ROWID ){ - sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]); + sqlite3_bind_value(pCsr->pStmt, 1, pRowidEq); }else{ sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid); sqlite3_bind_int64(pCsr->pStmt, 2, pCsr->iLastRowid); @@ -1269,6 +1325,8 @@ static int fts5FilterMethod( } } + filter_out: + sqlite3Fts5ExprFree(pExpr); pConfig->pzErrmsg = pzErrmsg; return rc; } @@ -2239,7 +2297,7 @@ static void fts5ApiCallback( iCsrId = sqlite3_value_int64(argv[0]); pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId); - if( pCsr==0 ){ + if( pCsr==0 || pCsr->ePlan==0 ){ char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId); sqlite3_result_error(context, zErr, -1); sqlite3_free(zErr); diff --git a/ext/fts5/test/fts5corrupt3.test b/ext/fts5/test/fts5corrupt3.test index 0497c95bcf..a7da137b11 100644 --- a/ext/fts5/test/fts5corrupt3.test +++ b/ext/fts5/test/fts5corrupt3.test @@ -767,7 +767,7 @@ SELECT * FROM t1 WHERE t1 MATCH 'abandon'; do_catchsql_test 13.1 { SELECT * FROM t1 WHERE t1 MATCH 'abandon'; -} {1 {vtable constructor failed: t1}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -958,7 +958,7 @@ do_test 15.0 { do_catchsql_test 15.1 { INSERT INTO t1(t1) VALUES('integrity-check'); -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #--------------------------------------------------------------------------- # @@ -3903,19 +3903,19 @@ do_test 33.0 { | end crash-fed6e90021ba5d.db }]} {} -do_execsql_test 33.1 { +do_catchsql_test 33.1 { CREATE VIRTUAL TABLE t2 USING fts5vocab('t1','row'); CREATE VIRTUAL TABLE t3 USING fts5vocab('t1','col'); CREATE VIRTUAL TABLE t4 USING fts5vocab('t1','instance'); -} +} {/*malformed database schema*/} do_catchsql_test 33.2 { SELECT * FROM t2; -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} do_catchsql_test 33.3 { SELECT * FROM t2, t3, t4 WHERE t2.term=t3.term AND t3.term=t4.term; -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -4637,17 +4637,17 @@ do_test 37.0 { do_catchsql_test 37.1 { SELECT * FROM t3; -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db -do_execsql_test 37.0 { +do_execsql_test 37a.0 { CREATE VIRTUAL TABLE t1 USING fts5(b, c); INSERT INTO t1 VALUES('a', 'b'); SELECT quote(block) FROM t1_data WHERE rowid=10; } {X'000000000101010001010101'} -do_execsql_test 37.1 { +do_execsql_test 37a.1 { UPDATE t1_data SET block = X'FFFFFFFF0101010001010101' WHERE rowid = 10; SELECT rowid FROM t1('a'); } {1} @@ -4894,7 +4894,7 @@ do_test 38.0 { do_catchsql_test 38.1 { UPDATE t1 SET b=quote(zeroblob(200)) WHERE t1 MATCH 'thread*'; -} {0 {}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -5326,16 +5326,16 @@ do_test 40.0 { | end crash2.txt.db }]} {} -do_execsql_test 40.1 { +do_catchsql_test 40.1 { BEGIN; INSERT INTO t1(b) VALUES(X'819192e578de3fa24af3733ca8769291a0fee3669f9fddefc5cba913e4225d4b6ce2b04f26b87fad3ee6f9b7d90a1ea62a169bf41e5d32707a6ca5c3d05e4bde05c9d89eaaa8c50e74333d2e9fcd7dfe95528a3a016aac1102d825c5cd70cf99d8a88e0ea7f798d4334386518b7ad359beb168b93aba059a2a3bd93112d65b44c12b9904ea786b204d80531cdf0504bf9b203dbe927061974caf7b9f30cbc3397b61f802e732012a6663d41c3607d6f1c0dbcfd489adac05ca500c0b04439d894cd93a840159225ef73b627e178b9f84b3ffe66cf22a963a8368813ff7961fc47f573211ccec95e0220dcbb3bf429f4a50ba54d7a53784ac51bf'); INSERT INTO t1(b) VALUES(X'c8ae0d0e7c3175946e62ba2b449511d4eb504079984a20f77969f62206c9f3d7ea25358ab705e6978627290b6d48db9032f815a06a79a4f4b809841a0942eed12954ed166f666111812a508abc3bec87958846edaec0a6fe14564bc0a4b78f1c35ebcacca6bae29cc37ae9b59d8a2d7593af1e47dda0ece2268a98d20febafad037964f139851f9a57f48b3706b01721769071991412044cd6006f1d72eb6eb4aa5ad77e378176db8c15575fbeee47165e38a7c6c5a557ac2dfe11813976eaf6741cf593a9e457053a3c34cddfbe605a6e25419f993de8374fafcd3636509d8416a51dc7bcc14cfca322ae343078f47e23522431c17d0da0c033'); INSERT INTO t1(b) VALUES(X'dc29a94e873a45a4243fce9b912aaefbadf1d0423e0345793874b356eeb500b92fb05284c1601fe9bad3143f72162f10242cec27c44ebf764c8fc9fb0824e32c4161472a4f914f579e0e8274f08ca1a02e59b9d8eec1f31061f9ccb9ed97a6f06534e991f7992c761489e6a7724f6e9c2b581e77487ded3a986d53c4419bbd3e9747cee300e670dd7294874c77e2ed48da68eaa6c3ec954a09ac410493d98e34d6686e54fbbe80696705f10e040c66093efb40746b33600685c94c664c7942835a9e954866121d5dcfb2cb12e92521ea3df175ee17072502dad9b9c1565f801b2179799011eb7418bfa00323e3157589e648ff7378be233c79b7'); -} +} {/*malformed database schema*/} do_catchsql_test 40.2 { INSERT INTO t1(a,b) VALUES(1,11),(2,22),(3, true ),(4,44); -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -5789,7 +5789,7 @@ do_test 43.0 { do_catchsql_test 43.1 { INSERT INTO t1(t1) VALUES('optimize'); -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -6047,7 +6047,7 @@ do_catchsql_test 45.2 { INSERT INTO t1(t1, rank) VALUES('merge', 5); INSERT INTO t1(t1, rank) VALUES('merge', 5); INSERT INTO t1(t1, rank) VALUES('merge', 5); -} {0 {}} +} {/*malformed database schema*/} #-------------------------------------------------------------------------- reset_db @@ -6265,7 +6265,7 @@ do_test 46.0 { do_catchsql_test 46.1 { SELECT snippet(t1,'[','', '--',-1,10) FROM t1('*'); -} {0 {{}}} +} {/*malformed database schema*/} #-------------------------------------------------------------------------- reset_db @@ -6418,7 +6418,7 @@ do_test 47.0 { do_catchsql_test 47.1 { INSERT INTO t1(t1) VALUES('integrity-check'); -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} do_catchsql_test 47.2 { SELECT count(*) FROM ( @@ -6426,7 +6426,7 @@ do_catchsql_test 47.2 { highlight(t1, 2, '[', ']') FROM t1('g h') WHERE rank MATCH 'bm25(1.0, 1.0)' ORDER BY rank ) -} {0 3} +} {/*malformed database schema*/} #-------------------------------------------------------------------------- reset_db @@ -6908,7 +6908,7 @@ do_catchsql_test 50.1 { #------------------------------------------------------------------------- reset_db -do_execsql_test 51.1 { +do_execsql_test 51.0 { BEGIN TRANSACTION; PRAGMA writable_schema=ON; CREATE VIRTUAL TABLE t1 USING fts5(a,b,c); @@ -6976,7 +6976,7 @@ COMMIT; do_catchsql_test 51.1 { SELECT max(rowid)==0 FROM t1('e*'); -} {0 0} +} {1 {database disk image is malformed}} #-------------------------------------------------------------------------- reset_db @@ -7130,7 +7130,7 @@ do_test 52.0 { do_catchsql_test 52.1 { SELECT fts5_decode(id, block) FROM t1_data; -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -7346,7 +7346,7 @@ do_test 53.0 { do_catchsql_test 53.1 { WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x<>1 FROM c WHERE x<10) INSERT INTO t1(a) SELECT randomblob(3000) FROM c; -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -7562,7 +7562,7 @@ do_test 54.0 { do_catchsql_test 54.1 { SELECT rowid==-1 FROM t1('t*'); -} {0 {0 0 0}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -7777,10 +7777,10 @@ do_test 55.0 { | end crash-b366b5ac0d3887.db }]} {} -do_execsql_test 55.1 { +do_catchsql_test 55.1 { SAVEPOINT one; DELETE FROM t1 WHERE a MATCH 'ts'; -} +} {/*malformed database schema*/} do_execsql_test 55.2 { ROLLBACK TO one; @@ -8013,7 +8013,7 @@ do_test 56.1 { set res "1 {database disk image is malformed}" } set res -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -8131,7 +8131,7 @@ do_test 57.0 { do_catchsql_test 57.1 { INSERT INTO t1(t1) VALUES('optimize') -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- reset_db @@ -8339,9 +8339,9 @@ do_test 58.0 { | end crash-5a5acd0ab42d31.db }]} {} -do_execsql_test 58.1 { +do_catchsql_test 58.1 { SELECT * FROM t1('t*'); -} {{} {} {} {} {} {}} +} {/*malformed database schema*/} #------------------------------------------------------------------------- do_test 59.0 { @@ -8544,7 +8544,7 @@ do_test 59.0 { do_catchsql_test 59.1 { SELECT (matchinfo(591,t1)) FROM t1 WHERE t1 MATCH 'e*eŸ' -} {0 {}} +} {1 {database disk image is malformed}} #------------------------------------------------------------------------- do_test 60.0 { @@ -8750,7 +8750,7 @@ do_test 60.0 { do_catchsql_test 60.2 { SELECT (matchinfo(t1,591)) FROM t1 WHERE t1 MATCH 'e*eŸ' -} {0 {}} +} {1 {database disk image is malformed}} #------------------------------------------------------------------------- do_test 61.0 { @@ -8948,13 +8948,13 @@ do_test 61.0 { | end crash-e5fa281edabddf.db }]} {} -do_execsql_test 61.1 { +do_catchsql_test 61.1 { CREATE VIRTUAL TABLE t3 USING fts5vocab('t1'(),'col' ); -} +} {/*malformed database schema*/} do_catchsql_test 61.2 { SELECT * FROM t3 ORDER BY rowid; -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} breakpoint #------------------------------------------------------------------------- @@ -9159,7 +9159,7 @@ do_test 62.0 { do_catchsql_test 62.1 { WITH c(x) AS (VALUES(false) UNION ALL SELECT x+1 FROM c WHERE x<72) INSERT INTO t1(a) SELECT randomblob(2829) FROM c; -} {0 {}} +} {/*malformed database schema*/} #--------------------------------------------------------------------------- do_test 63.0 { @@ -9357,16 +9357,343 @@ do_test 63.0 { do_catchsql_test 63.1 { SELECT * FROM t1 WHERE b MATCH 'thead*thead*theSt*'; -} {1 {database disk image is malformed}} +} {/*malformed database schema*/} do_catchsql_test 63.2 { INSERT INTO t1(t1) VALUES('optimize'); -} {0 {}} +} {/*malformed database schema*/} -breakpoint do_catchsql_test 63.3 { SELECT * FROM t1 WHERE b MATCH 'thead*thead*theSt*'; -} {0 {}} +} {/*malformed database schema*/} + +#--------------------------------------------------------------------------- +do_test 64.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +.open --hexdb +| size 28672 pagesize 4096 filename crash-4470f0b94422f7.db +| page 1 offset 0 +| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3. +| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 06 .....@ ........ +| 32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04 ................ +| 96: 00 00 00 00 0d 00 00 00 06 0d e2 00 0f c4 0f 6a ...............j +| 112: 0e fc 0e 9d 0e 3d 0d e2 00 00 00 00 00 01 00 00 .....=.......... +| 3552: 00 00 59 06 06 17 21 21 01 7f 74 61 62 6c 65 74 ..Y...!!..tablet +| 3568: 74 74 5f 63 6f 6e 66 69 67 74 74 74 5f 63 6f 6e tt_configttt_con +| 3584: 66 69 67 06 43 52 45 41 54 45 20 54 41 42 4c 45 fig.CREATE TABLE +| 3600: 20 27 74 74 74 5f 63 6f 6e 66 69 67 27 28 6b 20 'ttt_config'(k +| 3616: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20 PRIMARY KEY, v) +| 3632: 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5e 05 07 WITHOUT ROWID^.. +| 3648: 17 23 23 01 81 03 74 61 62 6c 65 74 74 74 5f 64 .##...tablettt_d +| 3664: 6f 63 73 69 7a 65 74 74 74 5f 64 6f 63 73 69 7a ocsizettt_docsiz +| 3680: 65 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 e.CREATE TABLE ' +| 3696: 74 74 74 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 ttt_docsize'(id +| 3712: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY +| 3728: 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 29 5d 04 07 KEY, sz BLOB)].. +| 3744: 17 23 23 01 81 01 74 61 62 6c 65 74 74 74 5f 63 .##...tablettt_c +| 3760: 6f 6e 74 65 6e 74 74 74 74 5f 63 6f 6e 74 65 6e ontentttt_conten +| 3776: 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 t.CREATE TABLE ' +| 3792: 74 74 74 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20 ttt_content'(id +| 3808: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 INTEGER PRIMARY +| 3824: 4b 45 59 2c 20 63 30 2c 20 63 31 29 6c 03 07 17 KEY, c0, c1)l... +| 3840: 1b 1b 01 81 2f 74 61 62 6c 65 74 74 74 5f 69 64 ..../tablettt_id +| 3856: 78 74 74 74 5f 69 64 78 03 43 52 45 41 54 45 20 xttt_idx.CREATE +| 3872: 54 41 42 4c 45 20 27 74 74 74 5f 69 64 78 27 28 TABLE 'ttt_idx'( +| 3888: 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 67 6e segid, term, pgn +| 3904: 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 73 o, PRIMARY KEY(s +| 3920: 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 54 egid, term)) WIT +| 3936: 48 4f 55 54 20 52 4f 57 49 44 58 02 07 17 1d 1d HOUT ROWIDX..... +| 3952: 01 81 03 74 61 62 6c 65 74 74 74 5f 64 61 74 61 ...tablettt_data +| 3968: 74 74 74 5f 64 61 74 61 02 43 52 45 41 54 45 20 ttt_data.CREATE +| 3984: 54 41 42 4c 45 20 27 74 74 74 5f 64 61 74 61 27 TABLE 'ttt_data' +| 4000: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d (id INTEGER PRIM +| 4016: 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42 ARY KEY, block B +| 4032: 4c 4f 42 29 3a 01 06 17 13 13 08 5f 74 61 62 6c LOB):......_tabl +| 4048: 65 74 74 74 74 74 74 43 52 45 41 54 45 20 56 49 ettttttCREATE VI +| 4064: 52 54 55 41 4c 20 54 41 42 4c 45 20 74 74 74 20 RTUAL TABLE ttt +| 4080: 55 53 49 4e 47 20 66 74 73 35 28 61 2c 20 62 29 USING fts5(a, b) +| page 2 offset 4096 +| 0: 0d 0f 44 00 05 0e 81 00 0f 1a 0e 81 0f af 0f 58 ..D............X +| 16: 0e 98 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| 3712: 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 03 01 .....0.......... +| 3728: 01 01 02 01 01 03 01 01 81 24 8c 80 80 80 80 01 .........$...... +| 3744: 04 00 82 4c 00 00 00 9b 02 30 65 03 1a 02 05 05 ...L.....0e..... +| 3760: 07 05 01 01 04 03 03 08 03 03 01 2e 02 05 05 07 ................ +| 3776: 05 07 05 07 05 01 01 04 03 03 08 03 03 08 03 03 ................ +| 3792: 07 f3 03 02 01 65 03 1e 03 05 05 04 05 05 01 00 .....e.......... +| 3808: 03 06 04 04 06 04 03 01 36 03 05 05 04 06 05 04 ........6....... +| 3824: 06 05 04 05 05 01 01 03 06 04 04 06 04 04 06 04 ................ +| 3840: 04 06 04 03 03 01 65 03 14 04 05 06 f5 05 01 01 ......e......... +| 3856: 02 08 09 01 20 04 05 07 05 07 05 07 05 05 01 00 .... ........... +| 3872: 02 08 0a 0a 0a 04 01 65 03 02 0a 01 06 0a 0a 0a .......e........ +| 3888: 05 01 65 03 06 01 01 0a 01 0a 01 01 0a 0a 0a 04 ..e............. +| 3904: 2b 31 21 0b 0f ef 00 14 2a 00 00 00 00 01 02 02 +1!.....*....... +| 3920: 00 02 01 01 01 02 01 01 50 88 80 80 80 80 01 04 ........P....... +| 3936: 00 81 24 00 00 00 47 02 30 65 02 1a 02 05 05 07 ..$...G.0e...... +| 3952: 05 01 01 04 03 03 08 03 03 02 01 65 02 1e 03 05 ...........e.... +| 3968: 05 04 05 05 01 01 03 06 04 04 06 04 03 03 01 65 ...............e +| 3984: 02 14 04 05 07 05 05 01 01 02 08 0a 04 01 65 02 ..............e. +| 4000: 02 0a 05 01 65 02 06 01 01 0a 04 12 14 0f 06 31 ....e..........1 +| 4016: 84 80 80 80 80 01 03 00 68 00 00 00 2b 02 30 65 ........h...+.0e +| 4032: 01 10 02 05 05 01 01 04 03 03 02 01 65 01 12 03 ............e... +| 4048: 05 05 01 01 03 06 04 03 03 01 65 01 0e 04 05 05 ..........e..... +| 4064: 01 01 02 08 04 0d 0e 06 01 03 00 12 04 4c 4c 00 .............LL. +| 4080: 00 00 11 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............ +| page 3 offset 8192 +| 0: 0a 00 00 00 03 0f ec 00 0f 00 00 00 00 00 00 00 ................ +| 4064: 00 00 00 00 00 00 00 00 00 00 00 00 06 04 01 0c ................ +| 4080: 01 03 02 06 04 01 0c 01 02 02 05 04 09 0c 01 02 ................ +| page 4 offset 12288 +| 0: 0d 00 00 00 04 0e 1a 00 0f c7 0f 5b 0e ef 0e 1a ...........[.... +| 3600: 00 00 00 00 00 00 00 00 00 00 81 52 04 06 00 81 ...........R.... +| 3616: 5d 81 55 65 20 65 65 20 65 65 65 20 65 20 65 65 ].Ue ee eee e ee +| 3632: 20 65 65 65 20 65 20 65 65 20 65 65 65 66 20 65 eee e ee eeef e +| 3648: 65 20 65 65 65 20 65 20 65 65 20 65 65 65 20 65 e eee e ee eee e +| 3664: 20 65 65 20 65 65 65 65 20 65 65 20 65 65 65 20 ee eeee ee eee +| 3680: 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 65 e ee eee e ee ee +| 3696: 65 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 ee ee eee e ee e +| 3712: 65 65 20 65 20 65 65 20 65 65 65 65 65 65 20 65 ee e ee eeeeee e +| 3728: 65 20 65 20 65 20 65 20 65 65 20 65 65 65 20 65 e e e e ee eee e +| 3744: 65 20 65 65 65 65 65 20 65 65 20 65 20 65 1f 65 e eeeee ee e e.e +| 3760: 20 65 65 20 65 65 65 20 65 65 20 65 65 65 65 65 ee eee ee eeeee +| 3776: 20 65 65 20 65 20 65 20 65 20 65 65 20 65 65 65 ee e e e ee eee +| 3792: 20 65 65 20 65 65 65 65 65 20 65 65 20 65 20 65 ee eeeee ee e e +| 3808: 20 65 20 65 65 20 65 65 65 20 65 65 20 65 65 6a e ee eee ee eej +| 3824: 03 03 ff 75 71 65 20 65 65 1f 65 65 65 20 65 20 ...uqe ee.eee e +| 3840: 65 65 20 65 65 65 20 65 20 65 65 20 65 65 65 65 ee eee e ee eeee +| 3856: 20 65 65 20 65 65 65 20 65 20 65 65 20 65 65 65 ee eee e ee eee +| 3872: 20 65 20 65 65 20 65 65 65 65 65 65 20 65 65 20 e ee eeeeee ee +| 3888: 65 20 65 20 65 20 65 65 20 65 65 65 20 65 65 20 e e e ee eee ee +| 3904: 65 65 65 65 65 20 65 65 20 65 20 65 20 65 20 65 eeeee ee e e e e +| 3920: 65 20 65 65 65 20 65 65 20 65 65 6a 02 04 00 75 e eee ee eej...u +| 3936: 40 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 @e ee eee e ee e +| 3952: 65 65 20 65 20 65 65 20 65 65 65 65 20 65 65 20 ee e ee eeee ee +| 3968: 65 65 65 20 65 20 65 65 20 65 65 65 20 65 20 65 eee e ee eee e e +| 3984: 65 20 65 65 65 65 65 65 20 65 65 20 65 20 65 20 e eeeeee ee e e +| 4000: 65 20 65 65 20 65 65 65 20 65 65 20 65 65 65 65 e ee eee ee eeee +| 4016: 65 20 65 65 20 65 20 65 20 65 20 65 65 20 65 65 e ee e e e ee ee +| 4032: 65 20 65 65 20 65 65 37 01 04 00 41 3f 65 20 65 e ee ee7...A?e e +| 4048: 65 20 65 65 65 20 65 20 65 65 20 65 65 65 20 65 e eee e ee eee e +| 4064: 20 65 65 20 65 65 65 65 65 65 20 65 65 20 65 20 ee eeeeee ee e +| 4080: 65 20 65 20 65 65 20 65 65 65 20 65 65 20 65 65 e e ee eee ee ee +| page 5 offset 16384 +| 0: 0d 00 00 00 04 0f e4 00 0f f9 0f f2 0f eb 0f e4 ................ +| 4064: 00 00 00 00 05 04 03 00 10 21 21 05 03 03 00 10 .........!!..... +| 4080: 11 11 05 02 03 00 10 11 11 05 01 03 00 10 09 09 ................ +| page 6 offset 20480 +| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version. +| end crash-4470f0b94422f7.db +}]} {} + +do_catchsql_test 64.1 { + SELECT * FROM ttt('e*'); +} {1 {database disk image is malformed}} + +#--------------------------------------------------------------------------- +do_test 65.0 { + sqlite3 db {} + db deserialize [decode_hexdb { +.open --hexdb +| size 28672 pagesize 4096 filename crash-3aef66940ace0c.db +| page 1 offset 0 +| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3. +| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 00 .....@ ........ +| 96: 00 00 00 00 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6 +| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 00 00 00 00 00 00 ...k............ +| 3472: 00 00 22 08 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet +| 3488: 32 74 32 08 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE +| 3504: 20 74 32 28 78 29 56 07 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta +| 3520: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c +| 3536: 6f 6e 66 69 67 07 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB +| 3552: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k +| 3568: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v) +| 3584: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 06 WITHOUT ROWID[. +| 3600: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d +| 3616: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize +| 3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't +| 3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN +| 3664: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE +| 3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21 Y, sz BLOB)^...! +| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont +| 3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52 entt1_content.CR +| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c +| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG +| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY, +| 3776: 63 30 2c 20 63 31 2c d6 63 32 29 69 04 07 17 19 c0, c1,.c2)i.... +| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt +| 3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42 1_idx.CREATE TAB +| 3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69 LE 't1_idx'(segi +| 3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 d, term, pgno, P +| 3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 RIMARY KEY(segid +| 3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 , term)) WITHOUT +| 3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74 ROWIDU........t +| 3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61 ablet1_datat1_da +| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE +| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT +| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY +| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8.. +| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52 ...._tablet1t1CR +| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB +| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5 +| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c)......... +| page 3 offset 8192 +| 0: 0d 00 00 00 03 0c 93 ff 0f e6 0f ef 0c 94 00 00 ................ +| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J.......... +| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00......... +| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 31 31 36 30 ...........21160 +| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 33 f1 609...........3. +| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 03 01 02 ..........5..... +| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 3d ......0000000..= +| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary.. +| 3328: 01 02 02 03 06 01 01 f2 03 06 4e 02 02 03 06 01 ..........N..... +| 3344: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................ +| 3360: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................ +| 3376: 03 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70 ............comp +| 3392: 69 6c 65 72 01 02 02 01 02 02 01 02 02 01 06 64 iler...........d +| 3408: 62 73 74 61 74 07 02 03 01 02 13 01 02 03 02 04 bstat........... +| 3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 07 65 ebug...........e +| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable........... +| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................ +| 3472: 01 02 02 01 02 01 f1 02 02 01 02 02 01 02 02 01 ................ +| 3488: 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 ................ +| 3504: 02 01 02 02 02 08 76 b4 65 6e 73 69 6f 6e 1f 02 ......v.ension.. +| 3520: 04 01 02 04 01 02 04 01 04 66 74 73 34 0a 02 03 .........fts4... +| 3536: 01 02 03 01 02 03 04 01 25 0d 02 03 01 02 03 01 ........%....... +| 3552: 02 03 01 03 67 63 63 01 02 03 01 02 03 01 02 03 ....gcc......... +| 3568: 02 06 65 6f 70 6f 6c 79 0f f2 03 01 02 03 01 02 ..eopoly........ +| 3584: 03 01 05 6a 73 6f 6e 31 13 02 03 01 02 03 01 02 ...json1........ +| 3600: 03 01 04 6c 6f 61 64 1f 02 03 01 02 03 01 02 03 ...load......... +| 3616: 00 03 6d 61 78 1c 02 0c 01 02 02 01 02 02 02 05 ..max........... +| 3632: 65 6d 6f 72 79 1c 02 03 01 02 03 01 02 03 04 04 emory........... +| 3648: 73 79 73 35 16 02 03 01 02 03 01 02 03 01 06 6e sys5...........n +| 3664: 6f 63 61 73 65 02 06 01 02 02 13 06 00 f2 02 03 ocase........... +| 3680: 06 01 12 02 13 06 01 02 02 03 06 01 02 02 03 06 ................ +| 3696: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................ +| 3712: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................ +| 3728: 02 01 04 6f 6d 69 74 1f 02 02 01 02 02 01 02 02 ...omit......... +| 3744: 01 05 72 74 72 65 65 19 02 03 01 02 03 01 02 03 ..rtree......... +| 3760: 04 02 69 6d 01 06 01 02 02 03 06 01 02 02 03 06 ..im............ +| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................ +| 3792: 02 02 03 06 01 02 02 03 06 01 02 02 8e 06 01 02 ................ +| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................ +| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 22 02 02 01 ..threadsafe.... +| 3840: 02 02 01 02 02 01 04 76 74 61 62 07 02 04 01 02 .......vtab..... +| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x......... +| 3872: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................ +| 3888: 01 06 01 11 02 01 06 01 01 02 01 06 01 01 02 01 ................ +| 3904: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................ +| 3920: 01 01 02 01 06 01 01 01 01 06 01 01 02 01 06 01 ................ +| 3936: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................ +| 3952: 02 01 06 01 01 01 f1 06 01 01 02 ad 06 01 01 02 ................ +| 3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................ +| 3984: 06 01 01 01 01 06 01 01 02 01 06 01 01 02 01 06 ................ +| 4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................ +| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................ +| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................ +| 4048: 12 44 13 11 0f 47 13 0e fc 0e 11 10 0f 0e 10 0f .D...G.......... +| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$. +| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............ +| page 4 offset 12288 +| 0: 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................ +| page 5 offset 16384 +| 0: 0d 00 00 00 24 0c 0a 00 00 00 00 00 00 00 00 00 ....$........... +| 3072: 00 00 00 00 00 00 00 00 00 00 18 24 05 00 25 0f ...........$..%. +| 3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49 .THREADSAFE=0XBI +| 3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..THREA +| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 8f DSAFE=0XNOCASE.. +| 3136: 05 00 25 0f 17 54 48 52 45 41 44 43 41 46 45 3d ..%..THREADCAFE= +| 3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRTRIM.!..3..OM +| 3168: 49 54 20 4b 4f 41 44 21 45 58 54 45 4e 53 49 4f IT KOAD!EXTENSIO +| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 0f 19 4f NXBINARY. ..3..O +| 3200: 4d 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 MIT LOAD EXTENSI +| 3216: 4f 4e 58 4e 4f 43 41 53 45 1e 1f 05 00 33 0f 17 ONXNOCASE....3.. +| 3232: 4f 4d 59 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 OMYT LOAD EXTENS +| 3248: 49 4f 4e 58 52 54 56 a9 4d 1f 1e 05 00 33 0f 19 IONXRTV.M....3.. +| 3264: 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 30 MAX MEMORY=50000 +| 3280: 30 30 30 57 42 49 4e 31 52 59 1f 1d 05 00 33 0f 000WBIN1RY....3. +| 3296: 19 4d 41 58 20 4d 45 4d 4f 52 59 3d 35 30 30 30 .MAX MEMORY=5000 +| 3312: 30 30 30 30 58 4e 4f 43 41 53 45 1e 1c 05 00 32 0000XNOCASE....2 +| 3328: 0f 17 4e 41 58 20 4d 45 4d 4f 52 59 2d 35 30 30 ..NAX MEMORY-500 +| 3344: 30 30 30 30 30 58 52 54 52 49 4d 18 1b 05 00 25 00000XRTRIM....% +| 3360: 0f 19 45 4e 41 42 4c 45 20 52 54 52 45 45 58 42 ..ENABLE RTREEXB +| 3376: 49 4e 41 52 59 18 1a 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB +| 3392: 4c 45 20 52 54 52 45 45 59 4e 4f 43 41 53 45 17 LE RTREEYNOCASE. +| 3408: 19 66 00 25 0f 17 45 4e 41 42 4c 45 20 52 54 52 .f.%..ENABLE RTR +| 3424: 45 45 58 52 54 52 49 4d 1a 18 05 00 29 0f 19 45 EEXRTRIM....)..E +| 3440: 4e 41 42 4c 45 20 4d 45 4d 53 59 53 35 58 42 49 NABLE MEMSYS5XBI +| 3456: 4e 41 52 59 1a 17 05 00 29 0f 19 45 4e 41 42 4c NARY....)..ENABL +| 3472: 45 20 4d 45 4d 53 59 53 35 58 4e 4f 43 41 53 45 E MEMSYS5XNOCASE +| 3488: 19 16 05 00 29 0f 17 45 4e 41 42 4c 45 20 4d 45 ....)..ENABLE ME +| 3504: 4d 53 59 53 35 58 52 54 52 49 4d 18 15 05 10 25 MSYS5XRTRIM....% +| 3520: 0f 19 45 4e 40 42 4c 45 20 4a 53 4f 4e 31 58 42 ..EN@BLE JSON1XB +| 3536: 49 4e 41 52 59 18 14 05 00 25 0f 19 45 4e 41 42 INARY....%..ENAB +| 3552: 4c 45 20 4a 53 4f 4e 32 58 4e 4f 43 41 53 45 17 LE JSON2XNOCASE. +| 3568: 13 05 00 25 0f 17 45 4d 41 42 4c 45 20 4a 53 4f ...%..EMABLE JSO +| 3584: 4e 31 58 52 54 52 49 4d 1a 12 05 00 29 0f 19 45 N1XRTRIM....)..E +| 3600: 4e 41 42 4c 45 20 47 45 4f 50 4f 4c 59 58 42 49 NABLE GEOPOLYXBI +| 3616: 4e 41 52 59 1a 11 05 00 29 0f 19 45 4f 81 42 4c NARY....)..EO.BL +| 3632: 45 20 47 45 4f 50 4f 4c 59 58 4e 4f 43 51 53 45 E GEOPOLYXNOCQSE +| 3648: 19 10 05 00 29 0f 17 45 4e 41 42 4c 45 20 47 45 ....)..ENABLE GE +| 3664: 4f 50 4f 4c 59 58 52 54 52 49 4d 17 0f 05 00 23 OPOLYXRTRIM....# +| 3680: 0f 1a 45 4e 41 42 4c 45 20 46 54 53 35 58 42 49 ..ENABLE FTS5XBI +| 3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c NARY....#..ENABL +| 3712: 45 20 46 54 53 35 48 4e 4f 43 41 53 45 16 1d 05 E FTS5HNOCASE... +| 3728: 00 23 0f a4 45 4e 41 42 4c 45 20 46 54 53 35 58 .#..ENABLE FTS5X +| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB +| 3760: 4c 45 20 46 55 53 34 58 42 49 4e 41 52 59 17 0b LE FUS4XBINARY.. +| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4 +| 3792: 57 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e WNOCASE....#..EN +| 3808: 41 42 4c 45 20 46 54 53 34 05 52 54 52 49 4d 1e ABLE FTS4.RTRIM. +| 3824: 09 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS +| 3840: 54 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e TAT VTABXBINARY. +| 3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS +| 3872: 54 41 54 20 56 54 41 42 58 4e 4f 43 41 53 45 1d TAT VTABXNOCASE. +| 3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS +| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM.. +| 3920: 05 00 17 0f 19 44 45 42 55 47 58 42 8a 4e 41 52 .....DEBUGXB.NAR +| 3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO +| 3952: 43 41 53 45 10 04 05 00 17 0f 17 44 45 42 55 47 CASE.......DEBUG +| 3968: 58 52 54 52 49 4d 27 03 05 00 43 0f 19 43 4f 4d XRTRIM'...C..COM +| 3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20 PILER=gcc-5.4.0 +| 4000: 32 30 31 36 30 36 30 39 58 42 49 4e 41 52 59 27 20160609XBINARY' +| 4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3f 87 ...C..COMPILER?. +| 4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30 cc-5.4.0 2016060 +| 4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 0f 17 43 9XNOCASE&...C..C +| 4064: 45 0d 60 59 4c 45 52 3d 67 63 63 2d 35 2e 34 2d E.`YLER=gcc-5.4- +| 4080: 30 20 32 30 31 36 30 36 30 39 00 00 00 00 00 00 0 20160609...... +| page 6 offset 20480 +| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#...... +| 3824: 06 22 03 01 12 02 01 01 06 21 03 00 12 03 01 01 .........!...... +| 3840: 06 20 03 00 12 03 01 01 06 1f 03 00 12 03 02 01 . .............. +| 3856: 06 1e 03 00 12 03 01 01 06 1d 03 00 12 03 01 01 ................ +| 3872: 06 1c 03 00 12 03 01 01 06 1b 03 00 12 02 01 01 ................ +| 3888: 06 1a 03 00 12 02 01 01 06 19 03 00 12 02 01 01 ................ +| 3904: 06 18 03 00 12 02 01 01 06 17 03 00 12 02 01 01 ................ +| 3920: 06 16 03 00 12 02 01 01 06 15 03 00 12 02 01 01 ................ +| 3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01 ................ +| 3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01 ................ +| 3968: 06 00 03 00 12 02 01 01 06 0f 03 00 12 02 01 01 ................ +| 3984: 06 0e 03 00 12 02 01 01 06 0d 03 00 12 02 01 01 ................ +| 4000: 06 0c 03 00 12 02 01 01 06 0b 03 00 12 02 01 01 ................ +| 4016: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................ +| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................ +| 4048: 06 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................ +| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................ +| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................ +| page 7 offset 24576 +| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................ +| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version. +| end crash-3aef66940ace0c.db +}]} {} + +do_catchsql_test 65.1 { + SELECT ( MATCH (t1,591)) FROM t1 WHERE t1 MATCH 'e*eŸ' +} {1 {database disk image is malformed}} + + sqlite3_fts5_may_be_corrupt 0 finish_test diff --git a/ext/fts5/test/fts5faultB.test b/ext/fts5/test/fts5faultB.test index 2faec706d5..e5fc514d09 100644 --- a/ext/fts5/test/fts5faultB.test +++ b/ext/fts5/test/fts5faultB.test @@ -147,5 +147,27 @@ do_faultsim_test 5.1 -faults oom* -body { faultsim_test_result {0 {1 4}} } +#------------------------------------------------------------------------- +# Test OOM injection in a query with two MATCH expressions +# +reset_db +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a); + INSERT INTO t1 VALUES('a b c d'); -- 1 + INSERT INTO t1 VALUES('d a b c'); -- 2 + INSERT INTO t1 VALUES('c d a b'); -- 3 + INSERT INTO t1 VALUES('b c d a'); -- 4 +} +do_faultsim_test 6.1 -faults oom* -body { + execsql { SELECT rowid FROM t1 WHERE t1 MATCH 'a' AND t1 MATCH 'b' } +} -test { + faultsim_test_result {0 {1 2 3 4}} +} +do_faultsim_test 6.2 -faults oom* -body { + execsql { SELECT rowid FROM t1 WHERE t1 MATCH 'a OR b' AND t1 MATCH 'c OR d' } +} -test { + faultsim_test_result {0 {1 2 3 4}} +} + finish_test diff --git a/ext/fts5/test/fts5misc.test b/ext/fts5/test/fts5misc.test new file mode 100644 index 0000000000..009f578dce --- /dev/null +++ b/ext/fts5/test/fts5misc.test @@ -0,0 +1,63 @@ +# 2019 September 02 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#************************************************************************* +# This file implements regression tests for SQLite library. The +# focus of this script is testing the FTS5 module. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5misc + +# If SQLITE_ENABLE_FTS5 is not defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a); +} + +do_catchsql_test 1.1.1 { + SELECT highlight(t1, 4, '', '') FROM t1('*'); +} {1 {unknown special query: }} +do_catchsql_test 1.1.2 { + SELECT a FROM t1 + WHERE rank = (SELECT highlight(t1, 4, '', '') FROM t1('*')); +} {1 {unknown special query: }} + +do_catchsql_test 1.2.1 { + SELECT highlight(t1, 4, '', '') FROM t1('*id'); +} {0 {{}}} + +do_catchsql_test 1.2.2 { + SELECT a FROM t1 + WHERE rank = (SELECT highlight(t1, 4, '', '') FROM t1('*id')); +} {0 {}} + +do_catchsql_test 1.3.1 { + SELECT highlight(t1, 4, '', '') FROM t1('*reads'); +} {1 {no such cursor: 1}} + +do_catchsql_test 1.3.2 { + SELECT a FROM t1 + WHERE rank = (SELECT highlight(t1, 4, '', '') FROM t1('*reads')); +} {1 {no such cursor: 1}} + +db close +sqlite3 db test.db + +do_catchsql_test 1.3.3 { + SELECT a FROM t1 + WHERE rank = (SELECT highlight(t1, 4, '', '') FROM t1('*reads')); +} {1 {no such cursor: 1}} + +finish_test + diff --git a/ext/fts5/test/fts5multi.test b/ext/fts5/test/fts5multi.test new file mode 100644 index 0000000000..7878cede7e --- /dev/null +++ b/ext/fts5/test/fts5multi.test @@ -0,0 +1,99 @@ +# 2014 September 13 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#************************************************************************* +# This file implements regression tests for SQLite library. The +# focus of this script is testing the FTS5 module. +# + +source [file join [file dirname [info script]] fts5_common.tcl] +set testprefix fts5multi + +# If SQLITE_ENABLE_FTS5 is not defined, omit this file. +ifcapable !fts5 { + finish_test + return +} + +fts5_aux_test_functions db + +do_execsql_test 1.0 { + CREATE VIRTUAL TABLE t1 USING fts5(a, b, c); + INSERT INTO t1 VALUES('gg bb bb' ,'gg ff gg' ,'ii ii'); + INSERT INTO t1 VALUES('dd dd hh kk','jj' ,'aa'); + INSERT INTO t1 VALUES('kk gg ee' ,'hh cc' ,'hh jj aa cc'); + INSERT INTO t1 VALUES('hh' ,'bb jj cc' ,'kk ii'); + INSERT INTO t1 VALUES('kk dd kk ii','aa ee aa' ,'ee'); + INSERT INTO t1 VALUES('ee' ,'ff gg kk aa','ee ff ee'); + INSERT INTO t1 VALUES('ff jj' ,'gg ee' ,'kk ee gg kk'); + INSERT INTO t1 VALUES('ff ee dd hh','kk ee' ,'gg dd'); + INSERT INTO t1 VALUES('bb' ,'aa' ,'bb aa'); + INSERT INTO t1 VALUES('hh cc bb' ,'ff bb' ,'cc'); + INSERT INTO t1 VALUES('jj' ,'ff dd bb aa','dd dd ff ff'); + INSERT INTO t1 VALUES('ff dd gg dd','gg aa bb ff','cc'); + INSERT INTO t1 VALUES('ff aa cc jj','kk' ,'ii dd'); + INSERT INTO t1 VALUES('jj dd' ,'cc' ,'ii hh ee aa'); + INSERT INTO t1 VALUES('ff ii hh' ,'dd' ,'gg'); + INSERT INTO t1 VALUES('ff dd gg hh','hh' ,'ff dd'); + INSERT INTO t1 VALUES('cc cc' ,'ff dd ff' ,'bb'); + INSERT INTO t1 VALUES('ii' ,'bb ii' ,'jj kk'); + INSERT INTO t1 VALUES('ff hh' ,'hh bb' ,'bb dd ee'); + INSERT INTO t1 VALUES('jj kk' ,'jj' ,'gg ff cc'); + INSERT INTO t1 VALUES('dd kk' ,'ii gg' ,'dd'); + INSERT INTO t1 VALUES('cc' ,'aa ff' ,'ii'); + INSERT INTO t1 VALUES('bb ff bb ii','bb kk bb aa','hh ff ii dd'); + INSERT INTO t1 VALUES('aa' ,'ee bb jj jj','dd'); + INSERT INTO t1 VALUES('kk dd cc' ,'aa jj' ,'ee aa ff'); + INSERT INTO t1 VALUES('aa gg aa' ,'jj' ,'ii kk hh gg'); + INSERT INTO t1 VALUES('ff hh aa' ,'jj ii' ,'hh dd bb jj'); + INSERT INTO t1 VALUES('hh' ,'aa gg kk' ,'bb ee'); + INSERT INTO t1 VALUES('bb' ,'ee' ,'gg'); + INSERT INTO t1 VALUES('dd kk' ,'kk bb aa' ,'ee'); +} + +foreach {tn c1 e1 c2 e2} { + 1 t1 aa t1 bb + 2 a aa b bb + 3 a "aa OR bb OR cc" b "jj OR ii OR hh" + 4 t1 "aa AND bb" t1 "cc" + 5 c "kk" b "aa OR bb OR cc OR dd OR ee" +} { + if {$c1=="t1"} { + set lhs "( $e1 )" + } else { + set lhs "$c1 : ( $e1 )" + } + if {$c2=="t1"} { + set rhs "( $e2 )" + } else { + set rhs "$c2 : ( $e2 )" + } + + set q1 "t1 MATCH '($lhs) AND ($rhs)'" + set q2 "$c1 MATCH '$e1' AND $c2 MATCH '$e2'" + + set ret [execsql "SELECT rowid FROM t1 WHERE $q1"] + set N [llength $ret] + do_execsql_test 1.$tn.1.($N) "SELECT rowid FROM t1 WHERE $q2" $ret + + set ret [execsql "SELECT fts5_test_poslist(t1) FROM t1 WHERE $q1"] + do_execsql_test 1.$tn.2.($N) " + SELECT fts5_test_poslist(t1) FROM t1 WHERE $q2 + " $ret +} + +do_catchsql_test 2.1.1 { + SELECT rowid FROM t1 WHERE t1 MATCH '(NOT' AND t1 MATCH 'aa bb'; +} {1 {fts5: syntax error near "NOT"}} +do_catchsql_test 2.1.2 { + SELECT rowid FROM t1 WHERE t1 MATCH 'aa bb' AND t1 MATCH '(NOT'; +} {1 {fts5: syntax error near "NOT"}} + +finish_test + diff --git a/ext/fts5/test/fts5plan.test b/ext/fts5/test/fts5plan.test index 8f57e39a81..46ac234ff7 100644 --- a/ext/fts5/test/fts5plan.test +++ b/ext/fts5/test/fts5plan.test @@ -31,7 +31,7 @@ do_eqp_test 1.1 { } { QUERY PLAN |--SCAN TABLE t1 - `--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537: + `--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:m } do_eqp_test 1.2 { @@ -46,7 +46,7 @@ do_eqp_test 1.3 { SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff } { QUERY PLAN - |--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537: + |--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:m `--USE TEMP B-TREE FOR ORDER BY } @@ -60,6 +60,6 @@ do_eqp_test 1.4 { do_eqp_test 1.5 { SELECT * FROM f1 WHERE rank MATCH ? -} {SCAN TABLE f1 VIRTUAL TABLE INDEX 2:} +} {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:r} finish_test diff --git a/ext/fts5/test/fts5rank.test b/ext/fts5/test/fts5rank.test index e8f5473c4b..22534e8e03 100644 --- a/ext/fts5/test/fts5rank.test +++ b/ext/fts5/test/fts5rank.test @@ -162,4 +162,22 @@ do_execsql_test 5.1 { SELECT rowid FROM ttt('word') WHERE rowid BETWEEN 30 AND 40 ORDER BY rank; } {30 31 32 33 34 35 36 37 38 39 40} +#------------------------------------------------------------------------- +reset_db +do_execsql_test 6.0 { + CREATE VIRTUAL TABLE "My.Table" USING fts5(Text); + + INSERT INTO "My.Table" VALUES ('hello this is a test'); + INSERT INTO "My.Table" VALUES ('of trying to order by'); + INSERT INTO "My.Table" VALUES ('rank on an fts5 table'); + INSERT INTO "My.Table" VALUES ('that have periods in'); + INSERT INTO "My.Table" VALUES ('the table names.'); + INSERT INTO "My.Table" VALUES ('table table table'); +} +do_execsql_test 6.1 { + SELECT * FROM "My.Table" WHERE Text MATCH 'table' ORDER BY rank; +} { + {table table table} {the table names.} {rank on an fts5 table} +} + finish_test diff --git a/ext/fts5/test/fts5simple.test b/ext/fts5/test/fts5simple.test index 7fb0681dc8..936bbb2549 100644 --- a/ext/fts5/test/fts5simple.test +++ b/ext/fts5/test/fts5simple.test @@ -467,4 +467,17 @@ do_execsql_test 21.3 { SELECT rowid FROM x1($doc); } {11112} +#------------------------------------------------------------------------- +reset_db +do_execsql_test 22.0 { + CREATE VIRTUAL TABLE x1 USING fts5(x); + INSERT INTO x1(x) VALUES('a b c'); + INSERT INTO x1(x) VALUES('x y z'); + INSERT INTO x1(x) VALUES('c b a'); + INSERT INTO x1(x) VALUES('z y x'); +} + +do_catchsql_test 22.1 {SELECT * FROM x1('')} {1 {fts5: syntax error near ""}} +do_catchsql_test 22.2 {SELECT * FROM x1(NULL)} {1 {fts5: syntax error near ""}} + finish_test diff --git a/ext/lsm1/Makefile b/ext/lsm1/Makefile index 7022b5682c..7056432d2d 100644 --- a/ext/lsm1/Makefile +++ b/ext/lsm1/Makefile @@ -43,10 +43,10 @@ LSMTESTSRC = $(LSMDIR)/lsm-test/lsmtest1.c $(LSMDIR)/lsm-test/lsmtest2.c \ # all: lsm.so -LSMOPTS += -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR) -DHAVE_ZLIB +LSMOPTS += -fPIC -DLSM_MUTEX_PTHREADS=1 -I$(LSMDIR) -DHAVE_ZLIB lsm.so: $(LSMOBJ) - $(TCCX) -shared -o lsm.so $(LSMOBJ) + $(TCCX) -shared -fPIC -o lsm.so $(LSMOBJ) %.o: $(LSMDIR)/%.c $(LSMHDR) sqlite3.h $(TCCX) $(LSMOPTS) -c $< diff --git a/ext/lsm1/lsm_vtab.c b/ext/lsm1/lsm_vtab.c index fe7c160b62..f96a6bbd71 100644 --- a/ext/lsm1/lsm_vtab.c +++ b/ext/lsm1/lsm_vtab.c @@ -842,7 +842,7 @@ static int lsm1BestIndex( const struct sqlite3_index_constraint *pConstraint; pConstraint = pIdxInfo->aConstraint; - for(i=0; inConstraint && idxNum<16; i++, pConstraint++){ + for(i=0; inConstraint; i++, pConstraint++){ if( pConstraint->usable==0 ) continue; if( pConstraint->iColumn!=0 ) continue; switch( pConstraint->op ){ diff --git a/ext/lsm1/test/lsm1_simple.test b/ext/lsm1/test/lsm1_simple.test index bc0cb4c660..2eab50a83a 100644 --- a/ext/lsm1/test/lsm1_simple.test +++ b/ext/lsm1/test/lsm1_simple.test @@ -88,6 +88,65 @@ do_execsql_test 210 { do_execsql_test 211 { SELECT quote(a), quote(lsm1_key), quote(lsm1_value), '|' FROM x1; } {'12' X'3132' X'05320000000000000A401FFB42ABE9DB' | '15' X'3135' X'4284C6' | '8' X'38' X'2162616E6A6F1633323105' |} +do_execsql_test 212 { + SELECT quote(a), quote(lsm1_key), quote(lsm1_value) FROM x1 WHERE a='12'; +} {'12' X'3132' X'05320000000000000A401FFB42ABE9DB'} +#------------------------------------------------------------------------- +reset_db +forcedelete testlsm.db +load_lsm1_vtab db +do_execsql_test 300 { + CREATE VIRTUAL TABLE x1 USING lsm1(testlsm.db,a,TEXT,b,c,d); +} +do_eqp_test 310 { + SELECT * FROM x1 WHERE a=? +} {SCAN TABLE x1 VIRTUAL TABLE INDEX 0:} + +do_eqp_test 320 { + SELECT * FROM x1 WHERE a>? +} {SCAN TABLE x1 VIRTUAL TABLE INDEX 2:} + +do_eqp_test 330 { + SELECT * FROM x1 WHERE a 'five'; +} {4 1 3 2} +do_execsql_test 421 { + SELECT b FROM x1 WHERE a <= 'three'; +} {3 1 4 5} finish_test diff --git a/ext/misc/carray.c b/ext/misc/carray.c index b39904ae15..32fec3406e 100644 --- a/ext/misc/carray.c +++ b/ext/misc/carray.c @@ -24,7 +24,7 @@ ** ** static int aX[] = { 53, 9, 17, 2231, 4, 99 }; ** int i = sqlite3_bind_parameter_index(pStmt, "$ptr"); -** sqlite3_bind_value(pStmt, i, aX, "carray", 0); +** sqlite3_bind_pointer(pStmt, i, aX, "carray", 0); ** ** There is an optional third parameter to determine the datatype of ** the C-language array. Allowed values of the third parameter are diff --git a/ext/misc/json1.c b/ext/misc/json1.c index 3a9d10331c..251fd14afc 100644 --- a/ext/misc/json1.c +++ b/ext/misc/json1.c @@ -1820,7 +1820,7 @@ static void jsonArrayStep( if( pStr->zBuf==0 ){ jsonInit(pStr, ctx); jsonAppendChar(pStr, '['); - }else{ + }else if( pStr->nUsed>1 ){ jsonAppendChar(pStr, ','); pStr->pCtx = ctx; } @@ -1870,7 +1870,9 @@ static void jsonGroupInverse( ){ int i; int inStr = 0; + int nNest = 0; char *z; + char c; JsonString *pStr; UNUSED_PARAM(argc); UNUSED_PARAM(argv); @@ -1881,12 +1883,18 @@ static void jsonGroupInverse( if( NEVER(!pStr) ) return; #endif z = pStr->zBuf; - for(i=1; z[i]!=',' || inStr; i++){ - assert( inUsed ); - if( z[i]=='"' ){ + for(i=1; (c = z[i])!=',' || inStr || nNest; i++){ + if( i>=pStr->nUsed ){ + pStr->nUsed = 1; + return; + } + if( c=='"' ){ inStr = !inStr; - }else if( z[i]=='\\' ){ + }else if( c=='\\' ){ i++; + }else if( !inStr ){ + if( c=='{' || c=='[' ) nNest++; + if( c=='}' || c==']' ) nNest--; } } pStr->nUsed -= i; @@ -1916,7 +1924,7 @@ static void jsonObjectStep( if( pStr->zBuf==0 ){ jsonInit(pStr, ctx); jsonAppendChar(pStr, '{'); - }else{ + }else if( pStr->nUsed>1 ){ jsonAppendChar(pStr, ','); pStr->pCtx = ctx; } @@ -2504,14 +2512,14 @@ int sqlite3Json1Init(sqlite3 *db){ #endif for(i=0; iaOp); sqlite3_free(pRe->aArg); @@ -624,7 +624,7 @@ void re_free(ReCompiled *pRe){ ** compiled regular expression in *ppRe. Return NULL on success or an ** error message if something goes wrong. */ -const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){ +static const char *re_compile(ReCompiled **ppRe, const char *zIn, int noCase){ ReCompiled *pRe; const char *zErr; int i, j; diff --git a/ext/rtree/rtreefuzz001.test b/ext/rtree/rtreefuzz001.test index f4a91264c7..db9df205af 100644 --- a/ext/rtree/rtreefuzz001.test +++ b/ext/rtree/rtreefuzz001.test @@ -465,6 +465,7 @@ do_test rtreefuzz001-100 { | end c1b.db }] catchsql { + PRAGMA writable_schema = 1; SELECT rtreecheck('t1'); } } {1 {SQL logic error}} @@ -1040,6 +1041,7 @@ do_test rtreefuzz001-500 { | 2880: ff ff ff 06 00 00 00 0c 00 00 00 01 00 00 00 0b ................ | 2896: 00 00 00 00 00 00 00 02 40 00 00 00 00 00 00 00 ........@....... | end crash-2e81f5dce5cbd4.db}] + execsql { PRAGMA writable_schema = 1;} catchsql {UPDATE t1 SET ex= ex ISNULL} } {1 {database disk image is malformed}} diff --git a/main.mk b/main.mk index c3eadc05db..8991b98c26 100644 --- a/main.mk +++ b/main.mk @@ -529,7 +529,6 @@ SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC -SHELL_OPT += -DSQLITE_INTROSPECTION_PRAGMAS FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1 FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000 diff --git a/manifest b/manifest index 3badbdad5f..066e15813e 100644 --- a/manifest +++ b/manifest @@ -1,11 +1,11 @@ -C Merge\slatest\strunk\schanges\swith\sthis\sbranch. -D 2019-08-13T15:22:10.851 +C Merge\sall\srecent\strunk\senhancements\sinto\sthe\sreuse-schema\sbranch. +D 2019-09-16T12:35:48.289 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 -F Makefile.in c4b55bbca70511d8757e38358dfbc06dd74abd51d61bf4939d2caea023c9b97b -F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 3a35f2d39e1c60cdfa6b53e13c1d3714048a3a0937ab278aa2684a7772c113ce +F Makefile.in 4f63722008696418bae434379987f9987cba2ce823579512f2dd5f0ff734c04a +F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241 +F Makefile.msc bfa3ab0a9d6a81ac5156084c67b75e2c9b66fd543954673ff2135075eef07414 F README.md 1514a365ffca3c138e00c5cc839906108a01011a6b082bad19b09781e3aa498a F VERSION 4c516d84c2a5f26c477ed34c09ac4136630f71c68139631f2eb591b22eea7cf1 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -48,7 +48,7 @@ F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74 F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3 F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4 -F ext/expert/expert1.test 358e416877a5693fb99d5514f5d88452b5239dc2196b74e0e926718502faef6d +F ext/expert/expert1.test e2afc53a27610e8251e44c7f961806607a5490ff204b3db342740d558e052662 F ext/expert/sqlite3expert.c 3da865f2286433588260f41e796422c611bceaca3a0bbf9139a619cf7d062c19 F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811 F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72 @@ -91,7 +91,7 @@ F ext/fts3/fts3_hash.c 8b6e31bfb0844c27dc6092c2620bdb1fca17ed613072db057d96952c6 F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116 F ext/fts3/fts3_porter.c 3565faf04b626cddf85f03825e86056a4562c009 -F ext/fts3/fts3_snippet.c 2f3a78b990f1c8658225618c8a0fa06ab60046688d6fb627a548e8ada9011150 +F ext/fts3/fts3_snippet.c 7963dd25ec81013c31f3c61697d0a1f3d06be21af3565774645c08d3dedf1fa7 F ext/fts3/fts3_term.c f45a1e7c6ef464abb1231245d123dae12266b69e05cc56e14045b76591ae92d1 F ext/fts3/fts3_test.c 73b16e229e517c1b1f0fb8e1046182a4e5dbc8dbe6eea8a5d4353fcce7dbbf39 F ext/fts3/fts3_tokenize_vtab.c 1de9a61acfa2a0445ed989310c31839c57f6b6086dd9d5c97177ae734a17fd8b @@ -111,14 +111,14 @@ F ext/fts3/unicode/mkunicode.tcl bf7fcaa6d68e6d38223467983785d054f1cff4d9e3905dd F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0 F ext/fts5/fts5.h 7c9da96f2b9dcfa4dd94081fb2d87ec418d8cdb35b25df56756c334b6b558fd7 -F ext/fts5/fts5Int.h d87fb17d12296613cdec2d1f4213ecd8840d3deb34837b6d3889b830d06baac4 +F ext/fts5/fts5Int.h 0ec19a906a54c0e53f8a380c0ff70f11a866aa259490bc13aa39f8d2491800fd F ext/fts5/fts5_aux.c dcc627d8b6e3fc773db528ff67b39955dab7b51628f9dba8e15849e5bedfd7fa F ext/fts5/fts5_buffer.c 5a5fe0159752c0fb0a5a93c722e9db2662822709490769d482b76a6dc8aaca70 -F ext/fts5/fts5_config.c d7523cba5e66da077233c023aecbc3e6a37978ff75a18131c5ab5b1229d5bac7 -F ext/fts5/fts5_expr.c 840c88d55e78083a5e61a35968df877712ae28791b347eced1e98e3b337d2d3c +F ext/fts5/fts5_config.c 606a29f2962a8f4508923e6ad833974b32a3ab4093f63fd6de0fb33a87eed54c +F ext/fts5/fts5_expr.c 5661fe64f4f5a499710df9561075de84b743f01e808af46df4130a9ec343a0fd F ext/fts5/fts5_hash.c 1cc0095646f5f3b46721aa112fb4f9bf29ae175cb5338f89dcec66ed97acfe75 -F ext/fts5/fts5_index.c cd363c2fa3e626c04a9b7c705ff50222b4cab052704938f6a24881602ed3ed0d -F ext/fts5/fts5_main.c 346a1ec08caa66f1187f1e0bf12e39e4d24682323b839e8a76ef653b8db8a91d +F ext/fts5/fts5_index.c b062bdb836e195656aac8d6684e943585cff4bf7d7c593c80cb67c3b6cfef7ee +F ext/fts5/fts5_main.c bf637030722badf06667d28f7159e4c209dbafd7aa76c33f387104b78ad147e1 F ext/fts5/fts5_storage.c 801b4e3cd33786a60a07b6b01f86d0fbdf7e68325054e08d17176293a8081e99 F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95 F ext/fts5/fts5_test_mi.c 08c11ec968148d4cb4119d96d819f8c1f329812c568bac3684f5464be177d3ee @@ -158,7 +158,7 @@ F ext/fts5/test/fts5connect.test 08030168fc96fc278fa81f28654fb7e90566f33aff269c0 F ext/fts5/test/fts5content.test 9517cc527a8e8a33949652d5c7b5e251f8c3d5ae3f23f01d4320e30f29a0336b F ext/fts5/test/fts5corrupt.test 77ae6f41a7eba10620efb921cf7dbe218b0ef232b04519deb43581cb17a57ebe F ext/fts5/test/fts5corrupt2.test 7453752ba12ce91690c469a6449d412561cc604b1dec994e16ab132952e7805f -F ext/fts5/test/fts5corrupt3.test 1f36c04fdd717f7d44a0addcdad0f5e54a5a403eab8a25426b069757830682ee +F ext/fts5/test/fts5corrupt3.test f326d70e08acffcbd8a551edd72b5723db7d3a902d288d958014c81a111cae21 F ext/fts5/test/fts5corrupt4.test ea805c4d7c68b5f185b9db5d2060a7ae5875339738dd48203c92162f41e7ca91 F ext/fts5/test/fts5delete.test cbf87e3b8867c4d5cfcaed975c7475fd3f99d072bce2075fcedf43d1f82af775 F ext/fts5/test/fts5detail.test 31b240dbf6d44ac3507e2f8b65f29fdc12465ffd531212378c7ce1066766f54e @@ -177,7 +177,7 @@ F ext/fts5/test/fts5fault7.test 0acbec416edb24b8881f154e99c31e9ccf73f539cfcd1640 F ext/fts5/test/fts5fault8.test 318238659d35f82ad215ecb57ca4c87486ea85d45dbeedaee42f148ff5105ee2 F ext/fts5/test/fts5fault9.test 098e6b894bbdf9b2192f994a30f4043673fb3f338b6b8ab1624c704422f39119 F ext/fts5/test/fts5faultA.test be4487576bff8c22cee6597d1893b312f306504a8c6ccd3c53ca85af12290c8c -F ext/fts5/test/fts5faultB.test e6d04f9ea7b21be1d89abb8df2cb4baf65b0453b744d5a805fcd3ef45ff86a7e +F ext/fts5/test/fts5faultB.test d606bdb8e81aaeb6f41de3fc9fc7ae315733f0903fbff05cf54f5b045b729ab5 F ext/fts5/test/fts5faultD.test cc5d1225556e356615e719c612e845d41bff7d5a F ext/fts5/test/fts5first.test 3fcf2365c00a15fc9704233674789a3b95131d12de18a9b996159f6909dc8079 F ext/fts5/test/fts5full.test 49b565da02918c06e58f51f0b953b0302b96f155aa68baba24782b81570685e2 @@ -190,21 +190,23 @@ F ext/fts5/test/fts5leftjoin.test c0b4cafb9661379e576dc4405c0891d8fcc27826807405 F ext/fts5/test/fts5matchinfo.test 79129ff6c9a2d86943b287a5a8caa7ee639f6dcf004d8975d15c279374e82e35 F ext/fts5/test/fts5merge.test e92a8db28b45931e7a9c7b1bbd36101692759d00274df74d83fd29d25d53b3a6 F ext/fts5/test/fts5merge2.test 3ebad1a59d6ad3fb66eff6523a09e95dc6367cbefb3cd73196801dea0425c8e2 +F ext/fts5/test/fts5misc.test 5becd134b66f7370042968a2b127b92ea7748e249f16cb6a996f450812e89eec +F ext/fts5/test/fts5multi.test a15bc91cdb717492e6e1b66fec1c356cb57386b980c7ba5af1915f97fe878581 F ext/fts5/test/fts5multiclient.test 5ff811c028d6108045ffef737f1e9f05028af2458e456c0937c1d1b8dea56d45 F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c2765c3ddd2ef58bd F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618834bf1fcc3e7b84da F ext/fts5/test/fts5optimize.test 36a752d24c818792032e4ff502936fc9cc5ef938721696396fdc79214b2717f1 F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b -F ext/fts5/test/fts5plan.test 00dc4c974938b509db7cb3680407f068ee6e9cc824f492f68cb741a7b679fe41 +F ext/fts5/test/fts5plan.test 771b999d161e24fd803ce0290adb7c6e7c9b9cc2c6a0adb344813fb89473aa32 F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15 F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457 F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056 F ext/fts5/test/fts5query.test ac363b17a442620bb0780e93c24f16a5f963dfe2f23dc85647b869efcfada728 -F ext/fts5/test/fts5rank.test ca5000241924ecc2882db33c60f4f3a62b1ee6b16b5a9c8c6ddd9b6b2138489c +F ext/fts5/test/fts5rank.test c9fd4a1e36b4fa92d572ec13d846469b97da249d1c2f7fd3ee7e017ce46f2416 F ext/fts5/test/fts5rebuild.test 55d6f17715cddbf825680dd6551efbc72ed916d8cf1cde40a46fc5d785b451e7 F ext/fts5/test/fts5restart.test 835ecc8f449e3919f72509ab58056d0cedca40d1fe04108ccf8ac4c2ba41f415 F ext/fts5/test/fts5rowid.test b8790ec170a8dc1942a15aef3db926a5f3061b1ff171013003d8297203a20ad6 -F ext/fts5/test/fts5simple.test 313ad28ef38ebe25f0a1673dd18f2fac446e25feb15bbb0c223a65ea00594f72 +F ext/fts5/test/fts5simple.test a298670508c1458b88ce6030440f26a30673931884eb5f4094ac1773b3ba217b F ext/fts5/test/fts5simple2.test 258a1b0c590409bfa5271e872c79572b319d2a56554d0585f68f146a0da603f0 F ext/fts5/test/fts5simple3.test d5c74a9d3ca71bd5dd5cacb7c55b86ea12cdddfc8b1910e3de2995206898380f F ext/fts5/test/fts5synonym.test 1651815b8008de170e8e600dcacc17521d765482ea8f074ae82cfa870d8bb7fb @@ -230,7 +232,7 @@ F ext/fts5/tool/showfts5.tcl d54da0e067306663e2d5d523965ca487698e722c F ext/icu/README.txt a295e91db742b153e8dce8f7efd31d28ad1eea4df31ef4daa3eedc85be2f5138 F ext/icu/icu.c c2c7592574c08cd1270d909b8fb8797f6ea1f49e931e71dbcc25506b9b224580 F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37 -F ext/lsm1/Makefile 98b0a24b45e248283d6bea4b6cb3e58d7b394edd8e96a0ac28c5fa5104813bad +F ext/lsm1/Makefile a553b728bba6c11201b795188c5708915cc4290f02b7df6ba7e8c4c943fd5cd9 F ext/lsm1/Makefile.msc f8c878b467232226de288da320e1ac71c131f5ec91e08b21f502303347260013 F ext/lsm1/lsm-test/README 87ea529d2abe615e856d4714bfe8bb185e6c2771b8612aa6298588b7b43e6f86 F ext/lsm1/lsm-test/lsmtest.h cf58528ffe0cfe535e91b44584e2ec5fb1caacdabecef0d8dcf83bf83168bf28 @@ -270,10 +272,10 @@ F ext/lsm1/lsm_str.c 65e361b488c87b10bf3e5c0070b14ffc602cf84f094880bece77bbf6678 F ext/lsm1/lsm_tree.c 682679d7ef2b8b6f2fe77aeb532c8d29695bca671c220b0abac77069de5fb9fb F ext/lsm1/lsm_unix.c 57361bcf5b1a1a028f5d66571ee490e9064d2cfb145a2cc9e5ddade467bb551b F ext/lsm1/lsm_varint.c 43f954af668a66c7928b81597c14d6ad4be9fedbc276bbd80f52fa28a02fdb62 -F ext/lsm1/lsm_vtab.c 529255dc704289001b225d97e57e0cfa14b29c3f281c7349cfa8fdb655de79ae +F ext/lsm1/lsm_vtab.c 169bfe7ef8e6c9de9c77e17c4c50c9ae55fb0167d80be3d1be82c991184b6f35 F ext/lsm1/lsm_win32.c 0a4acbd7e8d136dd3a5753f0a9e7a9802263a9d96cef3278cf120bcaa724db7c F ext/lsm1/test/lsm1_common.tcl 5ed4bab07c93be2e4f300ebe46007ecf4b3e20bc5fbe1dedaf04a8774a6d8d82 -F ext/lsm1/test/lsm1_simple.test ca949efefa102f4644231dcd9291d8cda7699a4ce1006b26e0e3fcb72233f422 +F ext/lsm1/test/lsm1_simple.test a04d08e8661ae6fc53786c67f0bd102c6692f003e859dde03ed9ac3f12e066e5 F ext/lsm1/tool/mklsm1c.tcl f31561bbee5349f0a554d1ad7236ac1991fc09176626f529f6078e07335398b0 F ext/misc/README.md d6dd0fe1d8af77040216798a6a2b0c46c73054d2f0ea544fbbcdccf6f238c240 F ext/misc/amatch.c 50a9ef2d38dabfa371f8c1904097d493271e63d58ccb0e9b79a4fa4a94e66660 @@ -281,7 +283,7 @@ F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a2 F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb1967af7 F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a F ext/misc/btreeinfo.c 4f0ebf278f46e68e6306c667917766cebc5550fd35d5de17847988e22892d4d2 -F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005 +F ext/misc/carray.c 91e9a7f512fda934894bed30464552fffa7d3073b5be04189ae0bd0c59f26bfd F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243 F ext/misc/completion.c cec672d40604075bb341a7f11ac48393efdcd90a979269b8fe7977ea62d0547f F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189 @@ -294,7 +296,7 @@ F ext/misc/fileio.c 288e7230e0fe464d71b0694e2d8bdd3a353118ac2e31da3964b95f460f09 F ext/misc/fossildelta.c 7708651072eb5620ab21bbfb518d184f27b2c29c0131b09b9a2d8852a8016430 F ext/misc/fuzzer.c c4e27daf41433a64cad5265cd27dbcb891147e9994d0422200ce81ce9a54b625 F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c -F ext/misc/json1.c 71ce4e39793b743fc7e4790bc3bab15598e95cab57ad8da4326fa640ae5e5310 +F ext/misc/json1.c 061950860e6b8b7af6fc40029bf673fb97887ab04d6a33950c32a0ced6775577 F ext/misc/memstat.c 3017a0832c645c0f8c773435620d663855f04690172316bd127270d1a7523d4d F ext/misc/memtrace.c 7c0d115d2ef716ad0ba632c91e05bd119cb16c1aedf3bec9f06196ead2d5537b F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567 @@ -303,7 +305,7 @@ F ext/misc/nextchar.c 279f80fe8ef5ba413242e2704e246503ac601f005eefb180d19e6c9203 F ext/misc/normalize.c b4290464f542bae7a97b43f15bd197949b833ffd668b7c313631bd5d4610212c F ext/misc/percentile.c 148dd07286b16e50f232bb638a47850085ad37d51f270429905bd865e595d1ca F ext/misc/prefixes.c 7be86d17525cfae6ed462fc3c519efc44488ac329890f77491c8f82871f57e17 -F ext/misc/regexp.c 79345bf03496155a640ee0300d3307296761cebb5e115b4e342cc2fb5861ec10 +F ext/misc/regexp.c 653b6ab5e89bcb5d45f9ebe0747d7f8f3f5706cac963fcbc9a3ddbe5fdc1efa2 F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c F ext/misc/rot13.c 540a169cb0d74f15522a8930b0cccdcb37a4fd071d219a5a083a319fc6e8db77 F ext/misc/scrub.c db9fff56fed322ca587d73727c6021b11ae79ce3f31b389e1d82891d144f22ad @@ -402,7 +404,7 @@ F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b5879 F ext/rtree/rtreecheck.test d67d5b3e9e45bfa8cd90734e8e9302144ac415b8e9176c6f02d4f92892ee8a35 F ext/rtree/rtreecirc.test aec664eb21ae943aeb344191407afff5d392d3ae9d12b9a112ced0d9c5de298e F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d -F ext/rtree/rtreefuzz001.test f9fecd174fc6475174d876f78f77b538122c1db296a96dca4615918953a892be +F ext/rtree/rtreefuzz001.test eef1ed593bb15886cd5d5367a2f2492f81e315848896cdf7afb6e21454978827 F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373 F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de F ext/rtree/util/randomshape.tcl 54ee03d0d4a1c621806f7f44d5b78d2db8fac26e0e8687c36c4bd0203b27dbff @@ -446,7 +448,7 @@ F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e6 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk b5dd74c752335a232b454f55387012e9326ee6002a2d0c2a2f3b6dc8b8dec642 +F main.mk f20c19fda395ae00a77662586eec40ba90aee6b1873ae275a7c2b23ed6d63d48 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -459,16 +461,16 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c deddf439893a8157b19b2b69e9537ed12aa2e4ddf5738141932f6d0330d1bb44 -F src/analyze.c 01ee7d24f0391a3756993572e9492e3d8e1dba87a44397fa2d8e660bc04ef99c -F src/attach.c 95c3e4b1aa81c16a537cfa0c990dbcfa6e460e382b6ff888752f8e70075a4def +F src/analyze.c 050e013f2b1d0f6f334e147c4c0f8a24f4b7dfb83c24fc62a2da7ebb50e45dfb +F src/attach.c 6a1a045ff64c542882d1159a1df0aebaeaad86c9ed204edd979e94e8e9feefe1 F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06 F src/backup.c f70077d40c08b7787bfe934e4d1da8030cb0cc57d46b345fba2294b7d1be23ab F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 -F src/btree.c 6061323b98cc794a1e3ad6907f683f1ad2b8c48d7c7d486072b21f18efe73761 +F src/btree.c fdc4389b271bca30138db27dc2dfb9f52c2a7baaa44845aaf31a3c54663d837f F src/btree.h c11446f07ec0e9dc85af8041cb0855c52f5359c8b2a43e47e02a685282504d89 F src/btreeInt.h 6111c15868b90669f79081039d19e7ea8674013f907710baa3c814dc3f8bfd3f -F src/build.c 7d97429277c45361bd093014721aaf1d5e8ea967505598d769f9c2b225a03896 +F src/build.c ab0e35602af640fb5840fcfab1bcdffb6776c4569841517d8ba8a3f4203d03fc F src/callback.c 2e6db109a37219464a3a5ed6f2f330af4a0500a1a224122f4be472e454efe2cf F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 15d1010037db3577d2e90e793197c539e86860ab272d7a49e4e976425d0eba62 @@ -476,7 +478,7 @@ F src/date.c e1d8ac7102f3f283e63e13867acb0efa33861cf34f0faf4cdbaf9fa7a1eb7041 F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7 F src/dbstat.c c12833de69cb655751487d2c5a59607e36be1c58ba1f4bd536609909ad47b319 F src/delete.c d08c9e01a2664afd12edcfa3a9c6578517e8ff8735f35509582693adbe0edeaf -F src/expr.c 85239130e25f54279b1dfb3641984a335ce5a38709af29f9b62b555ed1459d07 +F src/expr.c 10d90c4676047a75276446779d18fb3f7d3a1f9debc8b322e3772d2bd51f52ff F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 2c14c9431a2de2c0d9444d0cc27e4360f4829455f689decfff01cac383fe0894 F src/func.c 4ee36219698d50d672a28eca4adb0fd6b92e607a1883d318315e0d2fd5044467 @@ -485,10 +487,10 @@ F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38 F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c c2194dd2886337b870226fcb31c13e7df8c4b5e0ea85140e510a6f1daf1ad65b +F src/insert.c 40557ebd69f4115e7a273f9304a8ab637a47ce44f3c6923396928f023967b5e8 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa -F src/loadext.c 22afc33c3a61b4fd80a60a54f1882688371e6bc64685df2696b008fce65a999c -F src/main.c 4b96a652a86ba72e011c8487f87251b25bdaeb15aac2655a583eefecb08750ea +F src/loadext.c a045bb3425a9a633cc0f78e93d9beda6866f4c0f15bfdee735aba7c6b39f5cc4 +F src/main.c dcdd6acc2ec4a790aedf741cb684c43f632c41bbbc34a41129f5cde43437433c F src/malloc.c 0f9da2a66b230a5785af94b9672126845099b57b70a32c987d04ac28c69da990 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de @@ -496,7 +498,7 @@ F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3 F src/mem3.c 8768ac94694f31ffaf8b4d0ea5dc08af7010a35a F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944 F src/memdb.c 02a5fcec19b9d40dd449ca802dc1b2e8f93f255fbf2a886277a3c3800d8d35db -F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661 +F src/memjournal.c 7561c01c90958f3ba9bc6cb2d857123d932bdfa5539ea34427a0957b2e35154d F src/msvc.h 3a15918220367a8876be3fa4f2abe423a861491e84b864fb2b7426bf022a28f8 F src/mutex.c bae36f8af32c22ad80bbf0ccebec63c252b6a2b86e4d3e42672ff287ebf4a604 F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85 @@ -513,28 +515,28 @@ F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 422fd8cfa59fb9173eff36a95878904a0eeb0dcc62ba49350acc8b1e51c4dc7b F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3 -F src/parse.y 6d03a24bc0dcd15b93c480ea8a87f7ccd25313fe826485726d9ef13b82f2378d +F src/parse.y 6f284f7488ad9db9ae2762161e52bec2e9609462b98a3354fcc6e0ce7aa7be8d F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache1.c 62714cbd1b7299a6e6a27a587b66b4fd3a836a84e1181e7f96f5c34a50917848 -F src/pragma.c 7f5272822ecdc6bb830b0192a06d37618a938ef499e480b5aa79b07c59c1f492 -F src/pragma.h 089d20e01c735fcb9707f5947961008e4f0764b03f4a383ba1eacaa5b891fa6e -F src/prepare.c ca7d06cec9ac6534542f0ea9cf73fdfc22c05c4f54e882e09ac1fca83ea2e7df +F src/pragma.c f76a8ddaf4aa0e2dab3c080ad5c9fc4599c3431fe8f2ca36d6a129441e739d1a +F src/pragma.h 583d641cfd146d31c91d7ba2770d6b8413c3ff0dc4f4a56645216c983a119c08 +F src/prepare.c 43e4601125f076d6c30b33c47dfcb3cffcdc1f26f02c4339b6f27c63016c88cd F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 -F src/resolve.c d49679d55d3cf529bbdff8734c4ac02cedfb2fc785545b89815ddb79680b9198 +F src/resolve.c 9891cf5fd155bb199f8b1ff5d1429b9f70484487f4c455bba94348d4cb6f829f F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 -F src/select.c 11087458ec2af5c4b377559ea0462c2ab842e02badd35b21a8d67257c4e0b117 -F src/shell.c.in 42051fc4e6f6c90b5789491fa14af0b9354e7db90aad813595f29302e5d09a53 -F src/sqlite.h.in 20fa8617527bb29315a6342db84c6ddcd58e0fda63a111152296ea9c77b9a9db +F src/select.c e2c870548541d33d090a066e89ab2e7943299006e2827c1abfae39561041fc0b +F src/shell.c.in f3f258a9972d5315ec4a69b8410bd8dbebd72942a7f3b79550e6825b9a995e61 +F src/sqlite.h.in bd7a60793790a9ea7be03c5402bf2fe8c6a1156f5ab43cdec9a7e01fcb1ac402 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 -F src/sqlite3ext.h 9ecc93b8493bd20c0c07d52e2ac0ed8bab9b549c7f7955b59869597b650dd8b5 -F src/sqliteInt.h 47f291495f5fca52bd933dc1e3c70b513160e2b06b738db76fe4392a056054f3 +F src/sqlite3ext.h cef696ce3293242c67b2339763608427bf72ee66f1f3a05389ac2a7b46001c31 +F src/sqliteInt.h 0a25886fc8339edbc2eb82ba5a20a889d432e5a9d8a56729d8cac8bdb774d19e F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c d9f7d66ae8bee9ffbe4cf7ae72a8d3d429a269336dee1e705ecb3dbea27fa5e2 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 -F src/tclsqlite.c 5947f3797410e213cde1d61f61fbfda706ee4ee2e1db6e0b2376e3206dabc71d -F src/test1.c 87059457fb90b73a74044b379fe2cb0aefbb53c010c646ecaff23179a423638c +F src/tclsqlite.c 02d9f47e1797c7aa4174fe90dc5380fb99057303e0b6443fa1b103e9de65cf35 +F src/test1.c 07d774ae3fcd3aed48248483d550cef55cfb417bddab54f4c616b3ac8faa8e32 F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test4.c 405834f6a93ec395cc4c9bb8ecebf7c3d8079e7ca16ae65e82d01afd229694bb @@ -590,37 +592,37 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c 3e08eadda7a23a58dd45976c68c600ca2b61a6015c2e61849b1e0cb62f9a9169 -F src/treeview.c 06e65db6ffa14dd583f90403192190dfe3855c0e3acfcbac0e82109a46e2b16c -F src/trigger.c fbe9b54f60b3d163eff7f4c4958c03069686ed04dc2994c286b216176a965bb6 -F src/update.c 3cb9150d2cf661d938e2f1b1749945f3faa767f88febdb739ab1793bbf895ff2 -F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 +F src/treeview.c dd92b189d8c0623d6cf59cf2e136e4c3b2389ded133eaa15ca51d4714866ebb4 +F src/trigger.c 63761fc1306cf27eb1c875410d23452224ece3aafd14a0b73d6f53776050d06a +F src/update.c 7f05fad5e145248a00048aeb0bac78b8fdb4ed17216e14a6eb24c55596e87ee7 +F src/upsert.c 710c91bb13e3c3fed5b6fe17cb13e09560bdd003ad8b8c51e6b16c80cfc48b10 F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507 F src/util.c fffdfa627be74d69ef425f92db124e7148af449bb8a3286e79577c42bca84061 F src/vacuum.c 5b9b4771ffb47aaef038c4ad5f1acd76dfbc9e0a4f101c1ba7f7ac9c2ba96374 -F src/vdbe.c a19626224f62ec48da96dc41a3f9feda243ad5956c0067a93c7ea9210fb1a314 +F src/vdbe.c 968f911f87ab6a03e2ad1738f98e717db180036257e7ce0d1921e357cba5545f F src/vdbe.h 2cfde8249aac55d7f508752e27919e17a30add7bf7444dc221ae5a65d2bafe9d F src/vdbeInt.h e95de5129124d77f01439e6635012adfaf23c0017bff47296126143cf18bd0c6 F src/vdbeapi.c 95001d0f84ee3cda344fed98ca0d7961deb4fc836b83495630d0af1f7cc4789e -F src/vdbeaux.c 2edbf3ca7ea6398301b9655bd2fc6bdb69a55414301098eaba149a3fe43abc47 +F src/vdbeaux.c 38f1e2dcb4571ddc9e75459345ab8f229ad62e0bdc0a1f7545112e6e7f443bbd F src/vdbeblob.c 40028e015fe557a945c99edb6cbf844ea96d853c3e8ac4eb5c1e49bff59f154e F src/vdbemem.c 920285c3b7f5c64369e02da437dab71e9e91862df9c486541c14633739f91d75 -F src/vdbesort.c 3531ae3a431ad6b98b67bd891fb42ec9d66867157188a2b1a9e58c55da6151b2 +F src/vdbesort.c da75f505aba230060ce6472605a4aa6494f73eeb1071e1cc2643c3d4035e671b F src/vdbetrace.c fa3bf238002f0bbbdfb66cc8afb0cea284ff9f148d6439bc1f6f2b4c3b7143f0 -F src/vtab.c 9dd05ccba00bb8ce28c5fb86821c7ced3c1fe32b5312f9afde9910c7671346a4 +F src/vtab.c 043b188f5f3472935c08686b3f006ca07b26fbacb6eb371f8cd4b06602ab094e F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c bbd6838bd79c0a32144d482fb0b6a9d2d1a252fb3b16d5005ec30f2f80413b0d F src/wal.h 606292549f5a7be50b6227bd685fa76e3a4affad71bb8ac5ce4cb5c79f6a176a F src/walker.c d5a94907dcac990e31976be9dc769d17f6a806782593d6aec9d760ee01ec22cd -F src/where.c 90cb93dc8eb9383e72f661b2074551d47ff21e5379f7167f7e078bed436989e9 -F src/whereInt.h 2082fc2bd1eb66cb236a1a3c4b250e33d2bad9e43a0486a2cf9e4e211c58f3eb -F src/wherecode.c cf885ea2d439af9827c5cbab7d4c12be5c079439b7bd12e97151ccfe088c13c0 -F src/whereexpr.c 5cce1fd11876086890a27c05e0cb75ca97ba64ba6984f72154039f1cfd2e69cc -F src/window.c 98b2571c66246bddadf42e76da45ed970fe7518a4c9c1ccc8cdace0711bfabba +F src/where.c 9685d5988b79b93ebbe46941fbdb60d14861bb0fe3f9126117ef1753acc69b64 +F src/whereInt.h 2c6bae136a7c0be6ff75dc36950d1968c67d005c8e51d7a9d77cb996bb4843d9 +F src/wherecode.c 535c8e228478fd971b9a5b6cb6773995b0fbf7020d5989508a5094ce5b8cd95b +F src/whereexpr.c b3bbae199e7acd8d0fa822c9a29cbb822ef2b3d84d68de55a3d60b013f5d5da4 +F src/window.c bf055d1baec203de508c9d7ed3ac20146d5551518f2f77009f781876b8d0fdd5 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 -F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd +F test/affinity2.test da465d3d490ab24ef64f7715b5953343a4967762b9350b29eb1462879ff3fb9e F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 -F test/aggnested.test 18b00de006597e960a6b27ccec51474ac66cf1070a87c1933e5694dc02190ef1 +F test/aggnested.test 12106f0748e8e9bfc1a8e6840e203e051eae06a26ed13fc9fd5db108a8d6db54 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13 F test/alter.test 16ed8d2470193f34bc711e51506ff1211ebfab8025ca3b9510ff2aef139874cb @@ -645,7 +647,7 @@ F test/analyze6.test 6c3f7df2996cb6872f355a6ac1eb6d5de00a5a9288214bad7ef25c97d9c F test/analyze7.test 6ef0b12369f61ddeadc7d8a705c40e6b52cb29f63de3a4c56581b510b46b5783 F test/analyze8.test 36ce54947710bd44e4f9484e1ad07e725ef01a9d7078b417c1bc884356febe4d F test/analyze9.test 9fbf0e0101eef4f5dc149769aa14e10b76ee06e7c28598264b32173cd1999a54 -F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93 +F test/analyzeC.test 489fe2ea3be3f17548e8dd895f1b41c9669b52de1b0861f5bffe6eec46eac710 F test/analyzeD.test e50cd0b3e6063216cc0c88a1776e8645dc0bd65a6bb275769cbee33b7fd8d90c F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d F test/analyzeF.test 9e1a0537949eb5483642b1140a5c39e5b4025939024b935398471fa552f4dabb @@ -726,7 +728,7 @@ F test/capi3d.test aba917805573a03deed961a21f07a5a84505ad0a616f7e3fc1508844a15bc F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe F test/cast.test 3619f0c58c2e4b2a94aa86e75607e497d34ef40ab74418e71aef7b4ca5155895 F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef -F test/check.test e6527bed2b5557ffdbf5680765c4ae6fe61e9b68b7ee69a7f776787a4527b5da +F test/check.test 4b57ecbbb300336382ca21ef983dfa70b291a70ae430690494d13f1629f45a38 F test/checkfault.test da6cb3d50247169efcb20bdf57863a3ccfa1d27d9e55cd324f0680096970f014 F test/chunksize.test 427d87791743486cbf0c3b8c625002f3255cb3a89c6eba655a98923b1387b760 F test/close.test eccbad8ecd611d974cbf47278c3d4e5874faf02d811338d5d348af42d56d647c @@ -747,7 +749,7 @@ F test/colmeta.test 2c765ea61ee37bc43bbe6d6047f89004e6508eb1 F test/colname.test 87ad5458bb8709312dac0d6755fd30e8e4ca83298d0a9ef6e5c24277a3c3390e F test/conflict.test c7cc007e2af151516ddf38f7412fe10d473a694f55e3df437e2c7b31c2590e8d F test/conflict2.test bb0b94cf7196c64a3cbd815c66d3ee98c2fecd9c -F test/conflict3.test a83db76a6c3503b2fa057c7bfb08c318d8a422202d8bc5b86226e078e5b49ff9 +F test/conflict3.test 56d18aedfa521a7ebffadb8254cfff10caf4e49cd8659cb54da39513aed478ba F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4 F test/corrupt.test d7cb0300e4a297147b6a05e92a1684bc8973635c3bcaa3d66e983c9cbdbf47a3 F test/corrupt2.test bb50042cf9a1f1023d73af325d47eb02a6bb11e3c52f8812644b220c5d4bca35 @@ -813,7 +815,7 @@ F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2 F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e F test/distinct.test a1783b960ad8c15a77cd9f207be072898db1026c -F test/distinct2.test 1a01038083535fa9431f4a22587ae58d52d0a794910c36bd2bec07ba1e0e7367 +F test/distinct2.test b854b442111bf362328981f55d39d0df13140383b112057f6e046e311f14e5c3 F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376 F test/e_blobbytes.test 439a945953b35cb6948a552edaec4dc31fd70a05 F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d @@ -937,7 +939,7 @@ F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f F test/fts3corrupt.test 46b9ddda7f6588fd5a5b1f4bb4fc0618dc45010e7dddb8a3a188baf3197177ae F test/fts3corrupt2.test bf55c3fa0b0dc8ea1c0fe5543623bd27714585da6a129038fd6999fe3b0d25f3 F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f -F test/fts3corrupt4.test 9c21ef823a72b0b4a09428d78e63a44c961c19b0821682f4e99cdfe147ac105b +F test/fts3corrupt4.test d5389e14950e57333bfc972f262c90b5ba0e864a958df9e437e3aacd3a5570a7 F test/fts3corrupt5.test 0549f85ec4bd22e992f645f13c59b99d652f2f5e643dac75568bfd23a6db7ed5 F test/fts3cov.test cb932743da52a1c79a1ab8983e26c8121cf02263d6ff16e1f642e6f9b8348338 F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f @@ -967,7 +969,7 @@ F test/fts3query.test ca033ff2ebcc22c69d89032fb0bc1850997d31e7e60ecd26440796ba16 F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef37b99 F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0 F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e -F test/fts3snippet.test dace744104d1a44dc12dc9dd10b8d7542342df503d96942b7c4a55034e761789 +F test/fts3snippet.test 430bb5ace2b31ccd99de4d71775d956da832c114c4b3e39589748f114458647c F test/fts3sort.test ed34c716a11cc2009a35210e84ad5f9c102362ca F test/fts3tok1.test a663f4cac22a9505400bc22aacb818d7055240409c28729669ea7d4cc2120d15 F test/fts3tok_err.test 52273cd193b9036282f7bacb43da78c6be87418d @@ -992,7 +994,7 @@ F test/fts4rename.test 15fd9985c2bce6dea20da2245b22029ec89bd4710ed317c4c53abbe3c F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f757380429 F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d -F test/func.test e4313baba80bf933e58eb89a7c617bec0f0c348c862b096ec4387f36e05ad0a6 +F test/func.test 0889128141b99b38aa9ce78445acfc4c1f9fbe9aa4f51d4c6aff88ae43cf125b F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test 2bb0f31ab7baaed690b962a88544d7be6b34fa389364bc36a44e441ed3e3f1e6 F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f @@ -1013,7 +1015,7 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4 F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5 F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7 F test/fuzzdata7.db e7a86fd83dda151d160445d542e32e5c6019c541b3a74c2a525b6ac640639711 -F test/fuzzdata8.db 2f1375f053b772a48e0820fd3684eac0e109bc37d5612b72b0bb4bcebc1f0133 +F test/fuzzdata8.db dc52be9b732f5bc1cdc0db0ff5b8e69b87bc8989b13a94eb8acaef63897a007c F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8 F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14 F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536 @@ -1027,11 +1029,11 @@ F test/hook2.test b9ff3b8c6519fb67f33192f1afe86e7782ee4ac8 F test/icu.test 41aa8847745a879b897a7febea0f8f9efc8e67fe8bf680589b6e07c7b0a1569a F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607 F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 -F test/in.test 63e642e97bc22c8fd970752fb4f0b3992a957003ea87524fe69e5a700500c500 +F test/in.test 3e9bd58597a444123a40a9ac94cae0fec8897e17e9f519b02fc370bcf5ba5175 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 -F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068 -F test/in5.test 7ae37fcd4a5e198291c6ab5f31a5bb3d15397efe8b75a6736d7a95a7b8dd9e08 +F test/in4.test 0f77b0ff371549e6a119d0356be10bdba72258162e9701e83527a560482f5e98 +F test/in5.test b32ce7f4a93f44c5dee94af16886d922cc16ebe33c8e1765c73d4049d0f4b40f F test/in6.test 62d943a02f722948f4410ee0b53c3cb39acd7c41afb083df8d7004238fe90a20 F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822 F test/incrblob2.test a494c9e848560039a23974b9119cfc2cf3ad3bd15cc2694ee6367ae537ef8f1f @@ -1049,13 +1051,13 @@ F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407 F test/index3.test 51685f39345462b84fcf77eb8537af847fdf438cc96b05c45d6aaca4e473ade0 F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6 F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7 -F test/index6.test 7883c35749e3f38282572194ffdbe7d025b1e2938c1e67da2d408ff3c27d9a46 +F test/index6.test 4d1dd3cab97fba2ddf30bb70afc82eab35bd6e61788b3ac941e55263f81ef7e9 F test/index7.test 1d764c0cca45f5a76150b08e127ccc8d52492cfa788b5fafed4be784a351b020 F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7 F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721 F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e -F test/indexexpr1.test 0f293369ed6f56764cfc3db05685d45469d9e685ba87e3698527049ba359ae24 -F test/indexexpr2.test d319e7d1b1043403f39a20c892d512e02b5549c6004806b977030f2430c60208 +F test/indexexpr1.test fb56f0b9a9d147b38979d154176f150b5e45fdd5d0162fab639a7f9478134fa3 +F test/indexexpr2.test b580f378423bca443ffab47ada677203cfcf8a60f48a8aa20065f27c8f7739b5 F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811 F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7 F test/insert.test 72004f6a900a25bd3f1ce9a72e73d02749644666a8ce6d6d2dba061137e5aa63 @@ -1066,7 +1068,7 @@ F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6 F test/insertfault.test ac63d14ea3b49c573673a572f4014b9117383a03e497c58f308b5c776e4a7f74 F test/instr.test 9a8802f28437d8ade53fedfc47b2ca599b4e48ba F test/instrfault.test 0f870b218ea17cd477bb19ed330eecdb460dd53a -F test/intarray.test 8319986182af37c8eb4879c6bfe9cf0074e9d43b193a4c728a0efa3417c53fb7 +F test/intarray.test bb976b0b3df0ebb6a2eddfb61768280440e672beba5460ed49679ea984ccf440 F test/interrupt.test 16ea879ec728cb76414c148c5f24afd5d1f91054 F test/interrupt2.test e4408ca770a6feafbadb0801e54a0dcd1a8d108d F test/intpkey.test ac71107a49a06492b69b82aafaf225400598d3c8 @@ -1079,7 +1081,7 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4 F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b F test/istrue.test 75327829744e65cc8700e69340b8e6c192e10e39dfae7ccb0e970d3c4f49090a -F test/join.test d53a3662762eff50b65da8775201e609878a27dd0885a1ae7bcde9bb46cecbc5 +F test/join.test 6ce8296a08e78632c322cde0add78a7ce05466c3d9ec7d5130b38b5b489e7c27 F test/join2.test 10f7047e723ebd68b2f47189be8eed20451a6f665d8bf46f1774c640d1062417 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 @@ -1152,7 +1154,7 @@ F test/memsubsys2.test 3e4a8d0c05fd3e5fa92017c64666730a520c7e08 F test/minmax.test 6751e87b409fe11b02e70a306d846fa544e25a41 F test/minmax2.test dae92964ac87c1d2ef978c582e81a95e11c00f1cbef68980bfb2abaf10315063 F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354 -F test/minmax4.test 838fe32b812dc50778be3799767cefb5ff59bb04cff81d4f12c0708642f65151 +F test/minmax4.test 272ca395257f05937dc96441c9dde4bc9fbf116a8d4fa02baeb0d13d50e36c87 F test/misc1.test 7ce84b25df9872e7d7878613a96815d2ba5bc974ac4e15a50118dde8f3917599 F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d @@ -1184,6 +1186,7 @@ F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161 F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934 F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed3f18 F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3 +F test/nulls1.test 725fb4d99db2ddcce59ca6bf847cd92db8f1af861785918892f84ac3bcd4223d F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1 F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823 F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2 @@ -1218,12 +1221,12 @@ F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff F test/permutations.test 4282fb00e5ac0f8c2cd1be62652f6da4ac03ce3c58b7d785fa17f4684492a0e0 -F test/pg_common.tcl 4740dc35190d6acdab14c097783331361301ab504a94d948f6afbb56ce0a51e8 +F test/pg_common.tcl 222a1bad1c41c308fa366313cd7b51b3be7e9b21c8736a421b974ac941693b54 F test/pragma.test cf066fe0f7f5d49f4758de4986407b8676c61aaa7871599340d64f42a8edc352 F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c0df9 F test/pragma4.test 1cb4b32f1a304ed9e291d7c4d49c91c2c8dc1b9450e6d2c1198b2cc895d40d77 -F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983 +F test/pragma5.test 2be6a44c91e8585ccb4c71c5f221ccebe0692a49557215a912916ed391188959 F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8 F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9 F test/printf.test 0300699733e53101b2ce48800518427249edd4053bb50fa0621c6607482f0fdb @@ -1269,7 +1272,7 @@ F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256 F test/rowvalue4.test 02e35f7762371c2f57ebd856aa056eac56cb27ef7715a0bb31eac1895a745356 F test/rowvalue5.test c81c7d8cf36711ab37675ad7376084ae2a359cb6 F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087 -F test/rowvalue7.test 5d06ff19d9e6969e574a2e662a531dd0c67801a8 +F test/rowvalue7.test c1cbdbf407029db01f87764097c6ac02a1c5a37efd2776eff32a9cdfdf6f2dba F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0 F test/rowvalue9.test d8dd2c6ecac432dadaa79e41dc2434f007be1b6b F test/rowvaluefault.test 7cd9ccc6c2fbdd881672984087aad0491bb75504 @@ -1397,7 +1400,7 @@ F test/tabfunc01.test 20e98ffe55f35d8d33fd834ca8bf9d4b637e560af8fcd00464b4154d90 F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132 F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 -F test/tclsqlite.test 7ea484c9fb74d47d48c62b18a97b287c418b0c3aeacc639133b04a7e426d58af +F test/tclsqlite.test 47dded95a07b8916da62902724ce3a59d60331ed5ba2bfe42d1189ce0413c0f3 F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08 F test/tempdb2.test 353864e96fd3ae2f70773d0ffbf8b1fe48589b02c2ec05013b540879410c3440 F test/tempfault.test 0c0d349c9a99bf5f374655742577f8712c647900 @@ -1420,6 +1423,7 @@ F test/threadtest3.c 4de1edf7cddac6195acfaea56cccb8572df803854531251784f6b8ca46f F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925 F test/time-wordcount.sh 8e0b0f8109367827ad5d58f5cc849705731e4b90 F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c +F test/tkt-18458b1a.test c543c4b8e8c7c2200579a635e72c15bc374a92d44eddb1d588d4fdeca9cca532 F test/tkt-26ff0c2d1e.test c15bec890c4d226c0da2f35ff30f9e84c169cfef90e73a8cb5cec11d723dfa96 F test/tkt-2a5629202f.test 0521bd25658428baa26665aa53ffed9367d33af2 F test/tkt-2d1a5c67d.test be1326f3061caec85085f4c9ee4490561ca037c0 @@ -1455,6 +1459,7 @@ F test/tkt-9a8b09f8e6.test b2ef151d0984b2ebf237760dbeaa50724e5a0667 F test/tkt-9d68c883.test 16f7cb96781ba579bc2e19bb14b4ad609d9774b6 F test/tkt-9f2eb3abac.test cb6123ac695a08b4454c3792fbe85108f67fabf8 F test/tkt-a7b7803e.test 159ef554234fa1f9fb318c751b284bd1cf858da4 +F test/tkt-a7debbe0.test 65a647034e3416d068f81e7d86fffc07edfae371c70b8761714edb56ec1c7521 F test/tkt-a8a0d2996a.test 002e1cde8fc30c39611b52cf981c88200b858765748556822da72e0d32fac73e F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550 F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0 @@ -1569,7 +1574,7 @@ F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6 F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76 F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94 F test/transitive1.test 293300f46916569f08875cdb2fe2134be2c27677 -F test/trigger1.test 17e4b43e656c4b354df2357634a6ba887990f510c43629f4feca30e3338d2a61 +F test/trigger1.test 6be279c9d48b25320eab68c30fd5268ab787955679f4c584128f71800247fb50 F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6 F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945 F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359 @@ -1602,7 +1607,7 @@ F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97 F test/unordered.test ffeea7747d5ba962a8009a20b7e53d68cbae05b063604c68702c5998eb50c981 F test/update.test 1148de8d913e9817717990603aadeca07aab9ddbb10a30f167cbfd8d3a3ccb60 F test/update2.test 67455bc61fcbcf96923c45b3bc4f87bc72be7d67575ad35f134906148c7b06d3 -F test/upsert1.test 994bde41800bb77dbe32fcd2e1f6c4b49cc9f2c6cd345731c774dff02b51c110 +F test/upsert1.test 9b115320149e6d72db64511a373c522746c2a2156efdbdb52add33504f66c989 F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09 F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5 @@ -1620,8 +1625,8 @@ F test/vacuum5.test 263b144d537e92ad8e9ca8a73cc6e1583f41cfd0dda9432b87f7806174a2 F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2 F test/varint.test bbce22cda8fc4d135bcc2b589574be8410614e62 F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661 -F test/view.test c1e64ff5a860fdbb7b52add0996af2ee1af563ddf2e86b964d15d04d81a001be -F test/vtab1.test fa6baded08fdadd6f416a9c54956c049ae327b9bdd05d25bf8163f65e65e849c +F test/view.test 10ea54300a097d7c0337fd104abffe4a4786d1598b94017a37efe0e0d3e04dd5 +F test/vtab1.test c5d9e90ed02bcacd776dcbb7360199d290f7f53c26b484ddece543060c54319f F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c84082 F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3 @@ -1636,7 +1641,7 @@ F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292 F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96 F test/vtabE.test 2a143fe75a11275781d1fd1988d86b66a3f69cb98f4add62e3da8fd0f637b45f F test/vtabF.test 1918844c7c902f6a16c8dacf1ec8f84886d6e78b -F test/vtabH.test e65540eed0f7434cdf0b160374570b51f3e3179548f0fa5e99b1d33f8dcdf9a0 +F test/vtabH.test 2efb5a24b0bb50796b21eca23032cfb77abfa4b0c03938e38ce5897abac404ca F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f F test/vtabJ.test d7b73675708cf63cfcb9d443bb451fc01a028347275b7311e51f9fdf3ca6757f F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783 @@ -1680,7 +1685,7 @@ F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2a F test/walvfs.test f1accd66c876e3a0f6b4bef5b18d13411062d0ff0a0016e32bb41570474e99fc F test/wapp.tcl b440cd8cf57953d3a49e7ee81e6a18f18efdaf113b69f7d8482b0710a64566ec F test/wapptest.tcl 3090239c59379d41e1a0644feb6683082fdb86edfab0c668973f8003f22c0e5d x -F test/where.test d640c16d33ae671c7583fd575d1a64fd55194dcc4393b877b3028db9ddba5a3b +F test/where.test 19c709c9f0f6ed12c23f909f6592aa55fba34269d5a2898537aa27a22b9ce650 F test/where2.test 478d2170637b9211f593120648858593bf2445a1 F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcda2c F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8 @@ -1695,7 +1700,7 @@ F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6 F test/whereD.test 711d4df58d6d4fb9b3f5ce040b818564198be002 F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f F test/whereF.test 3d9412b1199d3e2bed34fcb76b4c48d0bf4df95d27e3f8dd27b6f8b4716d0d89 -F test/whereG.test 0158783235a6dd82fc0e37652b8522b186b9510594ac0a4bff0c4101b4396a52 +F test/whereG.test 4cda56de49f0c7d9a4f2590a3ddc5f79a7f2a03d2229d0f5bb5d3981ce57f293 F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2 F test/whereI.test a2874062140ed4aba9ffae76e6190a3df6fc73d1373fdfa8fd632945082a5364 F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a @@ -1719,13 +1724,15 @@ F test/window4.test 807f3e6b15f9338e5b9742b87c5c7ca825b42b9657fde6096e8901193708 F test/window5.test d328dd18221217c49c144181975eea17339eaeaf0e9aa558cee3afb84652821e F test/window6.test f8d674254b23289cc17c84d79dec7eda7caa1dfb7836c43122cfdf3640d1df32 F test/window7.tcl 6a1210f05d40ec89c22960213a22cd3f98d4e2f2eb20646c83c8c30d4d76108f -F test/window7.test ce7f865241fdd1c5c4db869cd7bb2986c3be836bc2e73649a6846dd920f63e0f -F test/window8.tcl 9e9a82ae9eea90a4a83481d641a812b974980c38f9247f3b89a6e3c8bed45518 -F test/window8.test df187dc19921f7be0ab709d531d681bd80ccaac96a913a89ecee8b272b91d43f -F test/window9.test 1fd3ff49119c28006e8f55e48e8425bf4d5bf560195c4df470ef147641004f56 +F test/window7.test 1d31276961ae7801edc72173edaf7593e3cbc79c06d1f1f09e20d8418af403cd +F test/window8.tcl f2711aa3571e4e6b0dad98db8d95fd6cb8d9db0c92bbdf535f153b07606a1ce2 +F test/window8.test c4331b27a6f66d69fa8f8bab10cc731db1a81d293ae108a68f7c3487fa94e65b +F test/window9.test 20a6b590be718b6bc98a5356d4396d6cdf19329c547da084fa225b92d68e1693 +F test/windowA.test 6d63dc1260daa17141a55007600581778523a8b420629f1282d2acfc36af23be +F test/windowB.test be2ecc1298021e87eef375af35906288cc929fc21f2651139f7dd50a5844b120 F test/windowerr.tcl f5acd6fbc210d7b5546c0e879d157888455cd4a17a1d3f28f07c1c8a387019e0 F test/windowerr.test a8b752402109c15aa1c5efe1b93ccb0ce1ef84fa964ae1cd6684dd0b3cc1819b -F test/windowfault.test 403693d7d951c5473f052f7ecddb61ed15ac9d212f238b8904ea270ba90f83e5 +F test/windowfault.test a90b397837209f15e54afa62e8be39b2759a0101fae04e05a08bcc50e243a452 F test/with1.test d32792084dcb5f6c047d77bb8a032822ef9fe050ade07d0aeffa37753a05e3c9 F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab F test/with3.test b5f1372097690c6ef84db2f13fc7e64a88c7263c3f88493605f90597e8a68d45 @@ -1765,8 +1772,8 @@ F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce F tool/index_usage.c 9ec344d29cbeb03fdc0fce668eedfb7495792170de933adf95cf8d6904a166ad F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f -F tool/lemon.c cc43148d2793ab93668e74a6a6319bb71c2e65c1ffcd6deeaa59e12be9362a43 -F tool/lempar.c 4b868d0a5eb9a67cd1b546274227c0d449dad073c663b331b686fa2253e1c86f +F tool/lemon.c 61d5f0af1eff8f754b75ddca668c9897fd30759e389bfffb42ce9e4d38fd4746 +F tool/lempar.c eb2841e2a7fd484cf44b1f526b06e7ab0f216d2f41818bf9485e8f38e3d1db19 F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9 F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862 F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca @@ -1774,12 +1781,12 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439 F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3 -F tool/mkkeywordhash.c 537b1a11ec1829b51b633da3ba2cc889b4a3f7356b06a07423b6d4cce92c2350 +F tool/mkkeywordhash.c bc5bcc92ebcaf15345346be7cf2204b83ed649b5208234adb5e543c061209bbf F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c F tool/mkopcodeh.tcl 352a4319c0ad869eb26442bf7c3b015aa15594c21f1cce5a6420dbe999367c21 F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa -F tool/mkpragmatab.tcl 15241b904c222876bedbbad42ba2fa529bd2cc20e6fbdf51cbed3a5837465069 +F tool/mkpragmatab.tcl ee69ec15f46275c873083e7e643adda86b3368cf587dab6b69eb7aa324d8242d F tool/mkshellc.tcl 70a9978e363b0f3280ca9ce1c46d72563ff479c1930a12a7375e3881b7325712 F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97 @@ -1846,7 +1853,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e30c7414fe483fcb68aeedd364dc5a3da62b01a80808a917016a9f148f1f3130 8c44b02f1479cec61554800702a3c1d806e4ee64b41ba2af17320f62794a02fe -R 4e1916fb0cea7cd10e2fe4a7fca0c441 -U dan -Z 9ccdede6ff16576fa964eaec773d7dc9 +P 5b4689d89cd27b238586ddee638b856145a9731ff70ffcb1659613528b792167 ca564d4b5b19fe56842a04f31bb61352e6ae9d72a7e7634eb27ebcf5f670545a +R 1c093b6224ac218a49aceeb65fb90195 +U drh +Z 90e6dfcc263ede0d7162600d2446fabb diff --git a/manifest.uuid b/manifest.uuid index d79520010c..9519e15ff8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5b4689d89cd27b238586ddee638b856145a9731ff70ffcb1659613528b792167 \ No newline at end of file +27eb223690989a294c5aad7a8ab1927904b1041e36ce7a0c04800bce49ec9142 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 6bcf97c3b3..d875fd870e 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1451,7 +1451,9 @@ static void decodeIntArray( if( sqlite3_strglob("unordered*", z)==0 ){ pIndex->bUnordered = 1; }else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){ - pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3)); + int sz = sqlite3Atoi(z+3); + if( sz<2 ) sz = 2; + pIndex->szIdxRow = sqlite3LogEst(sz); }else if( sqlite3_strglob("noskipscan*", z)==0 ){ pIndex->noSkipScan = 1; } diff --git a/src/attach.c b/src/attach.c index 7a39674081..c40bcaa58e 100644 --- a/src/attach.c +++ b/src/attach.c @@ -299,6 +299,7 @@ static void detachFunc( sqlite3 *db = sqlite3_context_db_handle(context); int i; Db *pDb = 0; + HashElem *pEntry; char zErr[128]; UNUSED_PARAMETER(NotUsed); @@ -323,6 +324,18 @@ static void detachFunc( goto detach_error; } + /* If any TEMP triggers reference the schema being detached, move those + ** triggers to reference the TEMP schema itself. */ + assert( db->aDb[1].pSchema ); + pEntry = sqliteHashFirst(&db->aDb[1].pSchema->trigHash); + while( pEntry ){ + Trigger *pTrig = (Trigger*)sqliteHashData(pEntry); + if( pTrig->pTabSchema==pDb->pSchema ){ + pTrig->pTabSchema = pTrig->pSchema; + } + pEntry = sqliteHashNext(pEntry); + } + sqlite3SchemaDisconnect(db, i, 0); sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; @@ -561,6 +574,7 @@ int sqlite3FixExpr( Expr *pExpr /* The expression to be fixed to one database */ ){ while( pExpr ){ + ExprSetProperty(pExpr, EP_Indirect); if( pExpr->op==TK_VARIABLE ){ if( pFix->pParse->db->init.busy ){ pExpr->op = TK_NULL; diff --git a/src/btree.c b/src/btree.c index 932ce04359..7ff91e667b 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4879,6 +4879,7 @@ static int accessPayload( assert( aWrite>=pBufStart ); /* due to (6) */ memcpy(aSave, aWrite, 4); rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1)); + if( rc && nextPage>pBt->nPage ) rc = SQLITE_CORRUPT_BKPT; nextPage = get4byte(aWrite); memcpy(aWrite, aSave, 4); }else @@ -6991,7 +6992,8 @@ static int pageInsertArray( while( 1 /*Exit by break*/ ){ int sz, rc; u8 *pSlot; - sz = cachedCellSize(pCArray, i); + assert( pCArray->szCell[i]!=0 ); + sz = pCArray->szCell[i]; if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){ if( (pData - pBegin)nOverflow)); if( pOld->nOverflow>0 ){ - if( limitaiOvfl[0] ){ + if( NEVER(limitaiOvfl[0]) ){ rc = SQLITE_CORRUPT_BKPT; goto balance_cleanup; } @@ -8475,7 +8478,9 @@ static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){ Pgno ovflPgno; /* Next overflow page to write */ u32 ovflPageSize; /* Size to write on overflow page */ - if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){ + if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd + || pCur->info.pPayload < pPage->aData + pPage->cellOffset + ){ return SQLITE_CORRUPT_BKPT; } /* Overwrite the local portion first */ diff --git a/src/build.c b/src/build.c index d583da0be0..4f487de6af 100644 --- a/src/build.c +++ b/src/build.c @@ -1498,7 +1498,7 @@ void sqlite3AddPrimaryKey( pTab->keyConf = (u8)onError; assert( autoInc==0 || autoInc==1 ); pTab->tabFlags |= autoInc*TF_Autoincrement; - if( pList ) pParse->iPkSortOrder = pList->a[0].sortOrder; + if( pList ) pParse->iPkSortOrder = pList->a[0].sortFlags; }else if( autoInc ){ #ifndef SQLITE_OMIT_AUTOINCREMENT sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an " @@ -1949,7 +1949,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ if( IN_RENAME_OBJECT ){ sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey); } - pList->a[0].sortOrder = pParse->iPkSortOrder; + pList->a[0].sortFlags = pParse->iPkSortOrder; assert( pParse->pNewTable==pTab ); pTab->iPKey = -1; sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0, @@ -3209,6 +3209,27 @@ Index *sqlite3AllocateIndexObject( return p; } +/* +** If expression list pList contains an expression that was parsed with +** an explicit "NULLS FIRST" or "NULLS LAST" clause, leave an error in +** pParse and return non-zero. Otherwise, return zero. +*/ +int sqlite3HasExplicitNulls(Parse *pParse, ExprList *pList){ + if( pList ){ + int i; + for(i=0; inExpr; i++){ + if( pList->a[i].bNulls ){ + u8 sf = pList->a[i].sortFlags; + sqlite3ErrorMsg(pParse, "unsupported use of NULLS %s", + (sf==0 || sf==3) ? "FIRST" : "LAST" + ); + return 1; + } + } + } + return 0; +} + /* ** Create a new index for an SQL table. pName1.pName2 is the name of the index ** and pTblList is the name of the table that is to be indexed. Both will @@ -3260,6 +3281,9 @@ void sqlite3CreateIndex( if( !IsSharedSchema(db) && SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto exit_create_index; } + if( sqlite3HasExplicitNulls(pParse, pList) ){ + goto exit_create_index; + } /* ** Find the table that is to be indexed. Return early if not found. @@ -3424,7 +3448,7 @@ void sqlite3CreateIndex( sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); if( pList==0 ) goto exit_create_index; assert( pList->nExpr==1 ); - sqlite3ExprListSetSortOrder(pList, sortOrder); + sqlite3ExprListSetSortOrder(pList, sortOrder, SQLITE_SO_UNDEFINED); }else{ sqlite3ExprListCheckLength(pParse, pList, "index"); if( pParse->nErr ) goto exit_create_index; @@ -3542,7 +3566,7 @@ void sqlite3CreateIndex( goto exit_create_index; } pIndex->azColl[i] = zColl; - requestedSortOrder = pListItem->sortOrder & sortOrderMask; + requestedSortOrder = pListItem->sortFlags & sortOrderMask; pIndex->aSortOrder[i] = (u8)requestedSortOrder; } @@ -4761,7 +4785,8 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ const char *zColl = pIdx->azColl[i]; pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 : sqlite3LocateCollSeq(pParse, zColl); - pKey->aSortOrder[i] = pIdx->aSortOrder[i]; + pKey->aSortFlags[i] = pIdx->aSortOrder[i]; + assert( 0==(pKey->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) ); } if( pParse->nErr ){ assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ ); diff --git a/src/expr.c b/src/expr.c index e00b319ed2..949758b10e 100644 --- a/src/expr.c +++ b/src/expr.c @@ -44,7 +44,6 @@ char sqlite3TableColumnAffinity(Table *pTab, int iCol){ */ char sqlite3ExprAffinity(Expr *pExpr){ int op; - if( pExpr->flags & EP_Generic ) return 0; while( ExprHasProperty(pExpr, EP_Skip) ){ assert( pExpr->op==TK_COLLATE ); pExpr = pExpr->pLeft; @@ -106,10 +105,22 @@ Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ } /* -** Skip over any TK_COLLATE operators and any unlikely() -** or likelihood() function at the root of an expression. +** Skip over any TK_COLLATE operators. */ Expr *sqlite3ExprSkipCollate(Expr *pExpr){ + while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){ + assert( pExpr->op==TK_COLLATE ); + pExpr = pExpr->pLeft; + } + return pExpr; +} + +/* +** Skip over any TK_COLLATE operators and/or any unlikely() +** or likelihood() or likely() functions at the root of an +** expression. +*/ +Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){ while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){ if( ExprHasProperty(pExpr, EP_Unlikely) ){ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); @@ -144,7 +155,6 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ Expr *p = pExpr; while( p ){ int op = p->op; - if( p->flags & EP_Generic ) break; if( op==TK_REGISTER ) op = p->op2; if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER) && p->y.pTab!=0 @@ -1325,12 +1335,7 @@ static int gatherSelectWindowsCallback(Walker *pWalker, Expr *pExpr){ assert( pWin ); assert( IsWindowFunc(pExpr) ); assert( pWin->ppThis==0 ); - if( pSelect->pWin ){ - pSelect->pWin->ppThis = &pWin->pNextWin; - } - pWin->pNextWin = pSelect->pWin; - pWin->ppThis = &pSelect->pWin; - pSelect->pWin = pWin; + sqlite3WindowLink(pSelect, pWin); } return WRC_Continue; } @@ -1404,8 +1409,9 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){ } pItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan); - pItem->sortOrder = pOldItem->sortOrder; + pItem->sortFlags = pOldItem->sortFlags; pItem->done = 0; + pItem->bNulls = pOldItem->bNulls; pItem->bSpanIsTab = pOldItem->bSpanIsTab; pItem->bSorterRef = pOldItem->bSorterRef; pItem->u = pOldItem->u; @@ -1516,7 +1522,7 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){ #ifndef SQLITE_OMIT_WINDOWFUNC pNew->pWin = 0; pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn); - if( p->pWin ) gatherSelectWindows(pNew); + if( p->pWin && db->mallocFailed==0 ) gatherSelectWindows(pNew); #endif pNew->selId = p->selId; *pp = pNew; @@ -1625,6 +1631,10 @@ ExprList *sqlite3ExprListAppendVector( for(i=0; inId; i++){ Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i); + assert( pSubExpr!=0 || db->mallocFailed ); + assert( pSubExpr==0 || pSubExpr->iTable==0 ); + if( pSubExpr==0 ) continue; + pSubExpr->iTable = pColumns->nId; pList = sqlite3ExprListAppend(pParse, pList, pSubExpr); if( pList ){ assert( pList->nExpr==iFirst+i+1 ); @@ -1657,15 +1667,34 @@ vector_append_error: /* ** Set the sort order for the last element on the given ExprList. */ -void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder){ +void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder, int eNulls){ + struct ExprList_item *pItem; if( p==0 ) return; - assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC>=0 && SQLITE_SO_DESC>0 ); assert( p->nExpr>0 ); - if( iSortOrder<0 ){ - assert( p->a[p->nExpr-1].sortOrder==SQLITE_SO_ASC ); - return; + + assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC==0 && SQLITE_SO_DESC>0 ); + assert( iSortOrder==SQLITE_SO_UNDEFINED + || iSortOrder==SQLITE_SO_ASC + || iSortOrder==SQLITE_SO_DESC + ); + assert( eNulls==SQLITE_SO_UNDEFINED + || eNulls==SQLITE_SO_ASC + || eNulls==SQLITE_SO_DESC + ); + + pItem = &p->a[p->nExpr-1]; + assert( pItem->bNulls==0 ); + if( iSortOrder==SQLITE_SO_UNDEFINED ){ + iSortOrder = SQLITE_SO_ASC; + } + pItem->sortFlags = (u8)iSortOrder; + + if( eNulls!=SQLITE_SO_UNDEFINED ){ + pItem->bNulls = 1; + if( iSortOrder!=eNulls ){ + pItem->sortFlags |= KEYINFO_ORDER_BIGNULL; + } } - p->a[p->nExpr-1].sortOrder = (u8)iSortOrder; } /* @@ -2164,27 +2193,30 @@ int sqlite3ExprCanBeNull(const Expr *p){ */ int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){ u8 op; + int unaryMinus = 0; if( aff==SQLITE_AFF_BLOB ) return 1; - while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; } + while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ + if( p->op==TK_UMINUS ) unaryMinus = 1; + p = p->pLeft; + } op = p->op; if( op==TK_REGISTER ) op = p->op2; switch( op ){ case TK_INTEGER: { - return aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC; + return aff>=SQLITE_AFF_NUMERIC; } case TK_FLOAT: { - return aff==SQLITE_AFF_REAL || aff==SQLITE_AFF_NUMERIC; + return aff>=SQLITE_AFF_NUMERIC; } case TK_STRING: { - return aff==SQLITE_AFF_TEXT; + return !unaryMinus && aff==SQLITE_AFF_TEXT; } case TK_BLOB: { - return 1; + return !unaryMinus; } case TK_COLUMN: { assert( p->iTable>=0 ); /* p cannot be part of a CHECK constraint */ - return p->iColumn<0 - && (aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC); + return aff>=SQLITE_AFF_NUMERIC && p->iColumn<0; } default: { return 0; @@ -2367,7 +2399,7 @@ static int sqlite3InRhsIsConstant(Expr *pIn){ #ifndef SQLITE_OMIT_SUBQUERY int sqlite3FindInIndex( Parse *pParse, /* Parsing context */ - Expr *pX, /* The right-hand side (RHS) of the IN operator */ + Expr *pX, /* The IN expression */ u32 inFlags, /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */ int *prRhsHasNull, /* Register holding NULL status. See notes */ int *aiMap, /* Mapping from Index fields to RHS fields */ @@ -2792,7 +2824,7 @@ void sqlite3CodeRhsOfIN( int i; ExprList *pList = pExpr->x.pList; struct ExprList_item *pItem; - int r1, r2, r3; + int r1, r2; affinity = sqlite3ExprAffinity(pLeft); if( affinity<=SQLITE_AFF_NONE ){ affinity = SQLITE_AFF_BLOB; @@ -2820,9 +2852,9 @@ void sqlite3CodeRhsOfIN( } /* Evaluate the expression and insert it into the temp table */ - r3 = sqlite3ExprCodeTarget(pParse, pE2, r1); - sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1); - sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r3, 1); + sqlite3ExprCode(pParse, pE2, r1); + sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r1, 1); } sqlite3ReleaseTempReg(pParse, r1); sqlite3ReleaseTempReg(pParse, r2); @@ -2848,7 +2880,7 @@ void sqlite3CodeRhsOfIN( ** ** The pExpr parameter is the SELECT or EXISTS operator to be coded. ** -** The register that holds the result. For a multi-column SELECT, +** Return the register that holds the result. For a multi-column SELECT, ** the result is stored in a contiguous array of registers and the ** return value is the register of the left-most result column. ** Return 0 if an error occurs. @@ -3092,13 +3124,21 @@ static void sqlite3ExprCodeIN( int r2, regToFree; int regCkNull = 0; int ii; + int bLhsReal; /* True if the LHS of the IN has REAL affinity */ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); if( destIfNull!=destIfFalse ){ regCkNull = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_BitAnd, rLhs, rLhs, regCkNull); } + bLhsReal = sqlite3ExprAffinity(pExpr->pLeft)==SQLITE_AFF_REAL; for(ii=0; iinExpr; ii++){ - r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, ®ToFree); + if( bLhsReal ){ + r2 = regToFree = sqlite3GetTempReg(pParse); + sqlite3ExprCode(pParse, pList->a[ii].pExpr, r2); + sqlite3VdbeAddOp4(v, OP_Affinity, r2, 1, 0, "E", P4_STATIC); + }else{ + r2 = sqlite3ExprCodeTemp(pParse, pList->a[ii].pExpr, ®ToFree); + } if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){ sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull); } @@ -3383,7 +3423,7 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){ ** the correct value for the expression. */ static void exprToRegister(Expr *pExpr, int iReg){ - Expr *p = sqlite3ExprSkipCollate(pExpr); + Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr); p->op2 = p->op; p->op = TK_REGISTER; p->iTable = iReg; @@ -3500,7 +3540,19 @@ expr_code_doover: if( iTab<0 ){ if( pParse->iSelfTab<0 ){ /* Generating CHECK constraints or inserting into partial index */ - return pExpr->iColumn - pParse->iSelfTab; + assert( pExpr->y.pTab!=0 ); + assert( pExpr->iColumn>=XN_ROWID ); + assert( pExpr->iColumny.pTab->nCol ); + if( pExpr->iColumn>=0 + && pExpr->y.pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL + ){ + sqlite3VdbeAddOp2(v, OP_SCopy, pExpr->iColumn - pParse->iSelfTab, + target); + sqlite3VdbeAddOp1(v, OP_RealAffinity, target); + return target; + }else{ + return pExpr->iColumn - pParse->iSelfTab; + } }else{ /* Coding an expression that is part of an index where column names ** in the index refer to the table to which the index belongs */ @@ -3895,8 +3947,8 @@ expr_code_doover: pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft); } assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT ); - if( pExpr->iTable - && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft)) + if( pExpr->iTable!=0 + && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft)) ){ sqlite3ErrorMsg(pParse, "%d columns assigned %d values", pExpr->iTable, n); @@ -3999,10 +4051,23 @@ expr_code_doover: break; } + /* TK_IF_NULL_ROW Expr nodes are inserted ahead of expressions + ** that derive from the right-hand table of a LEFT JOIN. The + ** Expr.iTable value is the table number for the right-hand table. + ** The expression is only evaluated if that table is not currently + ** on a LEFT JOIN NULL row. + */ case TK_IF_NULL_ROW: { int addrINR; + u8 okConstFactor = pParse->okConstFactor; addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable); + /* Temporarily disable factoring of constant expressions, since + ** even though expressions may appear to be constant, they are not + ** really constant because they originate from the right-hand side + ** of a LEFT JOIN. */ + pParse->okConstFactor = 0; inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); + pParse->okConstFactor = okConstFactor; sqlite3VdbeJumpHere(v, addrINR); sqlite3VdbeChangeP3(v, addrINR, inReg); break; @@ -4178,7 +4243,7 @@ int sqlite3ExprCodeAtInit( */ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){ int r2; - pExpr = sqlite3ExprSkipCollate(pExpr); + pExpr = sqlite3ExprSkipCollateAndLikely(pExpr); if( ConstFactorOk(pParse) && pExpr->op!=TK_REGISTER && sqlite3ExprIsConstantNotJoin(pExpr) @@ -4909,7 +4974,7 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){ for(i=0; inExpr; i++){ Expr *pExprA = pA->a[i].pExpr; Expr *pExprB = pB->a[i].pExpr; - if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1; + if( pA->a[i].sortFlags!=pB->a[i].sortFlags ) return 1; if( sqlite3ExprCompare(0, pExprA, pExprB, iTab) ) return 1; } return 0; @@ -4921,20 +4986,23 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){ */ int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){ return sqlite3ExprCompare(0, - sqlite3ExprSkipCollate(pA), - sqlite3ExprSkipCollate(pB), + sqlite3ExprSkipCollateAndLikely(pA), + sqlite3ExprSkipCollateAndLikely(pB), iTab); } /* ** Return non-zero if Expr p can only be true if pNN is not NULL. +** +** Or if seenNot is true, return non-zero if Expr p can only be +** non-NULL if pNN is not NULL */ static int exprImpliesNotNull( Parse *pParse, /* Parsing context */ Expr *p, /* The expression to be checked */ Expr *pNN, /* The expression that is NOT NULL */ int iTab, /* Table being evaluated */ - int seenNot /* True if p is an operand of NOT */ + int seenNot /* Return true only if p can be any non-NULL value */ ){ assert( p ); assert( pNN ); @@ -4946,19 +5014,19 @@ static int exprImpliesNotNull( if( seenNot && ExprHasProperty(p, EP_xIsSelect) ) return 0; assert( ExprHasProperty(p,EP_xIsSelect) || (p->x.pList!=0 && p->x.pList->nExpr>0) ); - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot); + return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); } case TK_BETWEEN: { ExprList *pList = p->x.pList; assert( pList!=0 ); assert( pList->nExpr==2 ); if( seenNot ) return 0; - if( exprImpliesNotNull(pParse, pList->a[0].pExpr, pNN, iTab, seenNot) - || exprImpliesNotNull(pParse, pList->a[1].pExpr, pNN, iTab, seenNot) + if( exprImpliesNotNull(pParse, pList->a[0].pExpr, pNN, iTab, 1) + || exprImpliesNotNull(pParse, pList->a[1].pExpr, pNN, iTab, 1) ){ return 1; } - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot); + return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); } case TK_EQ: case TK_NE: @@ -4968,20 +5036,21 @@ static int exprImpliesNotNull( case TK_GE: case TK_PLUS: case TK_MINUS: + case TK_BITOR: + case TK_LSHIFT: + case TK_RSHIFT: + case TK_CONCAT: + seenNot = 1; + /* Fall thru */ case TK_STAR: case TK_REM: case TK_BITAND: - case TK_BITOR: - case TK_SLASH: - case TK_LSHIFT: - case TK_RSHIFT: - case TK_CONCAT: { + case TK_SLASH: { if( exprImpliesNotNull(pParse, p->pRight, pNN, iTab, seenNot) ) return 1; /* Fall thru into the next case */ } case TK_SPAN: case TK_COLLATE: - case TK_BITNOT: case TK_UPLUS: case TK_UMINUS: { return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot); @@ -4989,8 +5058,9 @@ static int exprImpliesNotNull( case TK_TRUTH: { if( seenNot ) return 0; if( p->op2!=TK_IS ) return 0; - return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot); + return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); } + case TK_BITNOT: case TK_NOT: { return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1); } @@ -5056,7 +5126,6 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune; switch( pExpr->op ){ case TK_ISNOT: - case TK_NOT: case TK_ISNULL: case TK_NOTNULL: case TK_IS: @@ -5065,7 +5134,6 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ case TK_IN: case TK_FUNCTION: testcase( pExpr->op==TK_ISNOT ); - testcase( pExpr->op==TK_NOT ); testcase( pExpr->op==TK_ISNULL ); testcase( pExpr->op==TK_NOTNULL ); testcase( pExpr->op==TK_IS ); @@ -5081,6 +5149,18 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ } return WRC_Prune; + case TK_AND: + if( sqlite3ExprImpliesNonNullRow(pExpr->pLeft, pWalker->u.iCur) + && sqlite3ExprImpliesNonNullRow(pExpr->pRight, pWalker->u.iCur) + ){ + pWalker->eCode = 1; + } + return WRC_Prune; + + case TK_BETWEEN: + sqlite3WalkExpr(pWalker, pExpr->pLeft); + return WRC_Prune; + /* Virtual tables are allowed to use constraints like x=NULL. So ** a term of the form x=y does not prove that y is not null if x ** is the column of a virtual table */ @@ -5101,6 +5181,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ ){ return WRC_Prune; } + default: return WRC_Continue; } @@ -5130,7 +5211,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ */ int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){ Walker w; - p = sqlite3ExprSkipCollate(p); + p = sqlite3ExprSkipCollateAndLikely(p); while( p ){ if( p->op==TK_NOTNULL ){ p = p->pLeft; @@ -5236,7 +5317,10 @@ static int exprSrcCount(Walker *pWalker, Expr *pExpr){ } if( inThis++; - }else{ + }else if( nSrc==0 || pExpr->iTablea[0].iCursor ){ + /* In a well-formed parse tree (no name resolution errors), + ** TK_COLUMN nodes with smaller Expr.iTable values are in an + ** outer context. Those are the only ones to count as "other" */ p->nOther++; } } @@ -5253,8 +5337,9 @@ int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){ Walker w; struct SrcCount cnt; assert( pExpr->op==TK_AGG_FUNCTION ); + memset(&w, 0, sizeof(w)); w.xExprCallback = exprSrcCount; - w.xSelectCallback = 0; + w.xSelectCallback = sqlite3SelectWalkNoop; w.u.pSrcCount = &cnt; cnt.pSrc = pSrcList; cnt.nThis = 0; diff --git a/src/insert.c b/src/insert.c index 53d7e89b2a..d9078b89db 100644 --- a/src/insert.c +++ b/src/insert.c @@ -99,6 +99,7 @@ const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); } if( affSQLITE_AFF_NUMERIC) aff = SQLITE_AFF_NUMERIC; pIdx->zColAff[n] = aff; } pIdx->zColAff[n] = 0; @@ -833,6 +834,9 @@ void sqlite3Insert( pTab->zName); goto insert_cleanup; } + if( sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget) ){ + goto insert_cleanup; + } pTabList->a[0].iCursor = iDataCur; pUpsert->pUpsertSrc = pTabList; pUpsert->regData = regData; diff --git a/src/loadext.c b/src/loadext.c index 9ca139c8dc..03997c0275 100644 --- a/src/loadext.c +++ b/src/loadext.c @@ -461,7 +461,9 @@ static const sqlite3_api_routines sqlite3Apis = { #endif /* Version 3.28.0 and later */ sqlite3_stmt_isexplain, - sqlite3_value_frombind + sqlite3_value_frombind, + /* Version 3.30.0 and later */ + sqlite3_drop_modules, }; /* diff --git a/src/main.c b/src/main.c index e2e461c488..980ef63801 100644 --- a/src/main.c +++ b/src/main.c @@ -836,6 +836,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){ } aFlagOp[] = { { SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys }, { SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger }, + { SQLITE_DBCONFIG_ENABLE_VIEW, SQLITE_EnableView }, { SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer }, { SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension }, { SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose }, @@ -1247,11 +1248,8 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){ #ifndef SQLITE_OMIT_VIRTUALTABLE for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){ Module *pMod = (Module *)sqliteHashData(i); - if( pMod->xDestroy ){ - pMod->xDestroy(pMod->pAux); - } sqlite3VtabEponymousTableClear(db, pMod); - sqlite3DbFree(db, pMod); + sqlite3VtabModuleUnref(db, pMod); } sqlite3HashClear(&db->aModule); #endif @@ -1732,7 +1730,8 @@ int sqlite3CreateFunc( } assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC ); - extraFlags = enc & SQLITE_DETERMINISTIC; + assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY ); + extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|SQLITE_SUBTYPE); enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY); #ifndef SQLITE_OMIT_UTF16 @@ -1795,6 +1794,7 @@ int sqlite3CreateFunc( p->u.pDestructor = pDestructor; p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags; testcase( p->funcFlags & SQLITE_DETERMINISTIC ); + testcase( p->funcFlags & SQLITE_DIRECTONLY ); p->xSFunc = xSFunc ? xSFunc : xStep; p->xFinalize = xFinal; p->xValue = xValue; @@ -3087,6 +3087,7 @@ static int openDatabase( db->nMaxSorterMmap = 0x7FFFFFFF; db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger + | SQLITE_EnableView | SQLITE_CacheSpill /* The SQLITE_DQS compile-time option determines the default settings diff --git a/src/memjournal.c b/src/memjournal.c index 3b0e7a6728..0a14e847a2 100644 --- a/src/memjournal.c +++ b/src/memjournal.c @@ -96,14 +96,9 @@ static int memjrnlRead( int iChunkOffset; FileChunk *pChunk; -#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \ - || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE) if( (iAmt+iOfst)>p->endpoint.iOffset ){ return SQLITE_IOERR_SHORT_READ; } -#endif - - assert( (iAmt+iOfst)<=p->endpoint.iOffset ); assert( p->readpoint.iOffset==0 || p->readpoint.pChunk!=0 ); if( p->readpoint.iOffset!=iOfst || iOfst==0 ){ sqlite3_int64 iOff = 0; diff --git a/src/parse.y b/src/parse.y index 648e79d9e3..e7bbc738fe 100644 --- a/src/parse.y +++ b/src/parse.y @@ -211,6 +211,7 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);} IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW ROWS ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT + NULLS FIRST LAST %ifdef SQLITE_OMIT_COMPOUND_SELECT EXCEPT INTERSECT UNION %endif SQLITE_OMIT_COMPOUND_SELECT @@ -781,13 +782,13 @@ using_opt(U) ::= . {U = 0;} orderby_opt(A) ::= . {A = 0;} orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;} -sortlist(A) ::= sortlist(A) COMMA expr(Y) sortorder(Z). { +sortlist(A) ::= sortlist(A) COMMA expr(Y) sortorder(Z) nulls(X). { A = sqlite3ExprListAppend(pParse,A,Y); - sqlite3ExprListSetSortOrder(A,Z); + sqlite3ExprListSetSortOrder(A,Z,X); } -sortlist(A) ::= expr(Y) sortorder(Z). { +sortlist(A) ::= expr(Y) sortorder(Z) nulls(X). { A = sqlite3ExprListAppend(pParse,0,Y); /*A-overwrites-Y*/ - sqlite3ExprListSetSortOrder(A,Z); + sqlite3ExprListSetSortOrder(A,Z,X); } %type sortorder {int} @@ -796,6 +797,11 @@ sortorder(A) ::= ASC. {A = SQLITE_SO_ASC;} sortorder(A) ::= DESC. {A = SQLITE_SO_DESC;} sortorder(A) ::= . {A = SQLITE_SO_UNDEFINED;} +%type nulls {int} +nulls(A) ::= NULLS FIRST. {A = SQLITE_SO_ASC;} +nulls(A) ::= NULLS LAST. {A = SQLITE_SO_DESC;} +nulls(A) ::= . {A = SQLITE_SO_UNDEFINED;} + %type groupby_opt {ExprList*} %destructor groupby_opt {sqlite3ExprListDelete(pParse->db, $$);} groupby_opt(A) ::= . {A = 0;} @@ -1176,33 +1182,6 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] { */ sqlite3ExprUnmapAndDelete(pParse, A); A = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[N],1); - }else if( Y->nExpr==1 ){ - /* Expressions of the form: - ** - ** expr1 IN (?1) - ** expr1 NOT IN (?2) - ** - ** with exactly one value on the RHS can be simplified to something - ** like this: - ** - ** expr1 == ?1 - ** expr1 <> ?2 - ** - ** But, the RHS of the == or <> is marked with the EP_Generic flag - ** so that it may not contribute to the computation of comparison - ** affinity or the collating sequence to use for comparison. Otherwise, - ** the semantics would be subtly different from IN or NOT IN. - */ - Expr *pRHS = Y->a[0].pExpr; - Y->a[0].pExpr = 0; - sqlite3ExprListDelete(pParse->db, Y); - /* pRHS cannot be NULL because a malloc error would have been detected - ** before now and control would have never reached this point */ - if( ALWAYS(pRHS) ){ - pRHS->flags &= ~EP_Collate; - pRHS->flags |= EP_Generic; - } - A = sqlite3PExpr(pParse, N ? TK_NE : TK_EQ, A, pRHS); }else{ A = sqlite3PExpr(pParse, TK_IN, A, 0); if( A ){ @@ -1767,12 +1746,12 @@ filter_clause(A) ::= FILTER LP WHERE expr(X) RP. { A = X; } ** are synthesized and do not actually appear in the grammar: */ %token - TRUEFALSE /* True or false keyword */ - ISNOT /* Combination of IS and NOT */ - FUNCTION /* A function invocation */ COLUMN /* Reference to a table column */ AGG_FUNCTION /* An aggregate function */ AGG_COLUMN /* An aggregated column */ + TRUEFALSE /* True or false keyword */ + ISNOT /* Combination of IS and NOT */ + FUNCTION /* A function invocation */ UMINUS /* Unary minus */ UPLUS /* Unary plus */ TRUTH /* IS TRUE or IS FALSE or IS NOT TRUE or IS NOT FALSE */ diff --git a/src/pragma.c b/src/pragma.c index e7fb5508d2..54f0826eef 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1251,7 +1251,7 @@ void sqlite3Pragma( } break; -#ifdef SQLITE_INTROSPECTION_PRAGMAS +#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS case PragTyp_FUNCTION_LIST: { int i; HashElem *j; diff --git a/src/pragma.h b/src/pragma.h index 766bb03de1..067f76aa6d 100644 --- a/src/pragma.h +++ b/src/pragma.h @@ -318,7 +318,7 @@ static const PragmaName aPragmaName[] = { /* iArg: */ SQLITE_FullFSync }, #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) -#if defined(SQLITE_INTROSPECTION_PRAGMAS) +#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) {/* zName: */ "function_list", /* ePragTyp: */ PragTyp_FUNCTION_LIST, /* ePragFlg: */ PragFlg_Result0, @@ -442,7 +442,7 @@ static const PragmaName aPragmaName[] = { #endif #if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) #if !defined(SQLITE_OMIT_VIRTUALTABLE) -#if defined(SQLITE_INTROSPECTION_PRAGMAS) +#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) {/* zName: */ "module_list", /* ePragTyp: */ PragTyp_MODULE_LIST, /* ePragFlg: */ PragFlg_Result0, @@ -477,7 +477,7 @@ static const PragmaName aPragmaName[] = { /* iArg: */ SQLITE_ParserTrace }, #endif #endif -#if defined(SQLITE_INTROSPECTION_PRAGMAS) +#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) {/* zName: */ "pragma_list", /* ePragTyp: */ PragTyp_PRAGMA_LIST, /* ePragFlg: */ PragFlg_Result0, @@ -675,4 +675,4 @@ static const PragmaName aPragmaName[] = { /* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError }, #endif }; -/* Number of pragmas: 62 on by default, 81 total. */ +/* Number of pragmas: 65 on by default, 81 total. */ diff --git a/src/prepare.c b/src/prepare.c index 37315f6227..4623cc57e7 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -142,7 +142,7 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){ if( db->init.orphanTrigger ){ assert( iDb==1 ); }else{ - pData->rc = rc; + if( rc > pData->rc ) pData->rc = rc; if( rc==SQLITE_NOMEM ){ sqlite3OomFault(db); }else if( rc!=SQLITE_INTERRUPT diff --git a/src/resolve.c b/src/resolve.c index d88abc4a4b..b61af805b2 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -823,6 +823,15 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ ** SQL is being compiled using sqlite3NestedParse() */ no_such_func = 1; pDef = 0; + }else + if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0 + && ExprHasProperty(pExpr, EP_Indirect) + && !IN_RENAME_OBJECT + ){ + /* Functions tagged with SQLITE_DIRECTONLY may not be used + ** inside of triggers and views */ + sqlite3ErrorMsg(pParse, "%s() prohibited in triggers and views", + pDef->zName); } } @@ -908,16 +917,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ sqlite3WalkExprList(pWalker, pWin->pPartition); sqlite3WalkExprList(pWalker, pWin->pOrderBy); sqlite3WalkExpr(pWalker, pWin->pFilter); - if( 0==pSel->pWin - || 0==sqlite3WindowCompare(pParse, pSel->pWin, pWin, 0) - ){ - pWin->pNextWin = pSel->pWin; - if( pSel->pWin ){ - pSel->pWin->ppThis = &pWin->pNextWin; - } - pSel->pWin = pWin; - pWin->ppThis = &pSel->pWin; - } + sqlite3WindowLink(pSel, pWin); pNC->ncFlags |= NC_HasWin; }else #endif /* SQLITE_OMIT_WINDOWFUNC */ @@ -973,7 +973,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ } case TK_IS: case TK_ISNOT: { - Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); + Expr *pRight = sqlite3ExprSkipCollateAndLikely(pExpr->pRight); assert( !ExprHasProperty(pExpr, EP_Reduced) ); /* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE", ** and "x IS NOT FALSE". */ @@ -1184,7 +1184,7 @@ static int resolveCompoundOrderBy( int iCol = -1; Expr *pE, *pDup; if( pItem->done ) continue; - pE = sqlite3ExprSkipCollate(pItem->pExpr); + pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr); if( sqlite3ExprIsInteger(pE, &iCol) ){ if( iCol<=0 || iCol>pEList->nExpr ){ resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); @@ -1363,7 +1363,7 @@ static int resolveOrderGroupBy( pParse = pNC->pParse; for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ Expr *pE = pItem->pExpr; - Expr *pE2 = sqlite3ExprSkipCollate(pE); + Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pE); if( zType[0]!='G' ){ iCol = resolveAsName(pParse, pSelect->pEList, pE2); if( iCol>0 ){ diff --git a/src/select.c b/src/select.c index ca1256d160..811671dd69 100644 --- a/src/select.c +++ b/src/select.c @@ -664,7 +664,7 @@ static void pushOntoSorter( if( pParse->db->mallocFailed ) return; pOp->p2 = nKey + nData; pKI = pOp->p4.pKeyInfo; - memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */ + memset(pKI->aSortFlags, 0, pKI->nKeyField); /* Makes OP_Jump testable */ sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); testcase( pKI->nAllField > pKI->nKeyField+2 ); pOp->p4.pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pSort->pOrderBy,nOBSat, @@ -1275,7 +1275,7 @@ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){ int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*); KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra); if( p ){ - p->aSortOrder = (u8*)&p->aColl[N+X]; + p->aSortFlags = (u8*)&p->aColl[N+X]; p->nKeyField = (u16)N; p->nAllField = (u16)(N+X); p->enc = ENC(db); @@ -1352,7 +1352,7 @@ KeyInfo *sqlite3KeyInfoFromExprList( assert( sqlite3KeyInfoIsWriteable(pInfo) ); for(i=iStart, pItem=pList->a+iStart; iaColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr); - pInfo->aSortOrder[i-iStart] = pItem->sortOrder; + pInfo->aSortFlags[i-iStart] = pItem->sortFlags; } } return pInfo; @@ -1960,7 +1960,7 @@ int sqlite3ColumnsFromExprList( if( (zName = pEList->a[i].zName)!=0 ){ /* If the column contains an "AS " phrase, use as the name */ }else{ - Expr *pColExpr = sqlite3ExprSkipCollate(pEList->a[i].pExpr); + Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr); while( pColExpr->op==TK_DOT ){ pColExpr = pColExpr->pRight; assert( pColExpr!=0 ); @@ -2253,7 +2253,7 @@ static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){ } assert( sqlite3KeyInfoIsWriteable(pRet) ); pRet->aColl[i] = pColl; - pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder; + pRet->aSortFlags[i] = pOrderBy->a[i].sortFlags; } } @@ -3228,7 +3228,7 @@ static int multiSelectOrderBy( assert( sqlite3KeyInfoIsWriteable(pKeyDup) ); for(i=0; iaColl[i] = multiSelectCollSeq(pParse, p, i); - pKeyDup->aSortOrder[i] = 0; + pKeyDup->aSortFlags[i] = 0; } } } @@ -3476,11 +3476,20 @@ static Expr *substExpr( pNew->iRightJoinTable = pExpr->iRightJoinTable; ExprSetProperty(pNew, EP_FromJoin); } - if( pNew && ExprHasProperty(pExpr,EP_Generic) ){ - ExprSetProperty(pNew, EP_Generic); - } sqlite3ExprDelete(db, pExpr); pExpr = pNew; + + /* Ensure that the expression now has an implicit collation sequence, + ** just as it did when it was a column of a view or sub-query. */ + if( pExpr ){ + if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){ + CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, pExpr); + pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr, + (pColl ? pColl->zName : "BINARY") + ); + } + ExprClearProperty(pExpr, EP_Collate); + } } } }else{ @@ -4405,7 +4414,7 @@ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){ ExprList *pEList = pFunc->x.pList; /* Arguments to agg function */ const char *zFunc; /* Name of aggregate function pFunc */ ExprList *pOrderBy; - u8 sortOrder; + u8 sortFlags; assert( *ppMinMax==0 ); assert( pFunc->op==TK_AGG_FUNCTION ); @@ -4416,16 +4425,16 @@ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){ zFunc = pFunc->u.zToken; if( sqlite3StrICmp(zFunc, "min")==0 ){ eRet = WHERE_ORDERBY_MIN; - sortOrder = SQLITE_SO_ASC; + sortFlags = KEYINFO_ORDER_BIGNULL; }else if( sqlite3StrICmp(zFunc, "max")==0 ){ eRet = WHERE_ORDERBY_MAX; - sortOrder = SQLITE_SO_DESC; + sortFlags = KEYINFO_ORDER_DESC; }else{ return eRet; } *ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0); assert( pOrderBy!=0 || db->mallocFailed ); - if( pOrderBy ) pOrderBy->a[0].sortOrder = sortOrder; + if( pOrderBy ) pOrderBy->a[0].sortFlags = sortFlags; return eRet; } @@ -4906,6 +4915,10 @@ static int selectExpander(Walker *pWalker, Select *p){ u8 eCodeOrig = pWalker->eCode; if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; assert( pFrom->pSelect==0 ); + if( pTab->pSelect && (db->flags & SQLITE_EnableView)==0 ){ + sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited", + pTab->zName); + } pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); nCol = pTab->nCol; pTab->nCol = -1; diff --git a/src/shell.c.in b/src/shell.c.in index a562fa8513..a9ac61c38f 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -1290,7 +1290,7 @@ static void editFunc( fseek(f, 0, SEEK_END); sz = ftell(f); rewind(f); - p = sqlite3_malloc64( sz+(bBin==0) ); + p = sqlite3_malloc64( sz+1 ); if( p==0 ){ sqlite3_result_error_nomem(context); goto edit_func_end; @@ -1767,7 +1767,8 @@ static void eqp_render_level(ShellState *p, int iEqpId){ for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){ pNext = eqp_next_row(p, iEqpId, pRow); z = pRow->zText; - utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z); + utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, + pNext ? "|--" : "`--", z); if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){ memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4); eqp_render_level(p, pRow->iEqpId); @@ -1958,7 +1959,7 @@ static int shell_callback( while( j>0 && IsSpace(z[j-1]) ){ j--; } z[j] = 0; if( strlen30(z)>=79 ){ - for(i=j=0; (c = z[i])!=0; i++){ /* Copy changes from z[i] back to z[j] */ + for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */ if( c==cEnd ){ cEnd = 0; }else if( c=='"' || c=='\'' || c=='`' ){ @@ -2537,7 +2538,7 @@ static int display_stats( raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset); raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur); - iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE, bReset); + iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset); raw_printf(pArg->out, "Reprepare operations: %d\n", iCur); iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset); raw_printf(pArg->out, "Number of times run: %d\n", iCur); @@ -3460,20 +3461,20 @@ static const char *(azHelp[]) = { ".archive ... Manage SQL archives", " Each command must have exactly one of the following options:", " -c, --create Create a new archive", - " -u, --update Add files or update files with changed mtime", - " -i, --insert Like -u but always add even if mtime unchanged", + " -u, --update Add or update files with changed mtime", + " -i, --insert Like -u but always add even if unchanged", " -t, --list List contents of archive", " -x, --extract Extract files from archive", " Optional arguments:", " -v, --verbose Print each filename as it is processed", - " -f FILE, --file FILE Operate on archive FILE (default is current db)", - " -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS", - " -C DIR, --directory DIR Change to directory DIR to read/extract files", + " -f FILE, --file FILE Use archive FILE (default is current db)", + " -a FILE, --append FILE Open FILE using the apndvfs VFS", + " -C DIR, --directory DIR Read/extract files from directory DIR", " -n, --dryrun Show the SQL that would have occurred", " Examples:", - " .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar", - " .ar -tf archive.sar # List members of archive.sar", - " .ar -xvf archive.sar # Verbosely extract files from archive.sar", + " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar", + " .ar -tf ARCHIVE # List members of ARCHIVE", + " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE", " See also:", " http://sqlite.org/cli.html#sqlar_archive_support", #endif @@ -3482,7 +3483,7 @@ static const char *(azHelp[]) = { #endif ".backup ?DB? FILE Backup DB (default \"main\") to FILE", " --append Use the appendvfs", - " --async Write to FILE without a journal and without fsync()", + " --async Write to FILE without journal and fsync()", ".bail on|off Stop after hitting an error. Default OFF", ".binary on|off Turn binary output on or off. Default OFF", ".cd DIRECTORY Change the working directory to DIRECTORY", @@ -3502,15 +3503,15 @@ static const char *(azHelp[]) = { " Other Modes:", #ifdef SQLITE_DEBUG " test Show raw EXPLAIN QUERY PLAN output", - " trace Like \"full\" but also enable \"PRAGMA vdbe_trace\"", + " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"", #endif " trigger Like \"full\" but also show trigger bytecode", - ".excel Display the output of next command in a spreadsheet", + ".excel Display the output of next command in spreadsheet", ".exit ?CODE? Exit this program with return-code CODE", - ".expert EXPERIMENTAL. Suggest indexes for specified queries", + ".expert EXPERIMENTAL. Suggest indexes for queries", /* Because explain mode comes on automatically now, the ".explain" mode -** is removed from the help screen. It is still supported for legacy, however */ -/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/ +** is removed from the help screen. It is still supported for legacy, however */ +/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off",*/ ".filectrl CMD ... Run various sqlite3_file_control() operations", " Run \".filectrl\" with no arguments for details", ".fullschema ?--indent? Show schema and the content of sqlite_stat tables", @@ -3557,7 +3558,7 @@ static const char *(azHelp[]) = { " --append Use appendvfs to append database to the end of FILE", #ifdef SQLITE_ENABLE_DESERIALIZE " --deserialize Load into memory useing sqlite3_deserialize()", - " --hexdb Load the output of \"dbtotxt\" as an in-memory database", + " --hexdb Load the output of \"dbtotxt\" as an in-memory db", " --maxsize N Maximum size for --hexdb or --deserialized database", #endif " --new Initialize FILE to an empty database", @@ -3570,7 +3571,7 @@ static const char *(azHelp[]) = { " init Initialize the TEMP table that holds bindings", " list List the current parameter bindings", " set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE", - " PARAMETER should start with '$', ':', '@', or '?'", + " PARAMETER should start with one of: $ : @ ?", " unset PARAMETER Remove PARAMETER from the binding table", ".print STRING... Print literal STRING", #ifndef SQLITE_OMIT_PROGRESS_CALLBACK @@ -3585,6 +3586,11 @@ static const char *(azHelp[]) = { ".read FILE Read input from FILE", #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) ".recover Recover as much data as possible from corrupt db.", + " --freelist-corrupt Assume the freelist is corrupt", + " --recovery-db NAME Store recovery metadata in database file NAME", + " --lost-and-found TABLE Alternative name for the lost-and-found table", + " --no-rowids Do not attempt to recover rowid values", + " that are not also INTEGER PRIMARY KEYs", #endif ".restore ?DB? FILE Restore content of DB (default \"main\") from FILE", ".save FILE Write in-memory database into FILE", @@ -3616,7 +3622,7 @@ static const char *(azHelp[]) = { " Options:", " --schema Also hash the sqlite_master table", " --sha3-224 Use the sha3-224 algorithm", - " --sha3-256 Use the sha3-256 algorithm. This is the default.", + " --sha3-256 Use the sha3-256 algorithm (default)", " --sha3-384 Use the sha3-384 algorithm", " --sha3-512 Use the sha3-512 algorithm", " Any other argument is a LIKE pattern for tables to hash", @@ -3656,6 +3662,10 @@ static const char *(azHelp[]) = { " --row Trace each row (SQLITE_TRACE_ROW)", " --close Trace connection close (SQLITE_TRACE_CLOSE)", #endif /* SQLITE_OMIT_TRACE */ +#ifdef SQLITE_DEBUG + ".unmodule NAME ... Unregister virtual table modules", + " --allexcept Unregister everything except those named", +#endif ".vfsinfo ?AUX? Information about the top-level VFS", ".vfslist List all available VFSes", ".vfsname ?AUX? Print the name of the VFS stack", @@ -5531,7 +5541,7 @@ void shellReset( #endif /* !defined SQLITE_OMIT_VIRTUALTABLE */ #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) -/********************************************************************************* +/****************************************************************************** ** The ".archive" or ".ar" command. */ /* @@ -5729,7 +5739,8 @@ static int arParseCommand( i = n; }else{ if( iArg>=(nArg-1) ){ - return arErrorMsg(pAr, "option requires an argument: %c",z[i]); + return arErrorMsg(pAr, "option requires an argument: %c", + z[i]); } zArg = azArg[++iArg]; } @@ -6117,10 +6128,10 @@ end_ar_transaction: ** Implementation of ".ar" dot command. */ static int arDotCommand( - ShellState *pState, /* Current shell tool state */ - int fromCmdLine, /* True if -A command-line option, not .ar cmd */ - char **azArg, /* Array of arguments passed to dot command */ - int nArg /* Number of entries in azArg[] */ + ShellState *pState, /* Current shell tool state */ + int fromCmdLine, /* True if -A command-line option, not .ar cmd */ + char **azArg, /* Array of arguments passed to dot command */ + int nArg /* Number of entries in azArg[] */ ){ ArCommand cmd; int rc; @@ -6220,7 +6231,7 @@ end_ar_command: return rc; } /* End of the ".archive" or ".ar" command logic -**********************************************************************************/ +*******************************************************************************/ #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */ #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) @@ -6826,6 +6837,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ RecoverTable *pOrphan = 0; int bFreelist = 1; /* 0 if --freelist-corrupt is specified */ + int bRowids = 1; /* 0 if --no-rowids */ for(i=1; iout, azArg[0]); return 1; } } @@ -6949,7 +6961,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ " )" " SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)" ") " - "FROM pages WHERE maxlen > 0 AND i NOT IN freelist;" + "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;" "UPDATE recovery.map AS o SET intkey = (" " SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno" ");" @@ -7009,8 +7021,11 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ shellPrepare(pState->db, &rc, "SELECT pgno FROM recovery.map WHERE root=?", &pPages ); + shellPrepare(pState->db, &rc, - "SELECT max(field), group_concat(shell_escape_crnl(quote(value)), ', ')" + "SELECT max(field), group_concat(shell_escape_crnl(quote" + "(case when (? AND field<0) then NULL else value end)" + "), ', ')" ", min(field) " "FROM sqlite_dbdata WHERE pgno = ? AND field != ?" "GROUP BY cell", &pCells @@ -7045,11 +7060,16 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){ raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n"); } sqlite3_bind_int(pPages, 1, iRoot); - sqlite3_bind_int(pCells, 2, pTab->iPk); + if( bRowids==0 && pTab->iPk<0 ){ + sqlite3_bind_int(pCells, 1, 1); + }else{ + sqlite3_bind_int(pCells, 1, 0); + } + sqlite3_bind_int(pCells, 3, pTab->iPk); while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){ int iPgno = sqlite3_column_int(pPages, 0); - sqlite3_bind_int(pCells, 1, iPgno); + sqlite3_bind_int(pCells, 2, iPgno); while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){ int nField = sqlite3_column_int(pCells, 0); int iMin = sqlite3_column_int(pCells, 2); @@ -7132,7 +7152,7 @@ static int do_meta_command(char *zLine, ShellState *p){ int nArg = 0; int n, c; int rc = 0; - char *azArg[50]; + char *azArg[52]; #ifndef SQLITE_OMIT_VIRTUALTABLE if( p->expert.pExpert ){ @@ -7142,7 +7162,7 @@ static int do_meta_command(char *zLine, ShellState *p){ /* Parse the input line into tokens. */ - while( zLine[h] && nArgp==0 ) goto session_not_open; out = fopen(azCmd[1], "wb"); if( out==0 ){ - utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]); + utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", + azCmd[1]); }else{ int szChng; void *pChng; @@ -9127,8 +9151,7 @@ static int do_meta_command(char *zLine, ShellState *p){ { utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n", azArg[i], azArg[0]); - raw_printf(stderr, "Should be one of: --schema" - " --sha3-224 --sha3-256 --sha3-384 --sha3-512\n"); + showHelp(p->out, azArg[0]); rc = 1; goto meta_command_exit; } @@ -9413,26 +9436,26 @@ static int do_meta_command(char *zLine, ShellState *p){ int ctrlCode; /* Integer code for that option */ const char *zUsage; /* Usage notes */ } aCtrl[] = { - { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" }, - { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" }, - /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/ - /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/ - { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, - { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN" }, - /*{ "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" }, + { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" }, + { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" }, + /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/ + /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/ + { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" }, + { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN" }, + /*{ "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, "" }, + { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" }, #endif - { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " }, - { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" }, - { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" }, - { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" }, - { "reserve", SQLITE_TESTCTRL_RESERVE, "BYTES-OF-RESERVE" }, + { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " }, + { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" }, + { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" }, + { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" }, + { "reserve", SQLITE_TESTCTRL_RESERVE, "BYTES-OF-RESERVE"}, }; int testctrl = -1; int iCtrl = -1; @@ -9575,7 +9598,7 @@ static int do_meta_command(char *zLine, ShellState *p){ } } if( isOk==0 && iCtrl>=0 ){ - utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd, aCtrl[iCtrl].zUsage); + utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage); rc = 1; }else if( isOk==1 ){ raw_printf(p->out, "%d\n", rc2); @@ -9653,6 +9676,31 @@ static int do_meta_command(char *zLine, ShellState *p){ }else #endif /* !defined(SQLITE_OMIT_TRACE) */ +#ifdef SQLITE_DEBUG + if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){ + int ii; + int lenOpt; + char *zOpt; + if( nArg<2 ){ + raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n"); + rc = 1; + goto meta_command_exit; + } + open_db(p, 0); + zOpt = azArg[1]; + if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++; + lenOpt = (int)strlen(zOpt); + if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){ + assert( azArg[nArg]==0 ); + sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0); + }else{ + for(ii=1; iidb, azArg[ii], 0, 0); + } + } + }else +#endif + #if SQLITE_USER_AUTHENTICATION if( c=='u' && strncmp(azArg[0], "user", n)==0 ){ if( nArg<2 ){ @@ -9667,7 +9715,8 @@ static int do_meta_command(char *zLine, ShellState *p){ rc = 1; goto meta_command_exit; } - rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], strlen30(azArg[3])); + rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], + strlen30(azArg[3])); if( rc ){ utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]); rc = 1; diff --git a/src/sqlite.h.in b/src/sqlite.h.in index f19f1a22ec..5fb0d2927f 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -2095,6 +2095,17 @@ struct sqlite3_mem_methods { ** following this call. The second parameter may be a NULL pointer, in ** which case the trigger setting is not reported back. ** +** [[SQLITE_DBCONFIG_ENABLE_VIEW]] +**
SQLITE_DBCONFIG_ENABLE_VIEW
+**
^This option is used to enable or disable [CREATE VIEW | views]. +** There should be two additional arguments. +** The first argument is an integer which is 0 to disable views, +** positive to enable views or negative to leave the setting unchanged. +** The second parameter is a pointer to an integer into which +** is written 0 or 1 to indicate whether views are disabled or enabled +** following this call. The second parameter may be a NULL pointer, in +** which case the view setting is not reported back.
+** ** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]] **
SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER
**
^This option is used to enable or disable the @@ -2267,7 +2278,8 @@ struct sqlite3_mem_methods { #define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */ #define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */ #define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */ -#define SQLITE_DBCONFIG_MAX 1014 /* Largest DBCONFIG */ +#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */ +#define SQLITE_DBCONFIG_MAX 1015 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes @@ -4850,6 +4862,9 @@ int sqlite3_reset(sqlite3_stmt *pStmt); ** function that is not deterministic. The SQLite query planner is able to ** perform additional optimizations on deterministic functions, so use ** of the [SQLITE_DETERMINISTIC] flag is recommended where possible. +** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY] +** flag, which if present prevents the function from being invoked from +** within VIEWs or TRIGGERs. ** ** ^(The fifth parameter is an arbitrary pointer. The implementation of the ** function can gain access to this pointer using [sqlite3_user_data()].)^ @@ -4967,8 +4982,25 @@ int sqlite3_create_window_function( ** [SQLITE_UTF8 | preferred text encoding] as the fourth argument ** to [sqlite3_create_function()], [sqlite3_create_function16()], or ** [sqlite3_create_function_v2()]. +** +** The SQLITE_DETERMINISTIC flag means that the new function will always +** maps the same inputs into the same output. The abs() function is +** deterministic, for example, but randomblob() is not. +** +** The SQLITE_DIRECTONLY flag means that the function may only be invoked +** from top-level SQL, and cannot be used in VIEWs or TRIGGERs. +** +** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call +** [sqlite3_value_subtype()] to inspect the sub-types of its arguments. +** Specifying this flag makes no difference for scalar or aggregate user +** functions. However, if it is not specified for a user-defined window +** function, then any sub-types belonging to arguments passed to the window +** function may be discarded before the window function is called (i.e. +** sqlite3_value_subtype() will always return 0). */ -#define SQLITE_DETERMINISTIC 0x800 +#define SQLITE_DETERMINISTIC 0x000000800 +#define SQLITE_DIRECTONLY 0x000080000 +#define SQLITE_SUBTYPE 0x000100000 /* ** CAPI3REF: Deprecated Functions @@ -6614,6 +6646,12 @@ struct sqlite3_index_info { ** ^The sqlite3_create_module() ** interface is equivalent to sqlite3_create_module_v2() with a NULL ** destructor. +** +** ^If the third parameter (the pointer to the sqlite3_module object) is +** NULL then no new module is create and any existing modules with the +** same name are dropped. +** +** See also: [sqlite3_drop_modules()] */ int sqlite3_create_module( sqlite3 *db, /* SQLite connection to register module with */ @@ -6629,6 +6667,23 @@ int sqlite3_create_module_v2( void(*xDestroy)(void*) /* Module destructor function */ ); +/* +** CAPI3REF: Remove Unnecessary Virtual Table Implementations +** METHOD: sqlite3 +** +** ^The sqlite3_drop_modules(D,L) interface removes all virtual +** table modules from database connection D except those named on list L. +** The L parameter must be either NULL or a pointer to an array of pointers +** to strings where the array is terminated by a single NULL pointer. +** ^If the L parameter is NULL, then all virtual table modules are removed. +** +** See also: [sqlite3_create_module()] +*/ +int sqlite3_drop_modules( + sqlite3 *db, /* Remove modules from this connection */ + const char **azKeep /* Except, do not remove the ones named here */ +); + /* ** CAPI3REF: Virtual Table Instance Object ** KEYWORDS: sqlite3_vtab diff --git a/src/sqlite3ext.h b/src/sqlite3ext.h index 088148b936..416ac94231 100644 --- a/src/sqlite3ext.h +++ b/src/sqlite3ext.h @@ -322,6 +322,8 @@ struct sqlite3_api_routines { /* Version 3.28.0 and later */ int (*stmt_isexplain)(sqlite3_stmt*); int (*value_frombind)(sqlite3_value*); + /* Version 3.30.0 and later */ + int (*drop_modules)(sqlite3*,const char**); }; /* @@ -614,6 +616,8 @@ typedef int (*sqlite3_loadext_entry)( /* Version 3.28.0 and later */ #define sqlite3_stmt_isexplain sqlite3_api->isexplain #define sqlite3_value_frombind sqlite3_api->frombind +/* Version 3.30.0 and later */ +#define sqlite3_drop_modules sqlite3_api->drop_modules #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) diff --git a/src/sqliteInt.h b/src/sqliteInt.h index ef5723c49d..2deeda2c52 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1551,16 +1551,17 @@ struct sqlite3 { #define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */ #define SQLITE_DqsDDL 0x20000000 /* dbl-quoted strings allowed in DDL*/ #define SQLITE_DqsDML 0x40000000 /* dbl-quoted strings allowed in DML*/ +#define SQLITE_EnableView 0x80000000 /* Enable the use of views */ /* Flags used only if debugging */ #define HI(X) ((u64)(X)<<32) #ifdef SQLITE_DEBUG -#define SQLITE_SqlTrace HI(0x0001) /* Debug print SQL as it executes */ -#define SQLITE_VdbeListing HI(0x0002) /* Debug listings of VDBE progs */ -#define SQLITE_VdbeTrace HI(0x0004) /* True to trace VDBE execution */ -#define SQLITE_VdbeAddopTrace HI(0x0008) /* Trace sqlite3VdbeAddOp() calls */ -#define SQLITE_VdbeEQP HI(0x0010) /* Debug EXPLAIN QUERY PLAN */ -#define SQLITE_ParserTrace HI(0x0020) /* PRAGMA parser_trace=ON */ +#define SQLITE_SqlTrace HI(0x0100000) /* Debug print SQL as it executes */ +#define SQLITE_VdbeListing HI(0x0200000) /* Debug listings of VDBE progs */ +#define SQLITE_VdbeTrace HI(0x0400000) /* True to trace VDBE execution */ +#define SQLITE_VdbeAddopTrace HI(0x0800000) /* Trace sqlite3VdbeAddOp() calls */ +#define SQLITE_VdbeEQP HI(0x1000000) /* Debug EXPLAIN QUERY PLAN */ +#define SQLITE_ParserTrace HI(0x2000000) /* PRAGMA parser_trace=ON */ #endif /* @@ -1680,6 +1681,7 @@ struct FuncDestructor { ** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG ** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG ** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API +** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API ** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API */ #define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */ @@ -1700,6 +1702,8 @@ struct FuncDestructor { #define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */ #define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */ #define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */ +#define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */ +#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */ /* ** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are @@ -1813,6 +1817,7 @@ struct Savepoint { struct Module { const sqlite3_module *pModule; /* Callback pointers */ const char *zName; /* Name passed to create_module() */ + int nRefModule; /* Number of pointers to this object */ void *pAux; /* pAux passed to create_module() */ void (*xDestroy)(void *); /* Module destructor function */ Table *pEpoTab; /* Eponymous table for this module */ @@ -2154,10 +2159,13 @@ struct KeyInfo { u16 nKeyField; /* Number of key columns in the index */ u16 nAllField; /* Total columns, including key plus others */ sqlite3 *db; /* The database connection */ - u8 *aSortOrder; /* Sort order for each column. */ + u8 *aSortFlags; /* Sort order for each column. */ CollSeq *aColl[1]; /* Collating sequence for each term of the key */ }; +#define KEYINFO_ORDER_DESC 0x01 +#define KEYINFO_ORDER_BIGNULL 0x02 + /* ** This object holds a record which has been parsed out into individual ** fields, for the purposes of doing a comparison. @@ -2486,6 +2494,7 @@ struct Expr { ** TK_REGISTER: register number ** TK_TRIGGER: 1 -> new, 0 -> old ** EP_Unlikely: 134217728 times likelihood + ** TK_SELECT_COLUMN: Number of columns on the LHS ** TK_SELECT: 1st register of result vector */ ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. ** TK_VARIABLE: variable number (always >= 1). @@ -2514,36 +2523,37 @@ struct Expr { ** EP_Agg == NC_HasAgg == SF_HasAgg ** EP_Win == NC_HasWin */ -#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ -#define EP_Distinct 0x000002 /* Aggregate function with DISTINCT keyword */ -#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */ -#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */ -#define EP_Agg 0x000010 /* Contains one or more aggregate functions */ -#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ -#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */ -#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */ -#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */ -#define EP_Generic 0x000200 /* Ignore COLLATE or affinity on this tree */ -#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */ -#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */ -#define EP_Skip 0x001000 /* Operator does not contribute to affinity */ -#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */ -#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ -#define EP_Win 0x008000 /* Contains window functions */ -#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ -#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ -#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ -#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ -#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ -#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ -#define EP_Alias 0x400000 /* Is an alias for a result set column */ -#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ -#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */ -#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */ -#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */ -#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */ -#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */ -#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */ +#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */ +#define EP_Distinct 0x000002 /* Aggregate function with DISTINCT keyword */ +#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */ +#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */ +#define EP_Agg 0x000010 /* Contains one or more aggregate functions */ +#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */ +#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */ +#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */ +#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */ + /* 0x000200 Available for reuse */ +#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */ +#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */ +#define EP_Skip 0x001000 /* Operator does not contribute to affinity */ +#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */ +#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */ +#define EP_Win 0x008000 /* Contains window functions */ +#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */ +#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */ +#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */ +#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ +#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ +#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ +#define EP_Alias 0x400000 /* Is an alias for a result set column */ +#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ +#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */ +#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */ +#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */ +#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */ +#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */ +#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */ +#define EP_Indirect 0x40000000 /* Contained within a TRIGGER or a VIEW */ /* ** The EP_Propagate mask is a set of properties that automatically propagate @@ -2617,11 +2627,12 @@ struct ExprList { Expr *pExpr; /* The parse tree for this expression */ char *zName; /* Token associated with this expression */ char *zSpan; /* Original text of the expression */ - u8 sortOrder; /* 1 for DESC or 0 for ASC */ + u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */ unsigned done :1; /* A flag to indicate when processing is finished */ unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ unsigned reusable :1; /* Constant expression is reusable */ unsigned bSorterRef :1; /* Defer evaluation until after sorting */ + unsigned bNulls: 1; /* True if explicit "NULLS FIRST/LAST" */ union { struct { u16 iOrderByCol; /* For ORDER BY, column number in result set */ @@ -3613,8 +3624,8 @@ struct Window { Expr *pFilter; /* The FILTER expression */ FuncDef *pFunc; /* The function */ int iEphCsr; /* Partition buffer or Peer buffer */ - int regAccum; - int regResult; + int regAccum; /* Accumulator */ + int regResult; /* Interim result */ int csrApp; /* Function cursor (used by min/max) */ int regApp; /* Function register (also used by min/max) */ int regPart; /* Array of registers for PARTITION BY values */ @@ -3624,6 +3635,8 @@ struct Window { int regOne; /* Register containing constant value 1 */ int regStartRowid; int regEndRowid; + u8 bExprArgs; /* Defer evaluation of window function arguments + ** due to the SQLITE_SUBTYPE flag */ }; #ifndef SQLITE_OMIT_WINDOWFUNC @@ -3632,6 +3645,7 @@ void sqlite3WindowUnlinkFromSelect(Window*); void sqlite3WindowListDelete(sqlite3 *db, Window *p); Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8); void sqlite3WindowAttach(Parse*, Expr*, Window*); +void sqlite3WindowLink(Select *pSel, Window *pWin); int sqlite3WindowCompare(Parse*, Window*, Window*, int); void sqlite3WindowCodeInit(Parse*, Window*); void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int); @@ -3904,7 +3918,7 @@ void sqlite3ExprDelete(sqlite3*, Expr*); void sqlite3ExprUnmapAndDelete(Parse*, Expr*); ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); -void sqlite3ExprListSetSortOrder(ExprList*,int); +void sqlite3ExprListSetSortOrder(ExprList*,int,int); void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); void sqlite3ExprListDelete(sqlite3*, ExprList*); @@ -4291,6 +4305,7 @@ int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*); Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int); Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); Expr *sqlite3ExprSkipCollate(Expr*); +Expr *sqlite3ExprSkipCollateAndLikely(Expr*); int sqlite3CheckCollSeq(Parse *, CollSeq *); int sqlite3WritableSchema(sqlite3*); int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*); @@ -4403,7 +4418,7 @@ void sqlite3KeyInfoUnref(KeyInfo*); KeyInfo *sqlite3KeyInfoRef(KeyInfo*); KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*); KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int); - +int sqlite3HasExplicitNulls(Parse*, ExprList*); #ifdef SQLITE_DEBUG int sqlite3KeyInfoIsWriteable(KeyInfo*); @@ -4483,6 +4498,7 @@ void sqlite3AutoLoadExtensions(sqlite3*); # define sqlite3VtabInSync(db) 0 # define sqlite3VtabLock(X) # define sqlite3VtabUnlock(X) +# define sqlite3VtabModuleUnref(D,X) # define sqlite3VtabUnlockList(X) # define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK # define sqlite3GetVTable(X,Y) ((VTable*)0) @@ -4494,6 +4510,7 @@ void sqlite3AutoLoadExtensions(sqlite3*); int sqlite3VtabCommit(sqlite3 *db); void sqlite3VtabLock(VTable *); void sqlite3VtabUnlock(VTable *); + void sqlite3VtabModuleUnref(sqlite3*,Module*); void sqlite3VtabUnlockList(sqlite3*); int sqlite3VtabSavepoint(sqlite3 *, int, int); void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*); diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 3b0ce2d94f..eed7a43b92 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -1917,33 +1917,33 @@ static int SQLITE_TCLAPI DbObjCmd( "authorizer", "backup", "bind_fallback", "busy", "cache", "changes", "close", "collate", "collation_needed", - "commit_hook", "complete", "copy", - "deserialize", "enable_load_extension", "errorcode", - "eval", "exists", "function", - "incrblob", "interrupt", "last_insert_rowid", - "nullvalue", "onecolumn", "preupdate", - "profile", "progress", "rekey", - "restore", "rollback_hook", "serialize", - "status", "timeout", "total_changes", - "trace", "trace_v2", "transaction", - "unlock_notify", "update_hook", "version", - "wal_hook", 0 + "commit_hook", "complete", "config", + "copy", "deserialize", "enable_load_extension", + "errorcode", "eval", "exists", + "function", "incrblob", "interrupt", + "last_insert_rowid", "nullvalue", "onecolumn", + "preupdate", "profile", "progress", + "rekey", "restore", "rollback_hook", + "serialize", "status", "timeout", + "total_changes", "trace", "trace_v2", + "transaction", "unlock_notify", "update_hook", + "version", "wal_hook", 0 }; enum DB_enum { DB_AUTHORIZER, DB_BACKUP, DB_BIND_FALLBACK, DB_BUSY, DB_CACHE, DB_CHANGES, DB_CLOSE, DB_COLLATE, DB_COLLATION_NEEDED, - DB_COMMIT_HOOK, DB_COMPLETE, DB_COPY, - DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION,DB_ERRORCODE, - DB_EVAL, DB_EXISTS, DB_FUNCTION, - DB_INCRBLOB, DB_INTERRUPT, DB_LAST_INSERT_ROWID, - DB_NULLVALUE, DB_ONECOLUMN, DB_PREUPDATE, - DB_PROFILE, DB_PROGRESS, DB_REKEY, - DB_RESTORE, DB_ROLLBACK_HOOK, DB_SERIALIZE, - DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES, - DB_TRACE, DB_TRACE_V2, DB_TRANSACTION, - DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION, - DB_WAL_HOOK + DB_COMMIT_HOOK, DB_COMPLETE, DB_CONFIG, + DB_COPY, DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION, + DB_ERRORCODE, DB_EVAL, DB_EXISTS, + DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT, + DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN, + DB_PREUPDATE, DB_PROFILE, DB_PROGRESS, + DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK, + DB_SERIALIZE, DB_STATUS, DB_TIMEOUT, + DB_TOTAL_CHANGES, DB_TRACE, DB_TRACE_V2, + DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, + DB_VERSION, DB_WAL_HOOK }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ @@ -2331,6 +2331,74 @@ static int SQLITE_TCLAPI DbObjCmd( break; } + /* $db config ?OPTION? ?BOOLEAN? + ** + ** Configure the database connection using the sqlite3_db_config() + ** interface. + */ + case DB_CONFIG: { + static const struct DbConfigChoices { + const char *zName; + int op; + } aDbConfig[] = { + { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY }, + { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER }, + { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW }, + { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, + { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, + { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, + { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG }, + { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, + { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, + { "defensive", SQLITE_DBCONFIG_DEFENSIVE }, + { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA }, + { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, + { "dqs_dml", SQLITE_DBCONFIG_DQS_DML }, + { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL }, + }; + Tcl_Obj *pResult; + int ii; + if( objc>4 ){ + Tcl_WrongNumArgs(interp, 2, objv, "?OPTION? ?BOOLEAN?"); + return TCL_ERROR; + } + if( objc==2 ){ + /* With no arguments, list all configuration options and with the + ** current value */ + pResult = Tcl_NewListObj(0,0); + for(ii=0; iidb, aDbConfig[ii].op, -1, &v); + Tcl_ListObjAppendElement(interp, pResult, + Tcl_NewStringObj(aDbConfig[ii].zName,-1)); + Tcl_ListObjAppendElement(interp, pResult, + Tcl_NewIntObj(v)); + } + }else{ + const char *zOpt = Tcl_GetString(objv[2]); + int onoff = -1; + int v = 0; + if( zOpt[0]=='-' ) zOpt++; + for(ii=0; ii=sizeof(aDbConfig)/sizeof(aDbConfig[0]) ){ + Tcl_AppendResult(interp, "unknown config option: \"", zOpt, + "\"", (void*)0); + return TCL_ERROR; + } + if( objc==4 ){ + if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ){ + return TCL_ERROR; + } + } + sqlite3_db_config(pDb->db, aDbConfig[ii].op, onoff, &v); + pResult = Tcl_NewIntObj(v); + } + Tcl_SetObjResult(interp, pResult); + break; + } + /* $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR? ** ** Copy data into table from filename, optionally using SEPARATOR @@ -2741,10 +2809,16 @@ deserialize_error: } /* - ** $db function NAME [-argcount N] [-deterministic] SCRIPT + ** $db function NAME [OPTIONS] SCRIPT ** ** Create a new SQL function called NAME. Whenever that function is ** called, invoke SCRIPT to evaluate the function. + ** + ** Options: + ** --argcount N Function has exactly N arguments + ** --deterministic The function is pure + ** --directonly Prohibit use inside triggers and views + ** --returntype TYPE Specify the return type of the function */ case DB_FUNCTION: { int flags = SQLITE_UTF8; @@ -2777,6 +2851,9 @@ deserialize_error: if( n>1 && strncmp(z, "-deterministic",n)==0 ){ flags |= SQLITE_DETERMINISTIC; }else + if( n>1 && strncmp(z, "-directonly",n)==0 ){ + flags |= SQLITE_DIRECTONLY; + }else if( n>1 && strncmp(z, "-returntype", n)==0 ){ const char *azType[] = {"integer", "real", "text", "blob", "any", 0}; assert( SQLITE_INTEGER==1 && SQLITE_FLOAT==2 && SQLITE_TEXT==3 ); @@ -2792,7 +2869,8 @@ deserialize_error: eType++; }else{ Tcl_AppendResult(interp, "bad option \"", z, - "\": must be -argcount, -deterministic or -returntype", (char*)0 + "\": must be -argcount, -deterministic, -directonly," + " or -returntype", (char*)0 ); return TCL_ERROR; } diff --git a/src/test1.c b/src/test1.c index 6bc64e7626..6de1ff57f2 100644 --- a/src/test1.c +++ b/src/test1.c @@ -1110,6 +1110,31 @@ static int SQLITE_TCLAPI test_create_function( return TCL_OK; } +/* +** Usage: sqlite3_drop_modules DB ?NAME ...? +** +** Invoke the sqlite3_drop_modules(D,L) interface on database +** connection DB, in order to drop all modules except those named in +** the argument. +*/ +static int SQLITE_TCLAPI test_drop_modules( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite3 *db; + + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB\"", 0); + return TCL_ERROR; + } + if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; + sqlite3_drop_modules(db, argc>2 ? (const char**)(argv+2) : 0); + return TCL_OK; +} + /* ** Routines to implement the x_count() aggregate function. ** @@ -7175,6 +7200,7 @@ static int SQLITE_TCLAPI optimization_control( { "omit-noop-join", SQLITE_OmitNoopJoin }, { "stat4", SQLITE_Stat4 }, { "skip-scan", SQLITE_SkipScan }, + { "push-down", SQLITE_PushDown }, }; if( objc!=4 ){ @@ -7860,6 +7886,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_close_v2", (Tcl_CmdProc*)sqlite_test_close_v2 }, { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function }, { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate }, + { "sqlite3_drop_modules", (Tcl_CmdProc*)test_drop_modules }, { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, { "sqlite_bind", (Tcl_CmdProc*)test_bind }, diff --git a/src/treeview.c b/src/treeview.c index 753f214899..dcc81b8767 100644 --- a/src/treeview.c +++ b/src/treeview.c @@ -536,7 +536,13 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ } case TK_COLLATE: { - sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken); + /* COLLATE operators without the EP_Collate flag are intended to + ** emulate collation associated with a table column. Explicit + ** COLLATE operators that appear in the original SQL always have + ** the EP_Collate bit set */ + sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s", + !ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "", + pExpr->u.zToken, zFlgs); sqlite3TreeViewExpr(pView, pExpr->pLeft, 0); break; } @@ -557,10 +563,10 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){ #endif } if( pExpr->op==TK_AGG_FUNCTION ){ - sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q", - pExpr->op2, pExpr->u.zToken); + sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s", + pExpr->op2, pExpr->u.zToken, zFlgs); }else{ - sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken); + sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs); } if( pFarg ){ sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0); diff --git a/src/trigger.c b/src/trigger.c index 881427310a..17c86c0a9d 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -484,6 +484,9 @@ TriggerStep *sqlite3TriggerInsertStep( pTriggerStep->pIdList = pColumn; pTriggerStep->pUpsert = pUpsert; pTriggerStep->orconf = orconf; + if( pUpsert ){ + sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget); + } }else{ testcase( pColumn ); sqlite3IdListDelete(db, pColumn); @@ -643,10 +646,9 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ assert( iDb>=0 && iDbnDb ); sqlite3SchemaWritable(pParse, iDb); pTable = tableOfTrigger(pTrigger); - assert( pTable ); - assert( pTable->pSchema==pTrigger->pSchema || iDb==1 ); + assert( (pTable && pTable->pSchema==pTrigger->pSchema) || iDb==1 ); #ifndef SQLITE_OMIT_AUTHORIZATION - { + if( pTable ){ int code = SQLITE_DROP_TRIGGER; const char *zDb = db->aDb[iDb].zDbSName; const char *zTab = SCHEMA_TABLE(iDb); @@ -660,7 +662,6 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ /* Generate code to destroy the database record of the trigger. */ - assert( pTable!=0 ); if( (v = sqlite3GetVdbe(pParse))!=0 ){ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'", @@ -684,9 +685,11 @@ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){ if( ALWAYS(pTrigger) ){ if( pTrigger->pSchema==pTrigger->pTabSchema ){ Table *pTab = tableOfTrigger(pTrigger); - Trigger **pp; - for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext)); - *pp = (*pp)->pNext; + if( pTab ){ + Trigger **pp; + for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext)); + *pp = (*pp)->pNext; + } } sqlite3DeleteTrigger(db, pTrigger); db->mDbFlags |= DBFLAG_SchemaChange; diff --git a/src/update.c b/src/update.c index bbeaa3d5ce..458550b95d 100644 --- a/src/update.c +++ b/src/update.c @@ -715,28 +715,30 @@ void sqlite3Update( } if( !isView ){ - int addr1 = 0; /* Address of jump instruction */ - /* Do constraint checks. */ assert( regOldRowid>0 ); sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur, regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, aXRef, 0); + /* If REPLACE conflict handling may have been used, or if the PK of the + ** row is changing, then the GenerateConstraintChecks() above may have + ** moved cursor iDataCur. Reseek it. */ + if( bReplace || chngKey ){ + if( pPk ){ + sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey); + }else{ + sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid); + } + VdbeCoverageNeverTaken(v); + } + /* Do FK constraint checks. */ if( hasFK ){ sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey); } /* Delete the index entries associated with the current record. */ - if( bReplace || chngKey ){ - if( pPk ){ - addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); - }else{ - addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid); - } - VdbeCoverageNeverTaken(v); - } sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1); /* If changing the rowid value, or if there are foreign key constraints @@ -766,9 +768,6 @@ void sqlite3Update( sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0); } #endif - if( bReplace || chngKey ){ - sqlite3VdbeJumpHere(v, addr1); - } if( hasFK ){ sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey); diff --git a/src/upsert.c b/src/upsert.c index 850ae863b9..7beb9ffaec 100644 --- a/src/upsert.c +++ b/src/upsert.c @@ -205,6 +205,7 @@ void sqlite3UpsertDoUpdate( sqlite3 *db = pParse->db; SrcList *pSrc; /* FROM clause for the UPDATE */ int iDataCur; + int i; assert( v!=0 ); assert( pUpsert!=0 ); @@ -221,7 +222,6 @@ void sqlite3UpsertDoUpdate( Index *pPk = sqlite3PrimaryKeyIndex(pTab); int nPk = pPk->nKeyCol; int iPk = pParse->nMem+1; - int i; pParse->nMem += nPk; for(i=0; ipUpsertSrc, 0); + /* excluded.* columns of type REAL need to be converted to a hard real */ + for(i=0; inCol; i++){ + if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){ + sqlite3VdbeAddOp1(v, OP_RealAffinity, pUpsert->regData+i); + } + } sqlite3Update(pParse, pSrc, pUpsert->pUpsertSet, pUpsert->pUpsertWhere, OE_Abort, 0, 0, pUpsert); pUpsert->pUpsertSet = 0; /* Will have been deleted by sqlite3Update() */ diff --git a/src/vdbe.c b/src/vdbe.c index f46d5924fe..3ef03cd857 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -485,11 +485,12 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ *(zCsr++) = c; sqlite3_snprintf(100, zCsr, "%d[", pMem->n); zCsr += sqlite3Strlen30(zCsr); - for(i=0; i<16 && in; i++){ + for(i=0; i<25 && in; i++){ sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF)); zCsr += sqlite3Strlen30(zCsr); } - for(i=0; i<16 && in; i++){ + *zCsr++ = '|'; + for(i=0; i<25 && in; i++){ char z = pMem->z[i]; if( z<32 || z>126 ) *zCsr++ = '.'; else *zCsr++ = z; @@ -519,7 +520,7 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n); k += sqlite3Strlen30(&zBuf[k]); zBuf[k++] = '['; - for(j=0; j<15 && jn; j++){ + for(j=0; j<25 && jn; j++){ u8 c = pMem->z[j]; if( c>=0x20 && c<0x7f ){ zBuf[k++] = c; @@ -1832,6 +1833,7 @@ case OP_RealAffinity: { /* in1 */ testcase( pIn1->flags & MEM_Int ); testcase( pIn1->flags & MEM_IntReal ); sqlite3VdbeMemRealify(pIn1); + REGISTER_TRACE(pOp->p1, pIn1); } break; } @@ -2227,9 +2229,14 @@ case OP_Compare: { REGISTER_TRACE(p2+idx, &aMem[p2+idx]); assert( inKeyField ); pColl = pKeyInfo->aColl[i]; - bRev = pKeyInfo->aSortOrder[i]; + bRev = (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC); iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl); if( iCompare ){ + if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) + && ((aMem[p1+idx].flags & MEM_Null) || (aMem[p2+idx].flags & MEM_Null)) + ){ + iCompare = -iCompare; + } if( bRev ) iCompare = -iCompare; break; } @@ -2520,11 +2527,6 @@ case OP_Offset: { /* out3 */ ** if the P4 argument is a P4_MEM use the value of the P4 argument as ** the result. ** -** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor, -** then the cache of the cursor is reset prior to extracting the column. -** The first OP_Column against a pseudo-table after the value of the content -** register has changed should have this bit set. -** ** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then ** the result is guaranteed to only be used as the argument of a length() ** or typeof() function, respectively. The loading of large blobs can be @@ -4127,6 +4129,7 @@ case OP_SeekGT: { /* jump, in3, group */ pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; if( pC->isTable ){ + u16 flags3, newType; /* The BTREE_SEEK_EQ flag is only set on index cursors */ assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0 || CORRUPT_DB ); @@ -4135,16 +4138,19 @@ case OP_SeekGT: { /* jump, in3, group */ ** blob, or NULL. But it needs to be an integer before we can do ** the seek, so convert it. */ pIn3 = &aMem[pOp->p3]; - if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Str))==MEM_Str ){ + flags3 = pIn3->flags; + if( (flags3 & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Str))==MEM_Str ){ applyNumericAffinity(pIn3, 0); } - iKey = sqlite3VdbeIntValue(pIn3); + iKey = sqlite3VdbeIntValue(pIn3); /* Get the integer key value */ + newType = pIn3->flags; /* Record the type after applying numeric affinity */ + pIn3->flags = flags3; /* But convert the type back to its original */ /* If the P3 value could not be converted into an integer without ** loss of information, then special processing is required... */ - if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){ - if( (pIn3->flags & MEM_Real)==0 ){ - if( (pIn3->flags & MEM_Null) || oc>=OP_SeekGE ){ + if( (newType & (MEM_Int|MEM_IntReal))==0 ){ + if( (newType & MEM_Real)==0 ){ + if( (newType & MEM_Null) || oc>=OP_SeekGE ){ VdbeBranchTaken(1,2); goto jump_to_p2; }else{ @@ -5440,11 +5446,12 @@ case OP_Next: /* jump */ ** The Prev opcode is only used after SeekLT, SeekLE, and Last. */ assert( pOp->opcode!=OP_Next || pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE - || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found - || pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid); + || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found + || pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid + || pC->seekOp==OP_IfNoHope); assert( pOp->opcode!=OP_Prev || pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE - || pC->seekOp==OP_Last + || pC->seekOp==OP_Last || pC->seekOp==OP_IfNoHope || pC->seekOp==OP_NullRow); rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index d2f408a8c5..afd5b787f9 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1495,14 +1495,16 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ case P4_KEYINFO: { int j; KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; - assert( pKeyInfo->aSortOrder!=0 ); + assert( pKeyInfo->aSortFlags!=0 ); sqlite3_str_appendf(&x, "k(%d", pKeyInfo->nKeyField); for(j=0; jnKeyField; j++){ CollSeq *pColl = pKeyInfo->aColl[j]; const char *zColl = pColl ? pColl->zName : ""; if( strcmp(zColl, "BINARY")==0 ) zColl = "B"; - sqlite3_str_appendf(&x, ",%s%s", - pKeyInfo->aSortOrder[j] ? "-" : "", zColl); + sqlite3_str_appendf(&x, ",%s%s%s", + (pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_DESC) ? "-" : "", + (pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_BIGNULL)? "N." : "", + zColl); } sqlite3_str_append(&x, ")", 1); break; @@ -3815,7 +3817,7 @@ UnpackedRecord *sqlite3VdbeAllocUnpackedRecord( p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte); if( !p ) return 0; p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))]; - assert( pKeyInfo->aSortOrder!=0 ); + assert( pKeyInfo->aSortFlags!=0 ); p->pKeyInfo = pKeyInfo; p->nField = pKeyInfo->nKeyField + 1; return p; @@ -3914,7 +3916,7 @@ static int vdbeRecordCompareDebug( if( szHdr1>98307 ) return SQLITE_CORRUPT; d1 = szHdr1; assert( pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB ); - assert( pKeyInfo->aSortOrder!=0 ); + assert( pKeyInfo->aSortFlags!=0 ); assert( pKeyInfo->nKeyField>0 ); assert( idx1<=szHdr1 || CORRUPT_DB ); do{ @@ -3945,7 +3947,12 @@ static int vdbeRecordCompareDebug( pKeyInfo->nAllField>i ? pKeyInfo->aColl[i] : 0); if( rc!=0 ){ assert( mem1.szMalloc==0 ); /* See comment below */ - if( pKeyInfo->aSortOrder[i] ){ + if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) + && ((mem1.flags & MEM_Null) || (pPKey2->aMem[i].flags & MEM_Null)) + ){ + rc = -rc; + } + if( pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC ){ rc = -rc; /* Invert the result for DESC sort order. */ } goto debugCompareEnd; @@ -4321,7 +4328,7 @@ int sqlite3VdbeRecordCompareWithSkip( VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */ assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB ); - assert( pPKey2->pKeyInfo->aSortOrder!=0 ); + assert( pPKey2->pKeyInfo->aSortFlags!=0 ); assert( pPKey2->pKeyInfo->nKeyField>0 ); assert( idx1<=szHdr1 || CORRUPT_DB ); do{ @@ -4444,8 +4451,14 @@ int sqlite3VdbeRecordCompareWithSkip( } if( rc!=0 ){ - if( pPKey2->pKeyInfo->aSortOrder[i] ){ - rc = -rc; + int sortFlags = pPKey2->pKeyInfo->aSortFlags[i]; + if( sortFlags ){ + if( (sortFlags & KEYINFO_ORDER_BIGNULL)==0 + || ((sortFlags & KEYINFO_ORDER_DESC) + !=(serial_type==0 || (pRhs->flags&MEM_Null))) + ){ + rc = -rc; + } } assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) ); assert( mem1.szMalloc==0 ); /* See comment below */ @@ -4662,7 +4675,10 @@ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ ** header size is (12*5 + 1 + 1) bytes. */ if( p->pKeyInfo->nAllField<=13 ){ int flags = p->aMem[0].flags; - if( p->pKeyInfo->aSortOrder[0] ){ + if( p->pKeyInfo->aSortFlags[0] ){ + if( p->pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL ){ + return sqlite3VdbeRecordCompare; + } p->r1 = 1; p->r2 = -1; }else{ @@ -5008,7 +5024,7 @@ void sqlite3VdbePreUpdateHook( preupdate.keyinfo.db = db; preupdate.keyinfo.enc = ENC(db); preupdate.keyinfo.nKeyField = pTab->nCol; - preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder; + preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder; preupdate.iKey1 = iKey1; preupdate.iKey2 = iKey2; preupdate.pTab = pTab; diff --git a/src/vdbesort.c b/src/vdbesort.c index 05590da7ee..7d60ee5116 100644 --- a/src/vdbesort.c +++ b/src/vdbesort.c @@ -829,7 +829,8 @@ static int vdbeSorterCompareText( ); } }else{ - if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ + assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) ); + if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){ res = res * -1; } } @@ -897,7 +898,8 @@ static int vdbeSorterCompareInt( pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2 ); } - }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){ + }else if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){ + assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) ); res = res * -1; } @@ -1012,6 +1014,7 @@ int sqlite3VdbeSorterInit( if( pKeyInfo->nAllField<13 && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl) + && (pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL)==0 ){ pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT; } diff --git a/src/vtab.c b/src/vtab.c index f9ff48300b..93ce2293e2 100644 --- a/src/vtab.c +++ b/src/vtab.c @@ -32,6 +32,9 @@ struct VtabCtx { ** Construct and install a Module object for a virtual table. When this ** routine is called, it is guaranteed that all appropriate locks are held ** and the module is not already part of the connection. +** +** If there already exists a module with zName, replace it with the new one. +** If pModule==0, then delete the module zName if it exists. */ Module *sqlite3VtabCreateModule( sqlite3 *db, /* Database in which module is registered */ @@ -41,25 +44,36 @@ Module *sqlite3VtabCreateModule( void (*xDestroy)(void *) /* Module destructor function */ ){ Module *pMod; - int nName = sqlite3Strlen30(zName); - pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1); - if( pMod==0 ){ - sqlite3OomFault(db); + Module *pDel; + char *zCopy; + if( pModule==0 ){ + zCopy = (char*)zName; + pMod = 0; }else{ - Module *pDel; - char *zCopy = (char *)(&pMod[1]); + int nName = sqlite3Strlen30(zName); + pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1); + if( pMod==0 ){ + sqlite3OomFault(db); + return 0; + } + zCopy = (char *)(&pMod[1]); memcpy(zCopy, zName, nName+1); pMod->zName = zCopy; pMod->pModule = pModule; pMod->pAux = pAux; pMod->xDestroy = xDestroy; pMod->pEpoTab = 0; - pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); - assert( pDel==0 || pDel==pMod ); - if( pDel ){ + pMod->nRefModule = 1; + } + pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); + if( pDel ){ + if( pDel==pMod ){ sqlite3OomFault(db); sqlite3DbFree(db, pDel); pMod = 0; + }else{ + sqlite3VtabEponymousTableClear(db, pDel); + sqlite3VtabModuleUnref(db, pDel); } } return pMod; @@ -80,11 +94,7 @@ static int createModule( int rc = SQLITE_OK; sqlite3_mutex_enter(db->mutex); - if( sqlite3HashFind(&db->aModule, zName) ){ - rc = SQLITE_MISUSE_BKPT; - }else{ - (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy); - } + (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy); rc = sqlite3ApiExit(db, rc); if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux); sqlite3_mutex_leave(db->mutex); @@ -123,6 +133,44 @@ int sqlite3_create_module_v2( return createModule(db, zName, pModule, pAux, xDestroy); } +/* +** External API to drop all virtual-table modules, except those named +** on the azNames list. +*/ +int sqlite3_drop_modules(sqlite3 *db, const char** azNames){ + HashElem *pThis, *pNext; +#ifdef SQLITE_ENABLE_API_ARMOR + if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; +#endif + for(pThis=sqliteHashFirst(&db->aModule); pThis; pThis=pNext){ + Module *pMod = (Module*)sqliteHashData(pThis); + pNext = sqliteHashNext(pThis); + if( azNames ){ + int ii; + for(ii=0; azNames[ii]!=0 && strcmp(azNames[ii],pMod->zName)!=0; ii++){} + if( azNames[ii]!=0 ) continue; + } + createModule(db, pMod->zName, 0, 0, 0); + } + return SQLITE_OK; +} + +/* +** Decrement the reference count on a Module object. Destroy the +** module when the reference count reaches zero. +*/ +void sqlite3VtabModuleUnref(sqlite3 *db, Module *pMod){ + assert( pMod->nRefModule>0 ); + pMod->nRefModule--; + if( pMod->nRefModule==0 ){ + if( pMod->xDestroy ){ + pMod->xDestroy(pMod->pAux); + } + assert( pMod->pEpoTab==0 ); + sqlite3DbFree(db, pMod); + } +} + /* ** Lock the virtual table so that it cannot be disconnected. ** Locks nest. Every lock should have a corresponding unlock. @@ -180,6 +228,7 @@ void sqlite3VtabUnlock(VTable *pVTab){ pVTab->nRef--; if( pVTab->nRef==0 ){ sqlite3_vtab *p = pVTab->pVtab; + sqlite3VtabModuleUnref(pVTab->db, pVTab->pMod); if( p ){ p->pModule->xDisconnect(p); } @@ -593,6 +642,7 @@ static int vtabCallConstructor( ** the sqlite3_vtab object if successful. */ memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0])); pVTable->pVtab->pModule = pMod->pModule; + pMod->nRefModule++; pVTable->nRef = 1; if( sCtx.bDeclared==0 ){ const char *zFormat = "vtable constructor did not declare schema: %s"; diff --git a/src/where.c b/src/where.c index 65c92863a5..8c7874dc57 100644 --- a/src/where.c +++ b/src/where.c @@ -253,7 +253,8 @@ static WhereTerm *whereScanNext(WhereScan *pScan){ ){ if( (pTerm->eOperator & WO_EQUIV)!=0 && pScan->nEquivaiCur) - && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN + && (pX = sqlite3ExprSkipCollateAndLikely(pTerm->pExpr->pRight))->op + ==TK_COLUMN ){ int j; for(j=0; jnEquiv; j++){ @@ -449,7 +450,7 @@ static int findIndexCol( const char *zColl = pIdx->azColl[iCol]; for(i=0; inExpr; i++){ - Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr); + Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr); if( p->op==TK_COLUMN && p->iColumn==pIdx->aiColumn[iCol] && p->iTable==iBase @@ -513,7 +514,7 @@ static int isDistinctRedundant( ** current SELECT is a correlated sub-query. */ for(i=0; inExpr; i++){ - Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); + Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr); if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; } @@ -933,6 +934,7 @@ static sqlite3_index_info *allocateIndexInfo( for(i=0; ia[i].pExpr; if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; + if( pOrderBy->a[i].sortFlags & KEYINFO_ORDER_BIGNULL ) break; } if( i==n){ nOrderBy = n; @@ -1031,7 +1033,7 @@ static sqlite3_index_info *allocateIndexInfo( for(i=0; ia[i].pExpr; pIdxOrderBy[i].iColumn = pExpr->iColumn; - pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder; + pIdxOrderBy[i].desc = pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC; } *pmNoOmit = mNoOmit; @@ -2516,8 +2518,6 @@ static int whereLoopAddBtreeIndex( }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ /* "x IN (value, value, ...)" */ nIn = sqlite3LogEst(pExpr->x.pList->nExpr); - assert( nIn>0 ); /* RHS always has 2 or more terms... The parser - ** changes "x IN (?)" into "x=?". */ } if( pProbe->hasStat1 ){ LogEst M, logK, safetyMargin; @@ -2670,6 +2670,7 @@ static int whereLoopAddBtreeIndex( ** it to pNew->rRun, which is currently set to the cost of the index ** seek only. Then, if this is a non-covering index, add the cost of ** visiting the rows in the main table. */ + assert( pSrc->pTab->szTabRow>0 ); rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow; pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx); if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){ @@ -2768,7 +2769,7 @@ static int indexMightHelpWithOrderBy( if( pIndex->bUnordered ) return 0; if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0; for(ii=0; iinExpr; ii++){ - Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr); + Expr *pExpr = sqlite3ExprSkipCollateAndLikely(pOB->a[ii].pExpr); if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){ if( pExpr->iColumn<0 ) return 1; for(jj=0; jjnKeyCol; jj++){ @@ -2799,7 +2800,9 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){ } if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0; for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){ - Expr *pExpr = pTerm->pExpr; + Expr *pExpr; + if( pTerm->wtFlags & TERM_NOPARTIDX ) continue; + pExpr = pTerm->pExpr; if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab) && sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab) ){ @@ -3708,7 +3711,7 @@ static i8 wherePathSatisfiesOrderBy( */ for(i=0; ia[i].pExpr); + pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr); if( pOBExpr->op!=TK_COLUMN ) continue; if( pOBExpr->iTable!=iCur ) continue; pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn, @@ -3764,15 +3767,21 @@ static i8 wherePathSatisfiesOrderBy( u16 eOp = pLoop->aLTerm[j]->eOperator; /* Skip over == and IS and ISNULL terms. (Also skip IN terms when - ** doing WHERE_ORDERBY_LIMIT processing). + ** doing WHERE_ORDERBY_LIMIT processing). Except, IS and ISNULL + ** terms imply that the index is not UNIQUE NOT NULL in which case + ** the loop need to be marked as not order-distinct because it can + ** have repeated NULL rows. ** ** If the current term is a column of an ((?,?) IN (SELECT...)) ** expression for which the SELECT returns more than one column, ** check that it is the only column used by this loop. Otherwise, ** if it is one of two or more, none of the columns can be - ** considered to match an ORDER BY term. */ + ** considered to match an ORDER BY term. + */ if( (eOp & eqOpMask)!=0 ){ - if( eOp & WO_ISNULL ){ + if( eOp & (WO_ISNULL|WO_IS) ){ + testcase( eOp & WO_ISNULL ); + testcase( eOp & WO_IS ); testcase( isOrderDistinct ); isOrderDistinct = 0; } @@ -3798,7 +3807,7 @@ static i8 wherePathSatisfiesOrderBy( */ if( pIndex ){ iColumn = pIndex->aiColumn[j]; - revIdx = pIndex->aSortOrder[j]; + revIdx = pIndex->aSortOrder[j] & KEYINFO_ORDER_DESC; if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID; }else{ iColumn = XN_ROWID; @@ -3822,7 +3831,7 @@ static i8 wherePathSatisfiesOrderBy( isMatch = 0; for(i=0; bOnce && ia[i].pExpr); + pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr); testcase( wctrlFlags & WHERE_GROUPBY ); testcase( wctrlFlags & WHERE_DISTINCTBY ); if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0; @@ -3850,22 +3859,28 @@ static i8 wherePathSatisfiesOrderBy( /* Make sure the sort order is compatible in an ORDER BY clause. ** Sort order is irrelevant for a GROUP BY clause. */ if( revSet ){ - if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) isMatch = 0; + if( (rev ^ revIdx)!=(pOrderBy->a[i].sortFlags&KEYINFO_ORDER_DESC) ){ + isMatch = 0; + } }else{ - rev = revIdx ^ pOrderBy->a[i].sortOrder; + rev = revIdx ^ (pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC); if( rev ) *pRevMask |= MASKBIT(iLoop); revSet = 1; } } + if( isMatch && (pOrderBy->a[i].sortFlags & KEYINFO_ORDER_BIGNULL) ){ + if( j==pLoop->u.btree.nEq ){ + pLoop->wsFlags |= WHERE_BIGNULL_SORT; + }else{ + isMatch = 0; + } + } if( isMatch ){ if( iColumn==XN_ROWID ){ testcase( distinctColumns==0 ); distinctColumns = 1; } obSat |= MASKBIT(i); - if( (wctrlFlags & WHERE_ORDERBY_MIN) && j==pLoop->u.btree.nEq ){ - pLoop->wsFlags |= WHERE_MIN_ORDERED; - } }else{ /* No match found */ if( j==0 || jwsFlags & WHERE_CONSTRAINT)!=0 && (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0 + && (pLoop->wsFlags & WHERE_BIGNULL_SORT)==0 && (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 && pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED ){ @@ -5200,6 +5216,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ VdbeCoverageIf(v, pLevel->op==OP_Next); VdbeCoverageIf(v, pLevel->op==OP_Prev); VdbeCoverageIf(v, pLevel->op==OP_VNext); + if( pLevel->regBignull ){ + sqlite3VdbeResolveLabel(v, pLevel->addrBignull); + sqlite3VdbeAddOp2(v, OP_DecrJumpZero, pLevel->regBignull, pLevel->p2-1); + VdbeCoverage(v); + } #ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek); #endif diff --git a/src/whereInt.h b/src/whereInt.h index 09e45024c1..64978cf110 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -71,13 +71,15 @@ struct WhereLevel { int addrCont; /* Jump here to continue with the next loop cycle */ int addrFirst; /* First instruction of interior of the loop */ int addrBody; /* Beginning of the body of this loop */ + int regBignull; /* big-null flag reg. True if a NULL-scan is needed */ + int addrBignull; /* Jump here for next part of big-null scan */ #ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */ int addrLikeRep; /* LIKE range processing address */ #endif u8 iFrom; /* Which entry in the FROM clause */ u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */ - int p1, p2; /* Operands of the opcode used to ends the loop */ + int p1, p2; /* Operands of the opcode used to end the loop */ union { /* Information that depends on pWLoop->wsFlags */ struct { int nIn; /* Number of entries in aInLoop[] */ @@ -289,6 +291,7 @@ struct WhereTerm { #define TERM_LIKE 0x400 /* The original LIKE operator */ #define TERM_IS 0x800 /* Term.pExpr is an IS operator */ #define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */ +#define TERM_NOPARTIDX 0x2000 /* Not for use to enable a partial index */ /* ** An instance of the WhereScan object is used as an iterator for locating @@ -586,6 +589,6 @@ void sqlite3WhereTabFuncArgs(Parse*, struct SrcList_item*, WhereClause*); #define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/ #define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */ #define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */ -#define WHERE_MIN_ORDERED 0x00080000 /* Column nEq of index is min() expr */ +#define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */ #endif /* !defined(SQLITE_WHEREINT_H) */ diff --git a/src/wherecode.c b/src/wherecode.c index c781b06c15..2fbcba17e9 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1117,6 +1117,7 @@ typedef struct IdxExprTrans { static int whereIndexExprTransNode(Walker *p, Expr *pExpr){ IdxExprTrans *pX = p->u.pIdxTrans; if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){ + pExpr->affExpr = sqlite3ExprAffinity(pExpr); pExpr->op = TK_COLUMN; pExpr->iTable = pX->iIdxCur; pExpr->iColumn = pX->iIdxCol; @@ -1549,31 +1550,12 @@ Bitmask sqlite3WhereCodeOneLoopStart( u8 bSeekPastNull = 0; /* True to seek past initial nulls */ u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */ int omitTable; /* True if we use the index only */ - + int regBignull = 0; /* big-null flag register */ pIdx = pLoop->u.btree.pIndex; iIdxCur = pLevel->iIdxCur; assert( nEq>=pLoop->nSkip ); - /* If this loop satisfies a sort order (pOrderBy) request that - ** was passed to this function to implement a "SELECT min(x) ..." - ** query, then the caller will only allow the loop to run for - ** a single iteration. This means that the first row returned - ** should not have a NULL value stored in 'x'. If column 'x' is - ** the first one after the nEq equality constraints in the index, - ** this requires some special handling. - */ - assert( (pWInfo->pOrderBy!=0 && pWInfo->pOrderBy->nExpr==1) - || (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 ); - if( pLoop->wsFlags & WHERE_MIN_ORDERED ){ - assert( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN) ); - assert( pWInfo->nOBSat ); - assert( pIdx->nColumn>nEq ); - assert( pLoop->nSkip==0 ); - bSeekPastNull = 1; - nExtraReg = 1; - } - /* Find any inequality constraint terms for the start and end ** of the range. */ @@ -1614,6 +1596,25 @@ Bitmask sqlite3WhereCodeOneLoopStart( } assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); + /* If the WHERE_BIGNULL_SORT flag is set, then index column nEq uses + ** a non-default "big-null" sort (either ASC NULLS LAST or DESC NULLS + ** FIRST). In both cases separate ordered scans are made of those + ** index entries for which the column is null and for those for which + ** it is not. For an ASC sort, the non-NULL entries are scanned first. + ** For DESC, NULL entries are scanned first. + */ + if( (pLoop->wsFlags & (WHERE_TOP_LIMIT|WHERE_BTM_LIMIT))==0 + && (pLoop->wsFlags & WHERE_BIGNULL_SORT)!=0 + ){ + assert( bSeekPastNull==0 && nExtraReg==0 && nBtm==0 && nTop==0 ); + assert( pRangeEnd==0 && pRangeStart==0 ); + assert( pLoop->nSkip==0 ); + nExtraReg = 1; + bSeekPastNull = 1; + pLevel->regBignull = regBignull = ++pParse->nMem; + pLevel->addrBignull = sqlite3VdbeMakeLabel(pParse); + } + /* If we are doing a reverse order scan on an ascending index, or ** a forward order scan on a descending index, interchange the ** start and end terms (pRangeStart and pRangeEnd). @@ -1636,7 +1637,7 @@ Bitmask sqlite3WhereCodeOneLoopStart( if( zStartAff && nTop ){ zEndAff = sqlite3DbStrDup(db, &zStartAff[nEq]); } - addrNxt = pLevel->addrNxt; + addrNxt = (regBignull ? pLevel->addrBignull : pLevel->addrNxt); testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 ); testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 ); @@ -1670,10 +1671,14 @@ Bitmask sqlite3WhereCodeOneLoopStart( } bSeekPastNull = 0; }else if( bSeekPastNull ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); - nConstraint++; startEq = 0; + sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); start_constraints = 1; + nConstraint++; + }else if( regBignull ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); + start_constraints = 1; + nConstraint++; } codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff); if( pLoop->nSkip>0 && nConstraint==pLoop->nSkip ){ @@ -1684,6 +1689,11 @@ Bitmask sqlite3WhereCodeOneLoopStart( if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur); } + if( regBignull ){ + sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull); + VdbeComment((v, "NULL-scan pass ctr")); + } + op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev]; assert( op!=0 ); sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); @@ -1695,23 +1705,21 @@ Bitmask sqlite3WhereCodeOneLoopStart( VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT ); - if( bSeekPastNull && (pLoop->wsFlags & WHERE_TOP_LIMIT)==0 ){ - /* If bSeekPastNull is set only to skip past the NULL values for - ** a query like "SELECT min(a), b FROM t1", then add code so that - ** if there are no rows with (a IS NOT NULL), then do the seek - ** without jumping past NULLs instead. This allows the code in - ** select.c to pick a value for "b" in the above query. */ - assert( startEq==0 && (op==OP_SeekGT || op==OP_SeekLT) ); - assert( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0 && pWInfo->nOBSat>0 ); - sqlite3VdbeChangeP2(v, -1, sqlite3VdbeCurrentAddr(v)+1); + assert( bSeekPastNull==0 || bStopAtNull==0 ); + if( regBignull ){ + assert( bSeekPastNull==1 || bStopAtNull==1 ); + assert( bSeekPastNull==!bStopAtNull ); + assert( bStopAtNull==startEq ); sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2); - - op = aStartOp[(start_constraints<<2) + (1<<1) + bRev]; - assert( op==OP_SeekGE || op==OP_SeekLE ); - sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); + op = aStartOp[(nConstraint>1)*4 + 2 + bRev]; + sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, + nConstraint-startEq); VdbeCoverage(v); + VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind ); + VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last ); VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE ); VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE ); + assert( op==OP_Rewind || op==OP_Last || op==OP_SeekGE || op==OP_SeekLE); } } @@ -1744,8 +1752,10 @@ Bitmask sqlite3WhereCodeOneLoopStart( endEq = 1; } }else if( bStopAtNull ){ - sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); - endEq = 0; + if( regBignull==0 ){ + sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq); + endEq = 0; + } nConstraint++; } sqlite3DbFree(db, zStartAff); @@ -1756,6 +1766,12 @@ Bitmask sqlite3WhereCodeOneLoopStart( /* Check if the index cursor is past the end of the range. */ if( nConstraint ){ + if( regBignull ){ + /* Except, skip the end-of-range check while doing the NULL-scan */ + sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+3); + VdbeComment((v, "If NULL-scan 2nd pass")); + VdbeCoverage(v); + } op = aEndOp[bRev*2 + endEq]; sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); @@ -1763,6 +1779,23 @@ Bitmask sqlite3WhereCodeOneLoopStart( testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); } + if( regBignull ){ + /* During a NULL-scan, check to see if we have reached the end of + ** the NULLs */ + assert( bSeekPastNull==!bStopAtNull ); + assert( bSeekPastNull+bStopAtNull==1 ); + assert( nConstraint+bSeekPastNull>0 ); + sqlite3VdbeAddOp2(v, OP_If, regBignull, sqlite3VdbeCurrentAddr(v)+2); + VdbeComment((v, "If NULL-scan 1st pass")); + VdbeCoverage(v); + op = aEndOp[bRev*2 + bSeekPastNull]; + sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, + nConstraint+bSeekPastNull); + testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT ); + testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE ); + testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT ); + testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE ); + } if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){ sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1); diff --git a/src/whereexpr.c b/src/whereexpr.c index 252d924b85..f6f966b9e1 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -84,7 +84,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ }else{ pTerm->truthProb = 1; } - pTerm->pExpr = sqlite3ExprSkipCollate(p); + pTerm->pExpr = sqlite3ExprSkipCollateAndLikely(p); pTerm->wtFlags = wtFlags; pTerm->pWC = pWC; pTerm->iParent = -1; @@ -117,10 +117,16 @@ static int allowedOp(int op){ ** the left hand side of a comparison overrides any collation sequence ** attached to the right. For the same reason the EP_Collate flag ** is not commuted. +** +** The return value is extra flags that are added to the WhereTerm object +** after it is commuted. The only extra flag ever added is TERM_NOPARTIDX +** which prevents the term from being used to enable a partial index if +** COLLATE changes have been made. */ -static void exprCommute(Parse *pParse, Expr *pExpr){ +static u16 exprCommute(Parse *pParse, Expr *pExpr){ u16 expRight = (pExpr->pRight->flags & EP_Collate); u16 expLeft = (pExpr->pLeft->flags & EP_Collate); + u16 wtFlags = 0; assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); if( expRight==expLeft ){ /* Either X and Y both have COLLATE operator or neither do */ @@ -128,11 +134,13 @@ static void exprCommute(Parse *pParse, Expr *pExpr){ /* Both X and Y have COLLATE operators. Make sure X is always ** used by clearing the EP_Collate flag from Y. */ pExpr->pRight->flags &= ~EP_Collate; + wtFlags |= TERM_NOPARTIDX; }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){ /* Neither X nor Y have COLLATE operators, but X has a non-default ** collating sequence. So add the EP_Collate marker on X to cause ** it to be searched first. */ pExpr->pLeft->flags |= EP_Collate; + wtFlags |= TERM_NOPARTIDX; } } SWAP(Expr*,pExpr->pRight,pExpr->pLeft); @@ -144,6 +152,7 @@ static void exprCommute(Parse *pParse, Expr *pExpr){ assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE ); pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT; } + return wtFlags; } /* @@ -1140,7 +1149,7 @@ static void exprAnalyze( pDup = pExpr; pNew = pTerm; } - exprCommute(pParse, pDup); + pNew->wtFlags |= exprCommute(pParse, pDup); pNew->leftCursor = aiCurCol[0]; pNew->u.leftColumn = aiCurCol[1]; testcase( (prereqLeft | extraRight) != prereqLeft ); @@ -1451,7 +1460,7 @@ static void exprAnalyze( ** all terms of the WHERE clause. */ void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){ - Expr *pE2 = sqlite3ExprSkipCollate(pExpr); + Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pExpr); pWC->op = op; if( pE2==0 ) return; if( pE2->op!=op ){ diff --git a/src/window.c b/src/window.c index ebcb576bb5..0fb8eb461d 100644 --- a/src/window.c +++ b/src/window.c @@ -888,7 +888,7 @@ static ExprList *exprListAppendList( pDup->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse); } pList = sqlite3ExprListAppend(pParse, pList, pDup); - if( pList ) pList->a[nInit+i].sortOrder = pAppend->a[i].sortOrder; + if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags; } } return pList; @@ -965,8 +965,15 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ ** window function - one for the accumulator, another for interim ** results. */ for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ - pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); - pSublist = exprListAppendList(pParse, pSublist, pWin->pOwner->x.pList, 0); + ExprList *pArgs = pWin->pOwner->x.pList; + if( pWin->pFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){ + selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist); + pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); + pWin->bExprArgs = 1; + }else{ + pWin->iArgCol = (pSublist ? pSublist->nExpr : 0); + pSublist = exprListAppendList(pParse, pSublist, pArgs, 0); + } if( pWin->pFilter ){ Expr *pFilter = sqlite3ExprDup(db, pWin->pFilter, 0); pSublist = sqlite3ExprListAppend(pParse, pSublist, pFilter); @@ -1229,6 +1236,25 @@ void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){ } } +/* +** Possibly link window pWin into the list at pSel->pWin (window functions +** to be processed as part of SELECT statement pSel). The window is linked +** in if either (a) there are no other windows already linked to this +** SELECT, or (b) the windows already linked use a compatible window frame. +*/ +void sqlite3WindowLink(Select *pSel, Window *pWin){ + if( 0==pSel->pWin + || 0==sqlite3WindowCompare(0, pSel->pWin, pWin, 0) + ){ + pWin->pNextWin = pSel->pWin; + if( pSel->pWin ){ + pSel->pWin->ppThis = &pWin->pNextWin; + } + pSel->pWin = pWin; + pWin->ppThis = &pSel->pWin; + } +} + /* ** Return 0 if the two window objects are identical, or non-zero otherwise. ** Identical window objects can be processed in a single scan. @@ -1296,8 +1322,8 @@ void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){ pWin->regApp = pParse->nMem+1; pParse->nMem += 3; if( pKeyInfo && pWin->pFunc->zName[1]=='i' ){ - assert( pKeyInfo->aSortOrder[0]==0 ); - pKeyInfo->aSortOrder[0] = 1; + assert( pKeyInfo->aSortFlags[0]==0 ); + pKeyInfo->aSortFlags[0] = KEYINFO_ORDER_DESC; } sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pWin->csrApp, 2); sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO); @@ -1413,9 +1439,11 @@ static void windowAggStep( for(pWin=pMWin; pWin; pWin=pWin->pNextWin){ FuncDef *pFunc = pWin->pFunc; int regArg; - int nArg = windowArgCount(pWin); + int nArg = pWin->bExprArgs ? 0 : windowArgCount(pWin); int i; + assert( bInverse==0 || pWin->eStart!=TK_UNBOUNDED ); + for(i=0; izName!=nth_valueName ){ sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i); @@ -1453,14 +1481,29 @@ static void windowAggStep( int addrIf = 0; if( pWin->pFilter ){ int regTmp; - assert( nArg==0 || nArg==pWin->pOwner->x.pList->nExpr ); - assert( nArg || pWin->pOwner->x.pList==0 ); + assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr ); + assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 ); regTmp = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp); addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1); VdbeCoverage(v); sqlite3ReleaseTempReg(pParse, regTmp); } + if( pWin->bExprArgs ){ + int iStart = sqlite3VdbeCurrentAddr(v); + VdbeOp *pOp, *pEnd; + + nArg = pWin->pOwner->x.pList->nExpr; + regArg = sqlite3GetTempRange(pParse, nArg); + sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0); + + pEnd = sqlite3VdbeGetOp(v, -1); + for(pOp=sqlite3VdbeGetOp(v, iStart); pOp<=pEnd; pOp++){ + if( pOp->opcode==OP_Column && pOp->p1==pWin->iEphCsr ){ + pOp->p1 = csr; + } + } + } if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ CollSeq *pColl; assert( nArg>0 ); @@ -1471,6 +1514,9 @@ static void windowAggStep( bInverse, regArg, pWin->regAccum); sqlite3VdbeAppendP4(v, pFunc, P4_FUNCDEF); sqlite3VdbeChangeP5(v, (u8)nArg); + if( pWin->bExprArgs ){ + sqlite3ReleaseTempRange(pParse, regArg, nArg); + } if( addrIf ) sqlite3VdbeJumpHere(v, addrIf); } } @@ -1478,19 +1524,78 @@ static void windowAggStep( typedef struct WindowCodeArg WindowCodeArg; typedef struct WindowCsrAndReg WindowCsrAndReg; + +/* +** See comments above struct WindowCodeArg. +*/ struct WindowCsrAndReg { - int csr; - int reg; + int csr; /* Cursor number */ + int reg; /* First in array of peer values */ }; +/* +** A single instance of this structure is allocated on the stack by +** sqlite3WindowCodeStep() and a pointer to it passed to the various helper +** routines. This is to reduce the number of arguments required by each +** helper function. +** +** regArg: +** Each window function requires an accumulator register (just as an +** ordinary aggregate function does). This variable is set to the first +** in an array of accumulator registers - one for each window function +** in the WindowCodeArg.pMWin list. +** +** eDelete: +** The window functions implementation sometimes caches the input rows +** that it processes in a temporary table. If it is not zero, this +** variable indicates when rows may be removed from the temp table (in +** order to reduce memory requirements - it would always be safe just +** to leave them there). Possible values for eDelete are: +** +** WINDOW_RETURN_ROW: +** An input row can be discarded after it is returned to the caller. +** +** WINDOW_AGGINVERSE: +** An input row can be discarded after the window functions xInverse() +** callbacks have been invoked in it. +** +** WINDOW_AGGSTEP: +** An input row can be discarded after the window functions xStep() +** callbacks have been invoked in it. +** +** start,current,end +** Consider a window-frame similar to the following: +** +** (ORDER BY a, b GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING) +** +** The windows functions implmentation caches the input rows in a temp +** table, sorted by "a, b" (it actually populates the cache lazily, and +** aggressively removes rows once they are no longer required, but that's +** a mere detail). It keeps three cursors open on the temp table. One +** (current) that points to the next row to return to the query engine +** once its window function values have been calculated. Another (end) +** points to the next row to call the xStep() method of each window function +** on (so that it is 2 groups ahead of current). And a third (start) that +** points to the next row to call the xInverse() method of each window +** function on. +** +** Each cursor (start, current and end) consists of a VDBE cursor +** (WindowCsrAndReg.csr) and an array of registers (starting at +** WindowCodeArg.reg) that always contains a copy of the peer values +** read from the corresponding cursor. +** +** Depending on the window-frame in question, all three cursors may not +** be required. In this case both WindowCodeArg.csr and reg are set to +** 0. +*/ struct WindowCodeArg { - Parse *pParse; - Window *pMWin; - Vdbe *pVdbe; - int regGosub; - int addrGosub; - int regArg; - int eDelete; + Parse *pParse; /* Parse context */ + Window *pMWin; /* First in list of functions being processed */ + Vdbe *pVdbe; /* VDBE object */ + int addrGosub; /* OP_Gosub to this address to return one row */ + int regGosub; /* Register used with OP_Gosub(addrGosub) */ + int regArg; /* First in array of accumulator registers */ + int eDelete; /* See above */ WindowCsrAndReg start; WindowCsrAndReg current; @@ -1833,34 +1938,46 @@ static void windowIfNewPeer( /* ** This function is called as part of generating VM programs for RANGE ** offset PRECEDING/FOLLOWING frame boundaries. Assuming "ASC" order for -** the ORDER BY term in the window, it generates code equivalent to: +** the ORDER BY term in the window, and that argument op is OP_Ge, it generates +** code equivalent to: ** ** if( csr1.peerVal + regVal >= csr2.peerVal ) goto lbl; ** -** A special type of arithmetic is used such that if csr.peerVal is not -** a numeric type (real or integer), then the result of the addition is -** a copy of csr1.peerVal. +** The value of parameter op may also be OP_Gt or OP_Le. In these cases the +** operator in the above pseudo-code is replaced with ">" or "<=", respectively. +** +** If the sort-order for the ORDER BY term in the window is DESC, then the +** comparison is reversed. Instead of adding regVal to csr1.peerVal, it is +** subtracted. And the comparison operator is inverted to - ">=" becomes "<=", +** ">" becomes "<", and so on. So, with DESC sort order, if the argument op +** is OP_Ge, the generated code is equivalent to: +** +** if( csr1.peerVal - regVal <= csr2.peerVal ) goto lbl; +** +** A special type of arithmetic is used such that if csr1.peerVal is not +** a numeric type (real or integer), then the result of the addition addition +** or subtraction is a a copy of csr1.peerVal. */ static void windowCodeRangeTest( WindowCodeArg *p, - int op, /* OP_Ge or OP_Gt */ - int csr1, - int regVal, - int csr2, - int lbl + int op, /* OP_Ge, OP_Gt, or OP_Le */ + int csr1, /* Cursor number for cursor 1 */ + int regVal, /* Register containing non-negative number */ + int csr2, /* Cursor number for cursor 2 */ + int lbl /* Jump destination if condition is true */ ){ Parse *pParse = p->pParse; Vdbe *v = sqlite3GetVdbe(pParse); - int reg1 = sqlite3GetTempReg(pParse); - int reg2 = sqlite3GetTempReg(pParse); - int arith = OP_Add; - int addrGe; - - int regString = ++pParse->nMem; + ExprList *pOrderBy = p->pMWin->pOrderBy; /* ORDER BY clause for window */ + int reg1 = sqlite3GetTempReg(pParse); /* Reg. for csr1.peerVal+regVal */ + int reg2 = sqlite3GetTempReg(pParse); /* Reg. for csr2.peerVal */ + int regString = ++pParse->nMem; /* Reg. for constant value '' */ + int arith = OP_Add; /* OP_Add or OP_Subtract */ + int addrGe; /* Jump destination */ assert( op==OP_Ge || op==OP_Gt || op==OP_Le ); - assert( p->pMWin->pOrderBy && p->pMWin->pOrderBy->nExpr==1 ); - if( p->pMWin->pOrderBy->a[0].sortOrder ){ + assert( pOrderBy && pOrderBy->nExpr==1 ); + if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_DESC ){ switch( op ){ case OP_Ge: op = OP_Le; break; case OP_Gt: op = OP_Lt; break; @@ -1869,27 +1986,95 @@ static void windowCodeRangeTest( arith = OP_Subtract; } + /* Read the peer-value from each cursor into a register */ windowReadPeerValues(p, csr1, reg1); windowReadPeerValues(p, csr2, reg2); - /* Check if the peer value for csr1 value is a text or blob by comparing - ** it to the smallest possible string - ''. If it is, jump over the - ** OP_Add or OP_Subtract operation and proceed directly to the comparison. */ + VdbeModuleComment((v, "CodeRangeTest: if( R%d %s R%d %s R%d ) goto lbl", + reg1, (arith==OP_Add ? "+" : "-"), regVal, + ((op==OP_Ge) ? ">=" : (op==OP_Le) ? "<=" : (op==OP_Gt) ? ">" : "<"), reg2 + )); + + /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1). + ** This block adds (or subtracts for DESC) the numeric value in regVal + ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob), + ** then leave reg1 as it is. In pseudo-code, this is implemented as: + ** + ** if( reg1>='' ) goto addrGe; + ** reg1 = reg1 +/- regVal + ** addrGe: + ** + ** Since all strings and blobs are greater-than-or-equal-to an empty string, + ** the add/subtract is skipped for these, as required. If reg1 is a NULL, + ** then the arithmetic is performed, but since adding or subtracting from + ** NULL is always NULL anyway, this case is handled as required too. */ sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC); addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1); VdbeCoverage(v); sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1); sqlite3VdbeJumpHere(v, addrGe); + + /* If the BIGNULL flag is set for the ORDER BY, then it is required to + ** consider NULL values to be larger than all other values, instead of + ** the usual smaller. The VDBE opcodes OP_Ge and so on do not handle this + ** (and adding that capability causes a performance regression), so + ** instead if the BIGNULL flag is set then cases where either reg1 or + ** reg2 are NULL are handled separately in the following block. The code + ** generated is equivalent to: + ** + ** if( reg1 IS NULL ){ + ** if( op==OP_Ge ) goto lbl; + ** if( op==OP_Gt && reg2 IS NOT NULL ) goto lbl; + ** if( op==OP_Le && reg2 IS NULL ) goto lbl; + ** }else if( reg2 IS NULL ){ + ** if( op==OP_Le ) goto lbl; + ** } + ** + ** Additionally, if either reg1 or reg2 are NULL but the jump to lbl is + ** not taken, control jumps over the comparison operator coded below this + ** block. */ + if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_BIGNULL ){ + /* This block runs if reg1 contains a NULL. */ + int addr = sqlite3VdbeAddOp1(v, OP_NotNull, reg1); VdbeCoverage(v); + switch( op ){ + case OP_Ge: + sqlite3VdbeAddOp2(v, OP_Goto, 0, lbl); + break; + case OP_Gt: + sqlite3VdbeAddOp2(v, OP_NotNull, reg2, lbl); + VdbeCoverage(v); + break; + case OP_Le: + sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); + VdbeCoverage(v); + break; + default: assert( op==OP_Lt ); /* no-op */ break; + } + sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3); + + /* This block runs if reg1 is not NULL, but reg2 is. */ + sqlite3VdbeJumpHere(v, addr); + sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); VdbeCoverage(v); + if( op==OP_Gt || op==OP_Ge ){ + sqlite3VdbeChangeP2(v, -1, sqlite3VdbeCurrentAddr(v)+1); + } + } + + /* Compare registers reg2 and reg1, taking the jump if required. Note that + ** control skips over this test if the BIGNULL flag is set and either + ** reg1 or reg2 contain a NULL value. */ sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v); sqlite3VdbeChangeP5(v, SQLITE_NULLEQ); + assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le ); testcase(op==OP_Ge); VdbeCoverageIf(v, op==OP_Ge); testcase(op==OP_Lt); VdbeCoverageIf(v, op==OP_Lt); testcase(op==OP_Le); VdbeCoverageIf(v, op==OP_Le); testcase(op==OP_Gt); VdbeCoverageIf(v, op==OP_Gt); - sqlite3ReleaseTempReg(pParse, reg1); sqlite3ReleaseTempReg(pParse, reg2); + + VdbeModuleComment((v, "CodeRangeTest: end")); } /* @@ -2030,6 +2215,7 @@ Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ pNew = sqlite3DbMallocZero(db, sizeof(Window)); if( pNew ){ pNew->zName = sqlite3DbStrDup(db, p->zName); + pNew->zBase = sqlite3DbStrDup(db, p->zBase); pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0); pNew->pFunc = p->pFunc; pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0); @@ -2042,6 +2228,7 @@ Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){ pNew->pStart = sqlite3ExprDup(db, p->pStart, 0); pNew->pEnd = sqlite3ExprDup(db, p->pEnd, 0); pNew->pOwner = pOwner; + pNew->bImplicitFrame = p->bImplicitFrame; } } return pNew; @@ -2585,7 +2772,7 @@ void sqlite3WindowCodeStep( windowCheckValue(pParse, regEnd, 1 + (pMWin->eFrmType==TK_RANGE ? 3 : 0)); } - if( pMWin->eStart==pMWin->eEnd && regStart ){ + if( pMWin->eFrmType!=TK_RANGE && pMWin->eStart==pMWin->eEnd && regStart ){ int op = ((pMWin->eStart==TK_FOLLOWING) ? OP_Ge : OP_Le); int addrGe = sqlite3VdbeAddOp3(v, op, regStart, 0, regEnd); VdbeCoverageNeverNullIf(v, op==OP_Ge); /* NeverNull because bound */ diff --git a/test/affinity2.test b/test/affinity2.test index 9838bd660a..acdf91c062 100644 --- a/test/affinity2.test +++ b/test/affinity2.test @@ -14,6 +14,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +set testprefix affinity2 do_execsql_test affinity2-100 { CREATE TABLE t1( @@ -58,4 +59,73 @@ do_execsql_test affinity2-300 { SELECT rowid, xt==+xi, xt==xi, xt==xb FROM t1 ORDER BY rowid; } {1 1 1 0 2 1 1 1 3 0 1 1} +#------------------------------------------------------------------------- +do_execsql_test 400 { + CREATE TABLE ttt(c0, c1); + CREATE INDEX ii ON ttt(CAST(c0 AS NUMERIC)); + INSERT INTO ttt VALUES('abc', '-1'); +} +do_execsql_test 410 { + SELECT * FROM ttt WHERE CAST(c0 AS NUMERIC) > c1 GROUP BY rowid; +} {abc -1} +do_execsql_test 420 { + SELECT * FROM ttt INDEXED BY ii WHERE CAST(c0 AS NUMERIC) > c1 GROUP BY rowid; +} {abc -1} + +do_execsql_test 430 { + CREATE TABLE t3(a, b, c INTEGER); + CREATE INDEX t3ac ON t3(a, c-1); + INSERT INTO t3 VALUES(1, 1, 1); + INSERT INTO t3 VALUES(2, 1, 0); + INSERT INTO t3 VALUES(3, 1, 1); + INSERT INTO t3 VALUES(4, 1, 0); + INSERT INTO t3 VALUES(5, 1, 1); +} +do_execsql_test 440 { + SELECT * FROM t3 WHERE c='0' ORDER BY a; +} {2 1 0 4 1 0} + +# 2019-08-22 ticket https://sqlite.org/src/info/d99f1ffe836c591ac57f +# False positive in sqlite3ExprNeedsNoAffinityChange() +# +do_execsql_test 500 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0(c0 TEXT UNIQUE, c1); + INSERT INTO t0(c0) VALUES (-1); + SELECT quote(- x'ce'), quote(t0.c0), quote(- x'ce' >= t0.c0) FROM t0; +} {0 '-1' 1} +do_execsql_test 501 { + SELECT * FROM t0 WHERE - x'ce' >= t0.c0; +} {-1 {}} +do_execsql_test 502 { + SELECT quote(+-+x'ce'), quote(t0.c0), quote(+-+x'ce' >= t0.c0) FROM t0; +} {0 '-1' 1} +do_execsql_test 503 { + SELECT * FROM t0 WHERE +-+x'ce' >= t0.c0; +} {-1 {}} +do_execsql_test 504 { + SELECT quote(- 'ce'), quote(t0.c0), quote(- 'ce' >= t0.c0) FROM t0; +} {0 '-1' 1} +do_execsql_test 505 { + SELECT * FROM t0 WHERE - 'ce' >= t0.c0; +} {-1 {}} +do_execsql_test 506 { + SELECT quote(+-+'ce'), quote(t0.c0), quote(+-+'ce' >= t0.c0) FROM t0; +} {0 '-1' 1} +do_execsql_test 507 { + SELECT * FROM t0 WHERE +-+'ce' >= t0.c0; +} {-1 {}} + +# 2019-08-30 ticket https://www.sqlite.org/src/info/40812aea1fde9594 +# +do_execsql_test 600 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0(c0 REAL UNIQUE); + INSERT INTO t0(c0) VALUES (3175546974276630385); + SELECT 3175546974276630385 < c0 FROM t0; +} {1} +do_execsql_test 601 { + SELECT 1 FROM t0 WHERE 3175546974276630385 < c0; +} {1} + finish_test diff --git a/test/aggnested.test b/test/aggnested.test index 91de63b768..d712c840f1 100644 --- a/test/aggnested.test +++ b/test/aggnested.test @@ -1,4 +1,4 @@ -# 2012 August 23 +# 2012-08-23 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: @@ -232,6 +232,34 @@ do_test aggnested-3.16 { GROUP BY id1; } } {12 2 34 4} + +# 2019-08-31 +# Problem found by dbsqlfuzz +# +do_execsql_test aggnested-4.1 { + DROP TABLE IF EXISTS aa; + DROP TABLE IF EXISTS bb; + CREATE TABLE aa(x INT); INSERT INTO aa(x) VALUES(123); + CREATE TABLE bb(y INT); INSERT INTO bb(y) VALUES(456); + SELECT (SELECT sum(x+(SELECT y)) FROM bb) FROM aa; +} {579} +do_execsql_test aggnested-4.2 { + SELECT (SELECT sum(x+y) FROM bb) FROM aa; +} {579} +do_execsql_test aggnested-4.3 { + DROP TABLE IF EXISTS tx; + DROP TABLE IF EXISTS ty; + CREATE TABLE tx(x INT); + INSERT INTO tx VALUES(1),(2),(3),(4),(5); + CREATE TABLE ty(y INT); + INSERT INTO ty VALUES(91),(92),(93); + SELECT min((SELECT count(y) FROM ty)) FROM tx; +} {3} +do_execsql_test aggnested-4.4 { + SELECT max((SELECT a FROM (SELECT count(*) AS a FROM ty) AS s)) FROM tx; +} {3} + + finish_test diff --git a/test/analyzeC.test b/test/analyzeC.test index 02faa9c7e9..2a0a897810 100644 --- a/test/analyzeC.test +++ b/test/analyzeC.test @@ -132,6 +132,20 @@ do_execsql_test 4.3 { SELECT count(a) FROM t1; } {/.*INDEX t1ca.*/} +# 2019-08-15. +# Ticket https://www.sqlite.org/src/tktview/e4598ecbdd18bd82945f602901 +# The sz=N parameter in the sqlite_stat1 table needs to have a value of +# 2 or more to avoid a division by zero in the query planner. +# +do_execsql_test 4.4 { + DROP TABLE IF EXISTS t44; + CREATE TABLE t44(a PRIMARY KEY); + INSERT INTO sqlite_stat1 VALUES('t44',null,'sz=0'); + ANALYZE sqlite_master; + SELECT 0 FROM t44 WHERE a IN(1,2,3); +} {} + + # The sz=NNN parameter works even if there is other extraneous text # in the sqlite_stat1.stat column. diff --git a/test/check.test b/test/check.test index b703c75b00..e23043eb04 100644 --- a/test/check.test +++ b/test/check.test @@ -123,6 +123,11 @@ do_test check-2.1 { y REAL CONSTRAINT two CHECK( typeof(coalesce(y,0.1))=='real' ), z TEXT CONSTRAINT three CHECK( typeof(coalesce(z,''))=='text' ) ); + CREATE TABLE t2n( + x INTEGER CONSTRAINT one CHECK( typeof(coalesce(x,0))=="integer" ), + y NUMERIC CONSTRAINT two CHECK( typeof(coalesce(y,0.1))=='real' ), + z TEXT CONSTRAINT three CHECK( typeof(coalesce(z,''))=='text' ) + ); PRAGMA writable_schema = 0; } } {} @@ -146,9 +151,17 @@ do_test check-2.4 { } } {1 {CHECK constraint failed: one}} do_test check-2.5 { + # The 5 gets automatically promoted to 5.0 because the column type is REAL catchsql { INSERT INTO t2 VALUES(NULL, 5, NULL); } +} {0 {}} +do_test check-2.5b { + # This time the column type is NUMERIC, so not automatic promption to REAL + # occurs and the constraint fails. + catchsql { + INSERT INTO t2n VALUES(NULL, 5, NULL); + } } {1 {CHECK constraint failed: two}} do_test check-2.6 { catchsql { @@ -195,6 +208,7 @@ do_test check-2.cleanup { execsql { DROP TABLE IF EXISTS t2b; DROP TABLE IF EXISTS t2c; + DROP TABLE IF EXISTS t2n; } } {} diff --git a/test/conflict3.test b/test/conflict3.test index 751a442685..413e8241fe 100644 --- a/test/conflict3.test +++ b/test/conflict3.test @@ -366,5 +366,73 @@ do_execsql_test 12.3 { SELECT * FROM t2; } {111 111B 112 112} +#------------------------------------------------------------------------- +ifcapable trigger { + reset_db + do_execsql_test 13.1.0 { + PRAGMA recursive_triggers = true; + CREATE TABLE t0 (c0 UNIQUE, c1 UNIQUE); + CREATE TRIGGER tr0 AFTER DELETE ON t0 BEGIN + DELETE FROM t0; + END; + + INSERT INTO t0 VALUES(1, NULL); + INSERT INTO t0 VALUES(0, NULL); + } + + do_execsql_test 13.1.1 { + UPDATE OR REPLACE t0 SET c1 = 1; + } + + integrity_check 13.1.2 + + do_execsql_test 13.1.3 { + SELECT * FROM t0 + } {} + + do_execsql_test 13.2.0 { + CREATE TABLE t2 (a PRIMARY KEY, b UNIQUE, c UNIQUE) WITHOUT ROWID; + CREATE TRIGGER tr3 AFTER DELETE ON t2 BEGIN + DELETE FROM t2; + END; + + INSERT INTO t2 VALUES(1, 1, 1); + INSERT INTO t2 VALUES(2, 2, 2); + } + + do_execsql_test 13.2.1 { + UPDATE OR REPLACE t2 SET c = 0; + } + + integrity_check 13.2.2 + + do_execsql_test 13.2.3 { + SELECT * FROM t2 + } {} + + do_execsql_test 13.3.0 { + CREATE TABLE t1(a, b); + CREATE TABLE log(x); + CREATE INDEX i1 ON t1(a); + INSERT INTO t1 VALUES(1, 2); + + CREATE TRIGGER tb BEFORE UPDATE ON t1 BEGIN + DELETE FROM t1; + END; + CREATE TRIGGER ta AFTER UPDATE ON t1 BEGIN + INSERT INTO log VALUES('fired!'); + END; + + UPDATE t1 SET b=3; + } + + do_execsql_test 13.3.1 { + SELECT * FROM t1; + } {} + do_execsql_test 13.3.2 { + SELECT * FROM log; + } {} +} finish_test + diff --git a/test/distinct2.test b/test/distinct2.test index 634dfd72e3..c42a1c971a 100644 --- a/test/distinct2.test +++ b/test/distinct2.test @@ -274,6 +274,32 @@ do_execsql_test 2040 { two 1 1 } +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 3000 { + CREATE TABLE t0 (c0, c1 NOT NULL DEFAULT 1, c2, PRIMARY KEY (c0, c1)); + INSERT INTO t0(c2) VALUES (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL), (NULL); + INSERT INTO t0(c2) VALUES('a'); +} +do_execsql_test 3010 { + SELECT DISTINCT * FROM t0 WHERE NULL IS t0.c0; +} { + {} 1 {} + {} 1 a +} + +do_execsql_test 3020 { + ANALYZE; +} + +do_execsql_test 3030 { + SELECT DISTINCT * FROM t0 WHERE NULL IS c0; +} { + {} 1 {} + {} 1 a +} finish_test + diff --git a/test/fts3corrupt4.test b/test/fts3corrupt4.test index fdcfa969f2..d693702bf5 100644 --- a/test/fts3corrupt4.test +++ b/test/fts3corrupt4.test @@ -2147,6 +2147,7 @@ do_test 14.0 { }]} {} do_execsql_test 14.1 { + PRAGMA writable_schema = 1; WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10) INSERT INTO t1(a) SELECT randomblob(3000) FROM c; } @@ -3049,6 +3050,7 @@ do_test 19.0 { }]} {} do_catchsql_test 19.1 { + PRAGMA writable_schema = 1; SELECT rowid,a,c,snippet(t1,85101090932165,-1,10) FROM t1 WHERE a MATCH 'rtree'; } {1 {database disk image is malformed}} @@ -3250,6 +3252,7 @@ do_test 20.0 { }]} {} do_execsql_test 20.1 { + PRAGMA writable_schema = 1; BEGIN; WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10) INSERT INTO t1(a) SELECT randomblob(3000) FROM c; @@ -3472,8 +3475,8 @@ do_test 21.0 { | end crash-18cc014e42e828.db }]} {} -breakpoint do_catchsql_test 21.1 { + PRAGMA writable_schema = 1; SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'R*'; } {1 {database disk image is malformed}} @@ -3694,6 +3697,7 @@ do_test 22.0 { }]} {} do_catchsql_test 22.1 { + PRAGMA writable_schema = 1; SELECT snippet(t1,'', '', '--',-1,01)==0 FROM t1 WHERE a MATCH 'rtree OR json1rtree OR json1'; } {0 {0 0 0 0 0 0 0}} @@ -3913,6 +3917,7 @@ do_test 23.0 { }]} {} do_catchsql_test 23.1 { + PRAGMA writable_schema = 1; SELECT 'FyzLy'FROM t1 WHERE t1 MATCH 'j'; } {1 {database disk image is malformed}} @@ -4131,6 +4136,7 @@ do_test 24.0 { }]} {} do_catchsql_test 24.1 { + PRAGMA writable_schema = 1; WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT '4hE'+x FROM c WHERE x<72) INSERT INTO t1(a) SELECT randomblob(2829) FROM c; } {0 {}} @@ -4374,6 +4380,7 @@ do_test 25.0 { }]} {} do_catchsql_test 25.1 { + PRAGMA writable_schema = 1; WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x%1 FROM c WHERE x<599237) INSERT INTO t1( a ) SELECT randomblob(3000) FROM t2 ; } {0 {}} @@ -4608,6 +4615,7 @@ do_test 26.0 { }]} {} do_execsql_test 26.1 { + PRAGMA writable_schema = 1; SELECT count(*) FROM ( SELECT t1, (t1) FROM t1 WHERE b MATCH 'x' ) @@ -4826,6 +4834,7 @@ do_test 27.0 { }]} {} do_catchsql_test 27.2 { + PRAGMA writable_schema = 1; WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x GLOB 2.16770 FROM x) INSERT INTO t1(a) SELECT randomblob(3000) FROM t2 ; } {0 {}} @@ -5058,6 +5067,7 @@ do_test 28.0 { }]} {} do_catchsql_test 28.1 { + PRAGMA writable_schema = 1; WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT 3+x FROM c WHERE x<72) INSERT INTO t1(a) SELECT randomblob(2829) FROM c; } {0 {}} @@ -5312,6 +5322,7 @@ do_test 29.0 { }]} {} do_catchsql_test 29.1 { + PRAGMA writable_schema = 1; INSERT INTO t1(a) SELECT X'819192E578DE3F'; UPDATE t1 SET b=quote(zeroblob(current_date)) WHERE t1 MATCH 't*'; INSERT INTO t1(b) VALUES(x'78'); diff --git a/test/fts3snippet.test b/test/fts3snippet.test index ebcdb8cffd..976c8c8492 100644 --- a/test/fts3snippet.test +++ b/test/fts3snippet.test @@ -561,7 +561,31 @@ do_test 4.3 { }] } {64} +#------------------------------------------------------------------------- +# Request a snippet from a query with more than 64 phrases. +# +do_execsql_test 5.0 { + CREATE VIRTUAL TABLE t5 USING fts3(x); + INSERT INTO t5 VALUES('a1 a2 a3'); + INSERT INTO t5 VALUES('a4 a5 a6'); + INSERT INTO t5 VALUES('a70 a71 a72'); +} +do_execsql_test 5.1 { + SELECT snippet(t5, '[', ']') FROM t5 WHERE t5 MATCH + 'a1 OR a2 OR a3 OR a4 OR a5 OR a6 OR a7 OR a8 OR a9 OR a10 OR ' || + 'a11 OR a12 OR a13 OR a14 OR a15 OR a16 OR a17 OR a18 OR a19 OR a10 OR ' || + 'a21 OR a22 OR a23 OR a24 OR a25 OR a26 OR a27 OR a28 OR a29 OR a20 OR ' || + 'a31 OR a32 OR a33 OR a34 OR a35 OR a36 OR a37 OR a38 OR a39 OR a30 OR ' || + 'a41 OR a42 OR a43 OR a44 OR a45 OR a46 OR a47 OR a48 OR a49 OR a40 OR ' || + 'a51 OR a52 OR a53 OR a54 OR a55 OR a56 OR a57 OR a58 OR a59 OR a50 OR ' || + 'a61 OR a62 OR a63 OR a64 OR a65 OR a66 OR a67 OR a68 OR a69 OR a60 OR ' || + 'a71 OR a72 OR a73 OR a74 OR a75 OR a76 OR a77 OR a78 OR a79 OR a70' +} { + {[a1] [a2] [a3]} + {[a4] [a5] [a6]} + {[a70] [a71] [a72]} +} set sqlite_fts3_enable_parentheses 0 finish_test diff --git a/test/func.test b/test/func.test index 579bad8e44..7315af322a 100644 --- a/test/func.test +++ b/test/func.test @@ -1419,7 +1419,45 @@ do_execsql_test func-32.150 { SELECT test_frombind(x.a,y.b,x.c,:123,y.e,x.f,$xyz+y.f) FROM t1 x, t1 y; } {8} - +# 2019-08-15 +# Direct-only functions. +# +proc testdirectonly {x} {return [expr {$x*2}]} +do_test func-33.1 { + db func testdirectonly -directonly testdirectonly + db eval {SELECT testdirectonly(15)} +} {30} +do_catchsql_test func-33.2 { + CREATE VIEW v33(y) AS SELECT testdirectonly(15); + SELECT * FROM v33; +} {1 {testdirectonly() prohibited in triggers and views}} +do_execsql_test func-33.3 { + SELECT * FROM (SELECT testdirectonly(15)) AS v33; +} {30} +do_execsql_test func-33.4 { + WITH c(x) AS (SELECT testdirectonly(15)) + SELECT * FROM c; +} {30} +do_catchsql_test func-33.5 { + WITH c(x) AS (SELECT * FROM v33) + SELECT * FROM c; +} {1 {testdirectonly() prohibited in triggers and views}} +do_execsql_test func-33.10 { + CREATE TABLE t33a(a,b); + CREATE TABLE t33b(x,y); + CREATE TRIGGER r1 AFTER INSERT ON t33a BEGIN + INSERT INTO t33b(x,y) VALUES(testdirectonly(new.a),new.b); + END; +} {} +do_catchsql_test func-33.11 { + INSERT INTO t33a VALUES(1,2); +} {1 {testdirectonly() prohibited in triggers and views}} +do_execsql_test func-33.20 { + ALTER TABLE t33a RENAME COLUMN a TO aaa; + SELECT sql FROM sqlite_master WHERE name='r1'; +} {{CREATE TRIGGER r1 AFTER INSERT ON t33a BEGIN + INSERT INTO t33b(x,y) VALUES(testdirectonly(new.aaa),new.b); + END}} finish_test diff --git a/test/fuzzdata8.db b/test/fuzzdata8.db index 353f39ba70..5abaf46cb9 100644 Binary files a/test/fuzzdata8.db and b/test/fuzzdata8.db differ diff --git a/test/in.test b/test/in.test index c247f2e070..4595d5fd19 100644 --- a/test/in.test +++ b/test/in.test @@ -750,4 +750,39 @@ do_execsql_test in-17.4 { SELECT 1 IN (CAST('1' AS text) COLLATE nocase); } 0 +# 2019-08-27 ticket https://sqlite.org/src/info/dbaf8a6820be1ece +# +do_execsql_test in-18.1 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0(c0 INT UNIQUE); + INSERT INTO t0(c0) VALUES (1); + SELECT * FROM t0 WHERE '1' IN (t0.c0); +} {} + +# 2019-09-02 ticket https://www.sqlite.org/src/info/2841e99d104c6436 +# For the IN_INDEX_NOOP optimization, apply REAL affinity to the LHS +# values prior to comparison if the RHS has REAL affinity. +# +# Also ticket https://sqlite.org/src/info/29f635e0af71234b +# +do_execsql_test in-19.1 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0(c0 REAL UNIQUE); + INSERT INTO t0(c0) VALUES(2.07093491255203046E18); + SELECT 1 FROM t0 WHERE c0 IN ('2070934912552030444'); +} {1} +do_execsql_test in-19.2 { + SELECT c0 IN ('2070934912552030444') FROM t0; +} {1} +do_execsql_test in-19.3 { + SELECT c0 IN ('2070934912552030444',2,3) FROM t0; +} {1} +do_execsql_test in-19.4 { + DROP TABLE t0; + CREATE TABLE t0(c0 TEXT, c1 REAL, c2, PRIMARY KEY(c2, c0, c1)); + CREATE INDEX i0 ON t0(c1 IN (c0)); + INSERT INTO t0(c0, c2) VALUES (0, NULL) ON CONFLICT(c2, c1, c0) DO NOTHING; + PRAGMA integrity_check; +} {ok} + finish_test diff --git a/test/in4.test b/test/in4.test index a89961f82b..787b9ea36c 100644 --- a/test/in4.test +++ b/test/in4.test @@ -226,10 +226,13 @@ do_execsql_test in4-3.42 { do_execsql_test in4-3.43 { SELECT * FROM t3 WHERE x IN (10); } {10 10 10} -do_execsql_test in4-3.44 { - EXPLAIN - SELECT * FROM t3 WHERE x IN (10); -} {~/OpenEphemeral/} + +# This test would verify that the "X IN (Y)" -> "X==Y" optimization +# was working. But we have now taken that optimization out. +#do_execsql_test in4-3.44 { +# EXPLAIN +# SELECT * FROM t3 WHERE x IN (10); +#} {~/OpenEphemeral/} do_execsql_test in4-3.45 { SELECT * FROM t3 WHERE x NOT IN (10,11,99999); } {1 1 1} @@ -326,7 +329,7 @@ do_execsql_test in4-6.1 { do_execsql_test in4-6.1-eqp { EXPLAIN QUERY PLAN SELECT * FROM t6a, t6b WHERE a=3 AND b IN (c); -} {~/SCAN/} +} {~/SCAN TABLE t6a/} do_execsql_test in4-6.2 { SELECT * FROM t6a, t6b WHERE a=3 AND c IN (b); } {3 4 4 44} diff --git a/test/in5.test b/test/in5.test index a5ea7c1784..6680641ff3 100644 --- a/test/in5.test +++ b/test/in5.test @@ -248,5 +248,22 @@ do_execsql_test 9.1 { SELECT * FROM t9 WHERE a IN (44, 45, 44, 45) } {44 45} +#------------------------------------------------------------------------- +# Test that ticket c7a117190 is fixed. +# +reset_db +do_execsql_test 9.0 { + CREATE TABLE t0(c0); + CREATE VIEW v0(c0) AS SELECT LOWER(CAST('1e500' AS TEXT)) FROM t0; + INSERT INTO t0(c0) VALUES (NULL); +} + +do_execsql_test 9.1 { + SELECT lower('1e500') FROM t0 WHERE rowid NOT IN (0, 0, lower('1e500')); +} {1e500} + +do_execsql_test 9.2 { + SELECT lower('1e500') FROM t0 WHERE rowid != lower('1e500'); +} {1e500} finish_test diff --git a/test/index6.test b/test/index6.test index 5faf0f02ac..976c49fb86 100644 --- a/test/index6.test +++ b/test/index6.test @@ -437,4 +437,48 @@ do_execsql_test index6-14.2 { SELECT * FROM t0 WHERE CASE c0 WHEN 0 THEN 0 ELSE 1 END; } {{} row} +# 2019-08-30 +# Ticket https://www.sqlite.org/src/info/a6408d42b9f44462 +# Ticket https://www.sqlite.org/src/info/fba33c8b1df6a915 +# https://sqlite.org/src/info/bac716244fddac1fe841 +# +do_execsql_test index6-15.1 { + DROP TABLE t0; + CREATE TABLE t0(c0); + INSERT INTO t0(c0) VALUES (NULL); + CREATE INDEX i0 ON t0(1) WHERE c0 NOT NULL; + SELECT 1 FROM t0 WHERE (t0.c0 IS FALSE) IS FALSE; +} {1} +do_execsql_test index6-15.2 { + SELECT 1 FROM t0 WHERE (t0.c0 IS FALSE) BETWEEN FALSE AND TRUE; +} {1} +do_execsql_test index6-15.3 { + SELECT 1 FROM t0 WHERE TRUE BETWEEN (t0.c0 IS FALSE) AND TRUE; +} {1} +do_execsql_test index6-15.4 { + SELECT 1 FROM t0 WHERE FALSE BETWEEN FALSE AND (t0.c0 IS FALSE); +} {1} +do_execsql_test index6-15.5 { + SELECT 1 FROM t0 WHERE (c0 IS FALSE) IN (FALSE); +} {1} + +# 2019-09-03 +# Ticket https://sqlite.org/src/info/767a8cbc6d20bd68 +do_execsql_test index6-16.1 { + DROP TABLE t0; + CREATE TABLE t0(c0 COLLATE NOCASE, c1); + CREATE INDEX i0 ON t0(0) WHERE c0 >= c1; + INSERT INTO t0 VALUES('a', 'B'); + SELECT c1 <= c0, c0 >= c1 FROM t0; +} {1 0} +do_execsql_test index6-16.2 { + SELECT 2 FROM t0 WHERE c0 >= c1; +} {} +do_execsql_test index6-16.3 { + SELECT 3 FROM t0 WHERE c1 <= c0; +} {3} + + + + finish_test diff --git a/test/indexexpr1.test b/test/indexexpr1.test index ed7d9ffbc2..353792875b 100644 --- a/test/indexexpr1.test +++ b/test/indexexpr1.test @@ -457,4 +457,28 @@ do_execsql_test indexexpr-1700 { SELECT * FROM t0 WHERE ((NULL IS FALSE) IS FALSE); } {0} +# 2019-09-02 https://www.sqlite.org/src/tktview/57af00b6642ecd6848 +# When the expression of an an index-on-expression references a +# table column of type REAL that is actually holding an MEM_IntReal +# value, be sure to use the REAL value and not the INT value when +# computing the expression. +# +do_execsql_test indexexpr-1800 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0(c0 REAL, c1 TEXT); + CREATE INDEX i0 ON t0(+c0, c0); + INSERT INTO t0(c0) VALUES(0); + SELECT CAST(+ t0.c0 AS BLOB) LIKE 0 FROM t0; +} {0} +do_execsql_test indexexpr-1810 { + SELECT CAST(+ t0.c0 AS BLOB) LIKE '0.0' FROM t0; +} {1} +do_execsql_test indexexpr-1820 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(x REAL); + CREATE INDEX t1x ON t1(x, +x); + INSERT INTO t1(x) VALUES(2); + SELECT +x FROM t1 WHERE x=2; +} {2.0} + finish_test diff --git a/test/indexexpr2.test b/test/indexexpr2.test index a3a685fb3d..5d387c7523 100644 --- a/test/indexexpr2.test +++ b/test/indexexpr2.test @@ -295,6 +295,82 @@ do_execsql_test 7.3 { REINDEX; } {} +#------------------------------------------------------------------------- +reset_db +do_execsql_test 8.0 { + CREATE TABLE t0(c0); + CREATE INDEX i0 ON t0(c0) WHERE c0 NOT NULL; + INSERT INTO t0(c0) VALUES (NULL); +} +do_execsql_test 8.1.1 { + SELECT * FROM t0 WHERE ~('' BETWEEN t0.c0 AND TRUE); +} {{}} +do_execsql_test 8.1.2 { + SELECT ~('' BETWEEN t0.c0 AND TRUE) FROM t0; +} {-1} + +foreach {tn expr} { + 1 " 0 == (34 BETWEEN c0 AND 33)" + 2 " 1 != (34 BETWEEN c0 AND 33)" + 3 "-1 < (34 BETWEEN c0 AND 33)" + 4 "-1 <= (34 BETWEEN c0 AND 33)" + 5 " 1 > (34 BETWEEN c0 AND 33)" + 6 " 1 >= (34 BETWEEN c0 AND 33)" + 7 " 1 - (34 BETWEEN c0 AND 33)" + 8 "-1 + (34 BETWEEN c0 AND 33)" + 9 " 1 | (34 BETWEEN c0 AND 33)" + 10 " 1 << (34 BETWEEN c0 AND 33)" + 11 " 1 >> (34 BETWEEN c0 AND 33)" + 12 " 1 || (34 BETWEEN c0 AND 33)" +} { + do_execsql_test 8.3.$tn.1 "SELECT * FROM t0 WHERE $expr ORDER BY c0" { {} } + do_execsql_test 8.3.$tn.2 "SELECT ($expr) IS TRUE FROM t0" { 1 } +} + +do_execsql_test 8.4 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(1, 2), (3, 4); + CREATE TABLE t2(x, y); +} + +foreach {tn expr} { + 1 " 0 == (a=0 AND y=1)" + 2 " 1 != (a=0 AND y=1)" + 3 "-1 < (a=0 AND y=1)" + 4 "-1 <= (a=0 AND y=1)" + 5 " 1 > (a=0 AND y=1)" + 6 " 1 >= (a=0 AND y=1)" + 7 " 1 - (a=0 AND y=1)" + 8 "-1 + (a=0 AND y=1)" + 9 " 1 | (a=0 AND y=1)" + 10 "1 << (a=0 AND y=1)" + 11 "1 >> (a=0 AND y=1)" + 12 "1 || (a=0 AND y=1)" + + 13 " 0 == (10 BETWEEN y AND b)" + 14 " 1 != (10 BETWEEN y AND b)" + 15 "-1 < (10 BETWEEN y AND b)" + 16 "-1 <= (10 BETWEEN y AND b)" + 17 " 1 > (10 BETWEEN y AND b)" + 18 " 1 >= (10 BETWEEN y AND b)" + 19 " 1 - (10 BETWEEN y AND b)" + 20 "-1 + (10 BETWEEN y AND b)" + 21 " 1 | (10 BETWEEN y AND b)" + 22 " 1 << (10 BETWEEN y AND b)" + 23 " 1 >> (10 BETWEEN y AND b)" + 24 " 1 || (10 BETWEEN y AND b)" + + 25 " 1 || (10 BETWEEN y AND b)" +} { + do_execsql_test 8.5.$tn.1 " + SELECT * FROM t1 LEFT JOIN t2 WHERE $expr + " {1 2 {} {} 3 4 {} {}} + + do_execsql_test 8.5.$tn.2 " + SELECT ($expr) IS TRUE FROM t1 LEFT JOIN t2 + " {1 1} +} finish_test + diff --git a/test/intarray.test b/test/intarray.test index 049f117cc2..2250027c5d 100644 --- a/test/intarray.test +++ b/test/intarray.test @@ -47,12 +47,12 @@ do_test intarray-1.1 { } } {table ia1 table ia2 table ia3 table ia4} -# Verify the inability to DROP and recreate an intarray virtual table. +# Verify the ability to DROP and recreate an intarray virtual table. do_test intarray-1.1b { db eval {DROP TABLE ia1} - set rc [catch {sqlite3_intarray_create db ia1} msg] - lappend rc $msg -} {1 SQLITE_MISUSE} + set rc [catch {sqlite3_intarray_create db ia1} ia1] + lappend rc $ia1 +} {/0 [0-9A-Z]+/} do_test intarray-1.2 { db eval { diff --git a/test/join.test b/test/join.test index f613df85b0..f53a90c84a 100644 --- a/test/join.test +++ b/test/join.test @@ -812,11 +812,16 @@ do_execsql_test join-15.105 { FROM t1 LEFT JOIN t2 WHERE a IN (1,3,x,y); } {1 2 {} {} x 3 4 {} {} x} -do_execsql_test join-15.106 { +do_execsql_test join-15.106a { SELECT *, 'x' FROM t1 LEFT JOIN t2 WHERE NOT ( 'x'='y' AND t2.y=1 ); } {1 2 {} {} x 3 4 {} {} x} +do_execsql_test join-15.106b { + SELECT *, 'x' + FROM t1 LEFT JOIN t2 + WHERE ~ ( 'x'='y' AND t2.y=1 ); +} {1 2 {} {} x 3 4 {} {} x} do_execsql_test join-15.107 { SELECT *, 'x' FROM t1 LEFT JOIN t2 @@ -864,4 +869,19 @@ do_execsql_test join-16.100 { WHERE (b IS NOT NULL)=0; } {1 {}} +# 2019-08-17 ticket https://sqlite.org/src/tktview/6710d2f7a13a299728ab +# Ensure that constants that derive from the right-hand table of a LEFT JOIN +# are never factored out, since they are not really constant. +# +do_execsql_test join-17.100 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(x); + INSERT INTO t1(x) VALUES(0),(1); + SELECT * FROM t1 LEFT JOIN (SELECT abs(1) AS y FROM t1) ON x WHERE NOT(y='a'); +} {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} + finish_test diff --git a/test/minmax4.test b/test/minmax4.test index eeb8bff0bb..775fee86be 100644 --- a/test/minmax4.test +++ b/test/minmax4.test @@ -200,4 +200,37 @@ do_execsql_test 5.1 { SELECT MIN(a) FROM t1 WHERE a=123; } {123} +#------------------------------------------------------------------------- +# Tests for ticket f8a7060ece. +# +reset_db +do_execsql_test 6.1.0 { + CREATE TABLE t1(a, b, c); + INSERT INTO t1 VALUES(NULL, 1, 'x'); + CREATE INDEX i1 ON t1(a); +} +do_execsql_test 6.1.1 { + SELECT min(a), b, c FROM t1 WHERE c='x'; +} {{} 1 x} +do_execsql_test 6.1.2 { + INSERT INTO t1 VALUES(1, 2, 'y'); +} {} +do_execsql_test 6.1.3 { + SELECT min(a), b, c FROM t1 WHERE c='x'; +} {{} 1 x} + +do_execsql_test 6.2.0 { + CREATE TABLE t0(c0 UNIQUE, c1); + INSERT INTO t0(c1) VALUES (0); + INSERT INTO t0(c0) VALUES (0); + CREATE VIEW v0(c0, c1) AS + SELECT t0.c1, t0.c0 FROM t0 WHERE CAST(t0.rowid AS INT) = 1; +} +do_execsql_test 6.2.1 { + SELECT c0, c1 FROM v0; +} {0 {}} +do_execsql_test 6.2.2 { + SELECT v0.c0, MIN(v0.c1) FROM v0; +} {0 {}} + finish_test diff --git a/test/nulls1.test b/test/nulls1.test new file mode 100644 index 0000000000..98fc6ab37d --- /dev/null +++ b/test/nulls1.test @@ -0,0 +1,253 @@ +# 2019 August 10 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix nulls1 + +do_execsql_test 1.0 { + DROP TABLE IF EXISTS t3; + CREATE TABLE t3(a INTEGER); + INSERT INTO t3 VALUES(NULL), (10), (30), (20), (NULL); +} {} + +for {set a 0} {$a < 3} {incr a} { + foreach {tn limit} { + 1 "" + 2 "LIMIT 10" + } { + do_execsql_test 1.$a.$tn.1 " + SELECT a FROM t3 ORDER BY a nULLS FIRST $limit + " {{} {} 10 20 30} + + do_execsql_test 1.$a.$tn.2 " + SELECT a FROM t3 ORDER BY a nULLS LAST $limit + " {10 20 30 {} {}} + + do_execsql_test 1.$a.$tn.3 " + SELECT a FROM t3 ORDER BY a DESC nULLS FIRST $limit + " {{} {} 30 20 10} + + do_execsql_test 1.$a.$tn.4 " + SELECT a FROM t3 ORDER BY a DESC nULLS LAST $limit + " {30 20 10 {} {}} + } + + switch $a { + 0 { + execsql { CREATE INDEX i1 ON t3(a) } + } + 1 { + execsql { DROP INDEX i1 ; CREATE INDEX i1 ON t3(a DESC) } + } + } +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 2.0 { + CREATE TABLE t2(a, b, c); + CREATE INDEX i2 ON t2(a, b); + INSERT INTO t2 VALUES(1, 1, 1); + INSERT INTO t2 VALUES(1, NULL, 2); + INSERT INTO t2 VALUES(1, NULL, 3); + INSERT INTO t2 VALUES(1, 4, 4); +} + +do_execsql_test 2.1 { + SELECT * FROM t2 WHERE a=1 ORDER BY b NULLS LAST +} { + 1 1 1 1 4 4 1 {} 2 1 {} 3 +} + +do_execsql_test 2.2 { + SELECT * FROM t2 WHERE a=1 ORDER BY b DESC NULLS FIRST +} { + 1 {} 3 + 1 {} 2 + 1 4 4 + 1 1 1 +} + +#------------------------------------------------------------------------- +# +reset_db +do_execsql_test 3.0 { + CREATE TABLE t1(a, b, c, d, UNIQUE (b)); +} +foreach {tn sql err} { + 1 { CREATE INDEX i1 ON t1(a ASC NULLS LAST) } LAST + 2 { CREATE INDEX i1 ON t1(a ASC NULLS FIRST) } FIRST + 3 { CREATE INDEX i1 ON t1(a, b ASC NULLS LAST) } LAST + 4 { CREATE INDEX i1 ON t1(a, b ASC NULLS FIRST) } FIRST + 5 { CREATE INDEX i1 ON t1(a DESC NULLS LAST) } LAST + 6 { CREATE INDEX i1 ON t1(a DESC NULLS FIRST) } FIRST + 7 { CREATE INDEX i1 ON t1(a, b DESC NULLS LAST) } LAST + 8 { CREATE INDEX i1 ON t1(a, b DESC NULLS FIRST) } FIRST + 9 { CREATE TABLE t2(a, b, PRIMARY KEY(a DESC, b NULLS FIRST)) } FIRST + 10 { CREATE TABLE t2(a, b, UNIQUE(a DESC NULLS FIRST, b)) } FIRST + 11 { INSERT INTO t1 VALUES(1, 2, 3, 4) + ON CONFLICT (b DESC NULLS LAST) DO UPDATE SET a = a+1 } LAST + 12 { + CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN + INSERT INTO t1 VALUES(1, 2, 3, 4) + ON CONFLICT (b DESC NULLS FIRST) DO UPDATE SET a = a+1; + END + } FIRST +} { + do_catchsql_test 3.1.$tn $sql "1 {unsupported use of NULLS $err}" +} + +do_execsql_test 3.2 { + CREATE TABLE first(nulls, last); + INSERT INTO first(last, nulls) VALUES(100,200), (300,400), (200,300); + SELECT * FROM first ORDER BY nulls; +} { + 200 100 + 300 200 + 400 300 +} + +#------------------------------------------------------------------------- +# +ifcapable vtab { + register_echo_module db + do_execsql_test 4.0 { + CREATE TABLE tx(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX i1 ON tx(b); + INSERT INTO tx VALUES(1, 1, 1); + INSERT INTO tx VALUES(2, NULL, 2); + INSERT INTO tx VALUES(3, 3, 3); + INSERT INTO tx VALUES(4, NULL, 4); + INSERT INTO tx VALUES(5, 5, 5); + CREATE VIRTUAL TABLE te USING echo(tx); + } + + do_execsql_test 4.1 { + SELECT * FROM tx ORDER BY b NULLS FIRST; + } {2 {} 2 4 {} 4 1 1 1 3 3 3 5 5 5} + do_execsql_test 4.2 { + SELECT * FROM te ORDER BY b NULLS FIRST; + } {2 {} 2 4 {} 4 1 1 1 3 3 3 5 5 5} + + do_execsql_test 4.3 { + SELECT * FROM tx ORDER BY b NULLS LAST; + } {1 1 1 3 3 3 5 5 5 2 {} 2 4 {} 4} + do_execsql_test 4.4 { + SELECT * FROM te ORDER BY b NULLS LAST; + } {1 1 1 3 3 3 5 5 5 2 {} 2 4 {} 4} +} + +#------------------------------------------------------------------------- +# +do_execsql_test 5.0 { + CREATE TABLE t4(a, b, c); + INSERT INTO t4 VALUES(1, 1, 11); + INSERT INTO t4 VALUES(1, 2, 12); + INSERT INTO t4 VALUES(1, NULL, 1); + + INSERT INTO t4 VALUES(2, NULL, 1); + INSERT INTO t4 VALUES(2, 2, 12); + INSERT INTO t4 VALUES(2, 1, 11); + + INSERT INTO t4 VALUES(3, NULL, 1); + INSERT INTO t4 VALUES(3, 2, 12); + INSERT INTO t4 VALUES(3, NULL, 3); +} + +do_execsql_test 5.1 { + SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a, b NULLS LAST +} { + 1 1 11 1 2 12 1 {} 1 + 2 1 11 2 2 12 2 {} 1 + 3 2 12 3 {} 1 3 {} 3 +} +do_execsql_test 5.2 { + CREATE INDEX t4ab ON t4(a, b); + SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a, b NULLS LAST +} { + 1 1 11 1 2 12 1 {} 1 + 2 1 11 2 2 12 2 {} 1 + 3 2 12 3 {} 1 3 {} 3 +} +do_eqp_test 5.3 { + SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a, b NULLS LAST +} { + QUERY PLAN + `--SEARCH TABLE t4 USING INDEX t4ab (a=?) +} + +do_execsql_test 5.4 { + SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a DESC, b DESC NULLS FIRST +} { + 3 {} 3 3 {} 1 3 2 12 + 2 {} 1 2 2 12 2 1 11 + 1 {} 1 1 2 12 1 1 11 +} +do_eqp_test 5.5 { + SELECT * FROM t4 WHERE a IN (1, 2, 3) ORDER BY a DESC, b DESC NULLS FIRST +} { + QUERY PLAN + `--SEARCH TABLE t4 USING INDEX t4ab (a=?) +} + +#------------------------------------------------------------------------- +# +do_execsql_test 6.0 { + CREATE TABLE t5(a, b, c); + WITH s(i) AS ( + VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<200 + ) + INSERT INTO t5 SELECT i%2, CASE WHEN (i%10)==0 THEN NULL ELSE i END, i FROM s; +} + +set res1 [db eval { SELECT a,b FROM t5 WHERE a=1 ORDER BY b NULLS LAST, c }] +set res2 [db eval { + SELECT a,b FROM t5 WHERE a=1 ORDER BY b DESC NULLS FIRST, c DESC +}] + +do_execsql_test 6.1.1 { + CREATE INDEX t5ab ON t5(a, b, c); + SELECT a,b FROM t5 WHERE a=1 ORDER BY b NULLS LAST, c; +} $res1 +do_eqp_test 6.1.2 { + SELECT a,b FROM t5 WHERE a=1 ORDER BY b NULLS LAST, c; +} { + QUERY PLAN + `--SEARCH TABLE t5 USING COVERING INDEX t5ab (a=?) +} +do_execsql_test 6.2.1 { + SELECT a,b FROM t5 WHERE a=1 ORDER BY b DESC NULLS FIRST, c DESC +} $res2 +do_eqp_test 6.2.2 { + SELECT a,b FROM t5 WHERE a=1 ORDER BY b DESC NULLS FIRST, c DESC +} { + QUERY PLAN + `--SEARCH TABLE t5 USING COVERING INDEX t5ab (a=?) +} + +#------------------------------------------------------------------------- +do_execsql_test 7.0 { + CREATE TABLE t71(a, b, c); + CREATE INDEX t71abc ON t71(a, b, c); + + SELECT * FROM t71 WHERE a=1 AND b=2 ORDER BY c NULLS LAST; + SELECT * FROM t71 WHERE a=1 AND b=2 ORDER BY c DESC NULLS FIRST; + + SELECT * FROM t71 ORDER BY a NULLS LAST; + SELECT * FROM t71 ORDER BY a DESC NULLS FIRST; +} + +finish_test + + diff --git a/test/pg_common.tcl b/test/pg_common.tcl index bbc52ebede..b3f35cd0ed 100644 --- a/test/pg_common.tcl +++ b/test/pg_common.tcl @@ -70,8 +70,8 @@ proc execsql {sql} { proc execsql_test {tn sql} { set res [execsql $sql] set sql [string map {string_agg group_concat} $sql] - set sql [string map [list {NULLS FIRST} {}] $sql] - set sql [string map [list {NULLS LAST} {}] $sql] + # set sql [string map [list {NULLS FIRST} {}] $sql] + # set sql [string map [list {NULLS LAST} {}] $sql] puts $::fd "do_execsql_test $tn {" puts $::fd " [string trim $sql]" puts $::fd "} {$res}" diff --git a/test/pragma5.test b/test/pragma5.test index d2c58000cf..f16e4627ba 100644 --- a/test/pragma5.test +++ b/test/pragma5.test @@ -11,9 +11,9 @@ # This file implements regression tests for SQLite library. # # This file implements tests for the PRAGMA command. Specifically, -# those pragmas enabled at build time by setting: +# those pragmas that are not disabled at build time by setting: # -# -DSQLITE_INTROSPECTION_PRAGMAS +# -DSQLITE_OMIT_INTROSPECTION_PRAGMAS # set testdir [file dirname $argv0] diff --git a/test/rowvalue7.test b/test/rowvalue7.test index f6764f301e..03591afaf4 100644 --- a/test/rowvalue7.test +++ b/test/rowvalue7.test @@ -55,4 +55,14 @@ do_catchsql_test 2.2 { UPDATE t1 SET (b,c,d) = (SELECT x,y FROM t2 WHERE w=a); } {1 {3 columns assigned 2 values}} +# 2019-08-26 +# ticket https://www.sqlite.org/src/info/78acc9d40f0786e8 +# +do_catchsql_test 3.0 { + DROP TABLE IF EXISTS t1; + CREATE TABLE t1(a,b); + INSERT INTO t1 VALUES(1,2); + UPDATE t1 SET (a,a,a,b)=(SELECT 99,100); +} {1 {4 columns assigned 2 values}} + finish_test diff --git a/test/tclsqlite.test b/test/tclsqlite.test index 705e6b7ca1..468e2efb78 100644 --- a/test/tclsqlite.test +++ b/test/tclsqlite.test @@ -45,7 +45,7 @@ do_test tcl-1.1.1 { do_test tcl-1.2 { set v [catch {db bogus} msg] lappend v $msg -} {1 {bad option "bogus": must be authorizer, backup, bind_fallback, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, deserialize, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, serialize, status, timeout, total_changes, trace, trace_v2, transaction, unlock_notify, update_hook, version, or wal_hook}} +} {1 {bad option "bogus": must be authorizer, backup, bind_fallback, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, config, copy, deserialize, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, preupdate, profile, progress, rekey, restore, rollback_hook, serialize, status, timeout, total_changes, trace, trace_v2, transaction, unlock_notify, update_hook, version, or wal_hook}} do_test tcl-1.2.1 { set v [catch {db cache bogus} msg] lappend v $msg @@ -792,7 +792,7 @@ do_test 17.6.2 { do_test 17.6.3 { list [catch { db function xyz -n object ret } msg] $msg -} {1 {bad option "-n": must be -argcount, -deterministic or -returntype}} +} {1 {bad option "-n": must be -argcount, -deterministic, -directonly, or -returntype}} # 2019-02-28: The "bind_fallback" command. # diff --git a/test/tkt-18458b1a.test b/test/tkt-18458b1a.test new file mode 100644 index 0000000000..996ca88451 --- /dev/null +++ b/test/tkt-18458b1a.test @@ -0,0 +1,53 @@ +# 2019 September 10 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. In particular, +# that problems related to ticket [18458b1a] have been fixed. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix tkt-18458b1a + +foreach tn {1 2} { + reset_db + if {$tn==1} { + # Disable the flattener and push-down optimizations + optimization_control db query-flattener 0 + optimization_control db push-down 0 + } else { + # Enable them + optimization_control db query-flattener 1 + optimization_control db push-down 1 + } + + db cache size 0 + + do_execsql_test $tn.1.1 { + CREATE TABLE t0(c0 COLLATE NOCASE); + INSERT INTO t0(c0) VALUES ('B'); + CREATE VIEW v0(c0, c1) AS SELECT DISTINCT t0.c0, 'a' FROM t0; + } + + do_execsql_test $tn.1.2 { + SELECT count(*) FROM v0 WHERE c1 >= c0; + } 1 + + do_execsql_test $tn.1.3 { + SELECT count(*) FROM v0 WHERE NOT NOT (c1 >= c0); + } 1 + + do_execsql_test $tn.1.4 { + SELECT count(*) FROM v0 WHERE ((c1 >= c0) OR 0+0); + } 1 +} + +finish_test + diff --git a/test/tkt-a7debbe0.test b/test/tkt-a7debbe0.test new file mode 100644 index 0000000000..974f6d66b0 --- /dev/null +++ b/test/tkt-a7debbe0.test @@ -0,0 +1,103 @@ +# 2019 September 10 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. In particular, +# that problems related to ticket a7debbe0ad1 have been fixed. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix tkt-a7debbe0 + +foreach tn {1 2} { + reset_db + if {$tn==1} { + # Disable the flattener + optimization_control db query-flattener 0 + } else { + # Enable the flattener + optimization_control db query-flattener 1 + } + + do_execsql_test $tn.1.0 { + CREATE TABLE t0(xyz INTEGER); + INSERT INTO t0(xyz) VALUES(456); + CREATE VIEW v2(a, B) AS + SELECT 'a', 'B' COLLATE NOCASE FROM t0; + CREATE TABLE t2(a, B COLLATE NOCASE); + INSERT INTO t2 VALUES('a', 'B'); + CREATE VIEW v3(a, B) AS + SELECT 'a' COLLATE BINARY, 'B' COLLATE NOCASE FROM t0; + + CREATE VIEW v4(a, B) AS + SELECT 'a', +CAST('B' COLLATE NOCASE AS TEXT) FROM t0; + + CREATE VIEW v5(a, B) AS + SELECT 'a', ('B' COLLATE NOCASE) || '' FROM t0; + } + + # Table t2 and views v2 through v5 should all be equivalent. + do_execsql_test $tn.1.1.1 { SELECT a >= B FROM t2; } 1 + do_execsql_test $tn.1.1.2 { SELECT 'a' >= 'B' COLLATE NOCASE } 0 + do_execsql_test $tn.1.1.3 { SELECT a >= B FROM v2 } 1 + do_execsql_test $tn.1.1.4 { SELECT a >= B FROM v3 } 1 + do_execsql_test $tn.1.1.5 { SELECT a >= B FROM v4 } 1 + do_execsql_test $tn.1.1.6 { SELECT a >= B FROM v5 } 1 + + do_execsql_test $tn.1.2.1 { SELECT B < a FROM t2 } 0 + do_execsql_test $tn.1.2.2 { SELECT 'B' COLLATE NOCASE < 'a' } 0 + do_execsql_test $tn.1.2.3 { SELECT B < a FROM v2 } 0 + do_execsql_test $tn.1.2.4 { SELECT B < a FROM v3 } 0 + do_execsql_test $tn.1.2.5 { SELECT a < B FROM v4 } 0 + do_execsql_test $tn.1.2.6 { SELECT a < B FROM v5 } 0 + + #------------------------------------------------------------------------- + do_execsql_test $tn.2.0 { + CREATE TABLE t5(a, b COLLATE NOCASE); + INSERT INTO t5 VALUES(1, 'XYZ'); + } + + # Result should be 0, as column "xyz" from the sub-query has implicit + # collation sequence BINARY. + do_execsql_test $tn.2.1 { + SELECT xyz==b FROM ( SELECT a, 'xyz' AS xyz FROM t5 ), t5; + } {0} + + # Result should be 1, as literal 'xyz' has no collation sequence, so + # the comparison uses the implicit collation sequence of the RHS - NOCASE. + do_execsql_test $tn.2.2 { + SELECT 'xyz'==b FROM ( SELECT a, 'xyz' AS xyz FROM t5 ), t5; + } {1} + + #----------------------------------------------------------------------- + # The test case submitted with the ticket. + # + do_execsql_test $tn.3.0 { + DROP TABLE t0; + DROP VIEW v2; + + CREATE TABLE t0(c0); + INSERT INTO t0(c0) VALUES(''); + CREATE VIEW v2(c0, c1) AS + SELECT 'B' COLLATE NOCASE, 'a' FROM t0 ORDER BY t0.c0; + SELECT SUM(count) FROM ( + SELECT v2.c1 BETWEEN v2.c0 AND v2.c1 as count FROM v2 + ); + } 1 + + # The result is 1, as the collation used is the implicit collation sequence + # of v2.c1 - BINARY. + do_execsql_test $tn.3.1 { + SELECT v2.c1 BETWEEN v2.c0 AND v2.c1 as count FROM v2; + } 1 +} + +finish_test + diff --git a/test/trigger1.test b/test/trigger1.test index 8946cd85c9..ddb40e3adb 100644 --- a/test/trigger1.test +++ b/test/trigger1.test @@ -768,4 +768,18 @@ do_execsql_test trigger1-19.1 { SELECT * FROM t19; } {1 2 2} +# 2019-08-26 Chromium sqlite3_fts3_lpm_fuzzer find. +# +db close +sqlite3 db :memory: +do_execsql_test trigger1-20.1 { + CREATE TABLE t20_1(x); + ATTACH ':memory:' AS aux; + CREATE TABLE aux.t20_2(y); + CREATE TABLE aux.t20_3(z); + CREATE TEMP TRIGGER r20_3 AFTER INSERT ON t20_2 BEGIN UPDATE t20_3 SET z=z+1; END; + DETACH aux; + DROP TRIGGER r20_3; +} {} + finish_test diff --git a/test/upsert1.test b/test/upsert1.test index 0d13cd8543..006af438dc 100644 --- a/test/upsert1.test +++ b/test/upsert1.test @@ -210,5 +210,15 @@ do_execsql_test upsert1-780 { SELECT * FROM t1; } {1 2 33 4 5} +# 2019-08-30 ticket https://sqlite.org/src/info/5a3dba8104421320 +do_execsql_test upsert1-800 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0(c0 REAL UNIQUE, c1); + CREATE UNIQUE INDEX test800i0 ON t0(0 || c1); + INSERT INTO t0(c0, c1) VALUES (1, 2), (2, 1); + INSERT INTO t0(c0) VALUES (1) ON CONFLICT(c0) DO UPDATE SET c1=excluded.c0; + PRAGMA integrity_check; + REINDEX; +} {ok} finish_test diff --git a/test/view.test b/test/view.test index 490dc65a68..b3f50dc008 100644 --- a/test/view.test +++ b/test/view.test @@ -38,6 +38,18 @@ do_test view-1.1 { SELECT * FROM v1 ORDER BY a; } } {1 2 4 5 7 8} +do_test view-1.1.100 { + db config enable_view off + catchsql { + SELECT * FROM v1 ORDER BY a; + } +} {1 {access to view "v1" prohibited}} +do_test view-1.1.110 { + db config enable_view on + catchsql { + SELECT * FROM v1 ORDER BY a; + } +} {0 {1 2 4 5 7 8}} do_test view-1.2 { catchsql { ROLLBACK; diff --git a/test/vtab1.test b/test/vtab1.test index fd7c1fd41d..e8891a632c 100644 --- a/test/vtab1.test +++ b/test/vtab1.test @@ -1311,25 +1311,27 @@ do_execsql_test 18.1.0 { CREATE VIRTUAL TABLE e6 USING echo(t6); } -foreach {tn sql res filter} { - 1.1 "SELECT a FROM e6 WHERE b>'8James'" {4 2 6 1 5} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b > ?} 8James} - - 1.2 "SELECT a FROM e6 WHERE b>='8' AND b<'9'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ?} 8 9} - - 1.3 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8k 8J%} - - 1.4 "SELECT a FROM e6 WHERE b LIKE '8j%'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8k 8j%} - - 1.5 "SELECT a FROM e6 WHERE b LIKE '8%'" {3 4} - {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8%} -} { - set echo_module {} - do_execsql_test 18.$tn.1 $sql $res - do_test 18.$tn.2 { lrange $::echo_module 2 end } $filter +ifcapable !icu { + foreach {tn sql res filter} { + 1.1 "SELECT a FROM e6 WHERE b>'8James'" {4 2 6 1 5} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b > ?} 8James} + + 1.2 "SELECT a FROM e6 WHERE b>='8' AND b<'9'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ?} 8 9} + + 1.3 "SELECT a FROM e6 WHERE b LIKE '8J%'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8k 8J%} + + 1.4 "SELECT a FROM e6 WHERE b LIKE '8j%'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} 8J 8k 8j%} + + 1.5 "SELECT a FROM e6 WHERE b LIKE '8%'" {3 4} + {xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8%} + } { + set echo_module {} + do_execsql_test 18.$tn.1 $sql $res + do_test 18.$tn.2 { lrange $::echo_module 2 end } $filter + } } do_execsql_test 18.2.0 { PRAGMA case_sensitive_like = ON } @@ -1350,7 +1352,7 @@ foreach {tn sql res filter} { do_execsql_test 18.2.x { PRAGMA case_sensitive_like = OFF } #------------------------------------------------------------------------- -# Test that an existing module may not be overridden. +# Test that it is ok to override and existing module. # do_test 19.1 { sqlite3 db2 test.db @@ -1358,7 +1360,7 @@ do_test 19.1 { } SQLITE_OK do_test 19.2 { register_echo_module [sqlite3_connection_pointer db2] -} SQLITE_MISUSE +} SQLITE_OK do_test 19.3 { db2 close } {} diff --git a/test/vtabH.test b/test/vtabH.test index 78b156cb63..f1a0466554 100644 --- a/test/vtabH.test +++ b/test/vtabH.test @@ -30,36 +30,38 @@ do_execsql_test 1.0 { CREATE VIRTUAL TABLE e6 USING echo(t6); } -foreach {tn sql expect} { - 1 "SELECT * FROM e6 WHERE b LIKE '8abc'" { - xBestIndex - {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} - xFilter - {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} - 8ABC 8abd 8abc +ifcapable !icu { + foreach {tn sql expect} { + 1 "SELECT * FROM e6 WHERE b LIKE '8abc'" { + xBestIndex + {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} + xFilter + {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b like ?} + 8ABC 8abd 8abc + } + + 2 "SELECT * FROM e6 WHERE b GLOB '8abc'" { + xBestIndex + {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b glob ?} + xFilter + {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b glob ?} + 8abc 8abd 8abc + } + 3 "SELECT * FROM e6 WHERE b LIKE '8e/'" { + xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b like ?} + xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8e/ + } + 4 "SELECT * FROM e6 WHERE b GLOB '8e/'" { + xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b glob ?} + xFilter {SELECT rowid, a, b FROM 't6' WHERE b glob ?} 8e/ + } + } { + do_test 1.$tn { + set echo_module {} + execsql $sql + set ::echo_module + } [list {*}$expect] } - - 2 "SELECT * FROM e6 WHERE b GLOB '8abc'" { - xBestIndex - {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b glob ?} - xFilter - {SELECT rowid, a, b FROM 't6' WHERE b >= ? AND b < ? AND b glob ?} - 8abc 8abd 8abc - } - 3 "SELECT * FROM e6 WHERE b LIKE '8e/'" { - xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b like ?} - xFilter {SELECT rowid, a, b FROM 't6' WHERE b like ?} 8e/ - } - 4 "SELECT * FROM e6 WHERE b GLOB '8e/'" { - xBestIndex {SELECT rowid, a, b FROM 't6' WHERE b glob ?} - xFilter {SELECT rowid, a, b FROM 't6' WHERE b glob ?} 8e/ - } -} { - do_test 1.$tn { - set echo_module {} - execsql $sql - set ::echo_module - } [list {*}$expect] } diff --git a/test/where.test b/test/where.test index 5997498839..26bf3a0402 100644 --- a/test/where.test +++ b/test/where.test @@ -1538,4 +1538,37 @@ do_catchsql_test where-25.5 { ON CONFLICT(c) DO UPDATE SET b=NULL } {1 {corrupt database}} +# 2019-08-21 Ticket https://www.sqlite.org/src/info/d9f584e936c7a8d0 +# +db close +sqlite3 db :memory: +do_execsql_test where-26.1 { + CREATE TABLE t0(c0 INTEGER PRIMARY KEY, c1 TEXT); + INSERT INTO t0(c0, c1) VALUES (1, 'a'); + CREATE TABLE t1(c0 INT PRIMARY KEY, c1 TEXT); + INSERT INTO t1(c0, c1) VALUES (1, 'a'); + SELECT * FROM t0 WHERE '-1' BETWEEN 0 AND t0.c0; +} {1 a} +do_execsql_test where-26.2 { + SELECT * FROM t1 WHERE '-1' BETWEEN 0 AND t1.c0; +} {1 a} +do_execsql_test where-26.3 { + SELECT * FROM t0 WHERE '-1'>=0 AND '-1'<=t0.c0; +} {1 a} +do_execsql_test where-26.4 { + SELECT * FROM t1 WHERE '-1'>=0 AND '-1'<=t1.c0; +} {1 a} +do_execsql_test where-26.5 { + SELECT '-1' BETWEEN 0 AND t0.c0 FROM t0; +} {1} +do_execsql_test where-26.6 { + SELECT '-1' BETWEEN 0 AND t1.c0 FROM t1; +} {1} +do_execsql_test where-26.7 { + SELECT '-1'>=0 AND '-1'<=t0.c0 FROM t0; +} {1} +do_execsql_test where-26.8 { + SELECT '-1'>=0 AND '-1'<=t1.c0 FROM t1; +} {1} + finish_test diff --git a/test/whereG.test b/test/whereG.test index d2e6a4ee96..595de116aa 100644 --- a/test/whereG.test +++ b/test/whereG.test @@ -266,5 +266,47 @@ do_execsql_test 7.3 { SELECT coalesce(a,a), x FROM t1, t2 ORDER BY 1, 2; } {1 3 1 4 9 3 9 4} +# 2019-08-22 +# Ticket https://www.sqlite.org/src/info/7e07a3dbf5a8cd26 +# +do_execsql_test 8.1 { + DROP TABLE IF EXISTS t0; + CREATE TABLE t0 (c0); + INSERT INTO t0(c0) VALUES ('a'); + SELECT LIKELY(t0.rowid) <= '0' FROM t0; +} {1} +do_execsql_test 8.2 { + SELECT * FROM t0 WHERE LIKELY(t0.rowid) <= '0'; +} {a} +do_execsql_test 8.3 { + SELECT (t0.rowid) <= '0' FROM t0; +} {0} +do_execsql_test 8.4 { + SELECT * FROM t0 WHERE (t0.rowid) <= '0'; +} {} +do_execsql_test 8.5 { + SELECT unlikely(t0.rowid) <= '0', likelihood(t0.rowid,0.5) <= '0' FROM t0; +} {1 1} +do_execsql_test 8.6 { + SELECT * FROM t0 WHERE unlikely(t0.rowid) <= '0'; +} {a} +do_execsql_test 8.7 { + SELECT * FROM t0 WHERE likelihood(t0.rowid, 0.5) <= '0'; +} {a} +do_execsql_test 8.8 { + SELECT unlikely(t0.rowid <= '0'), + likely(t0.rowid <= '0'), + likelihood(t0.rowid <= '0',0.5) + FROM t0; +} {0 0 0} +do_execsql_test 8.9 { + SELECT * FROM t0 WHERE unlikely(t0.rowid <= '0'); +} {} +do_execsql_test 8.10 { + SELECT * FROM t0 WHERE likelihood(t0.rowid <= '0', 0.5); +} {} + + + finish_test diff --git a/test/window7.test b/test/window7.test index fd04e23c43..441e2b126a 100644 --- a/test/window7.test +++ b/test/window7.test @@ -41,54 +41,146 @@ do_execsql_test 1.0 { do_execsql_test 1.1 { SELECT a, sum(b) FROM t3 GROUP BY a ORDER BY 1; -} {0 550 1 460 2 470 3 480 4 490 5 500 6 510 7 520 8 530 9 540} +} {0 550 1 460 2 470 3 480 4 490 5 500 6 510 7 520 8 530 + 9 540} do_execsql_test 1.2 { SELECT a, sum(b) OVER ( ORDER BY a GROUPS BETWEEN CURRENT ROW AND CURRENT ROW ) FROM t3 ORDER BY 1; -} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540} +} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 + 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 + 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 + 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 + 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 + 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 + 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 + 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 + 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 + 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 + 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 + 9 540} do_execsql_test 1.3 { SELECT a, sum(b) OVER ( ORDER BY a GROUPS BETWEEN 0 PRECEDING AND 0 FOLLOWING ) FROM t3 ORDER BY 1; -} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540} +} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 + 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 + 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 + 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 + 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 + 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 + 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 + 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 + 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 + 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 + 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 + 9 540} do_execsql_test 1.4 { SELECT a, sum(b) OVER ( ORDER BY a GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING ) FROM t3 ORDER BY 1; -} {0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590} +} {0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 + 0 1480 0 1480 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 + 1 1960 1 1960 1 1960 1 1960 2 2450 2 2450 2 2450 2 2450 + 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 3 2400 3 2400 + 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 + 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 + 4 2450 4 2450 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 + 5 2500 5 2500 5 2500 5 2500 6 2550 6 2550 6 2550 6 2550 + 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 7 2600 7 2600 + 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 + 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 + 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 + 9 1590 9 1590 9 1590 9 1590} do_execsql_test 1.5 { SELECT a, sum(b) OVER ( ORDER BY a RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING ) FROM t3 ORDER BY 1; -} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540} +} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 + 0 550 1 460 1 460 1 460 1 460 1 460 1 460 1 460 1 460 + 1 460 1 460 2 470 2 470 2 470 2 470 2 470 2 470 2 470 + 2 470 2 470 2 470 3 480 3 480 3 480 3 480 3 480 3 480 + 3 480 3 480 3 480 3 480 4 490 4 490 4 490 4 490 4 490 + 4 490 4 490 4 490 4 490 4 490 5 500 5 500 5 500 5 500 + 5 500 5 500 5 500 5 500 5 500 5 500 6 510 6 510 6 510 + 6 510 6 510 6 510 6 510 6 510 6 510 6 510 7 520 7 520 + 7 520 7 520 7 520 7 520 7 520 7 520 7 520 7 520 8 530 + 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 8 530 + 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 + 9 540} do_execsql_test 1.6 { SELECT a, sum(b) OVER ( ORDER BY a RANGE BETWEEN 2 PRECEDING AND 2 FOLLOWING ) FROM t3 ORDER BY 1; -} {0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590} +} {0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 0 1480 + 0 1480 0 1480 1 1960 1 1960 1 1960 1 1960 1 1960 1 1960 + 1 1960 1 1960 1 1960 1 1960 2 2450 2 2450 2 2450 2 2450 + 2 2450 2 2450 2 2450 2 2450 2 2450 2 2450 3 2400 3 2400 + 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 3 2400 + 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 4 2450 + 4 2450 4 2450 5 2500 5 2500 5 2500 5 2500 5 2500 5 2500 + 5 2500 5 2500 5 2500 5 2500 6 2550 6 2550 6 2550 6 2550 + 6 2550 6 2550 6 2550 6 2550 6 2550 6 2550 7 2600 7 2600 + 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 7 2600 + 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 + 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 + 9 1590 9 1590 9 1590 9 1590} do_execsql_test 1.7 { SELECT a, sum(b) OVER ( ORDER BY a RANGE BETWEEN 2 PRECEDING AND 1 FOLLOWING ) FROM t3 ORDER BY 1; -} {0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590} +} {0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 + 0 1010 0 1010 1 1480 1 1480 1 1480 1 1480 1 1480 1 1480 + 1 1480 1 1480 1 1480 1 1480 2 1960 2 1960 2 1960 2 1960 + 2 1960 2 1960 2 1960 2 1960 2 1960 2 1960 3 1900 3 1900 + 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 3 1900 + 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 4 1940 + 4 1940 4 1940 5 1980 5 1980 5 1980 5 1980 5 1980 5 1980 + 5 1980 5 1980 5 1980 5 1980 6 2020 6 2020 6 2020 6 2020 + 6 2020 6 2020 6 2020 6 2020 6 2020 6 2020 7 2060 7 2060 + 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 7 2060 + 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 8 2100 + 8 2100 8 2100 9 1590 9 1590 9 1590 9 1590 9 1590 9 1590 + 9 1590 9 1590 9 1590 9 1590} do_execsql_test 1.8.1 { SELECT a, sum(b) OVER ( ORDER BY a RANGE BETWEEN 0 PRECEDING AND 1 FOLLOWING ) FROM t3 ORDER BY 1; -} {0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 1 930 1 930 1 930 1 930 1 930 1 930 1 930 1 930 1 930 1 930 2 950 2 950 2 950 2 950 2 950 2 950 2 950 2 950 2 950 2 950 3 970 3 970 3 970 3 970 3 970 3 970 3 970 3 970 3 970 3 970 4 990 4 990 4 990 4 990 4 990 4 990 4 990 4 990 4 990 4 990 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 8 1070 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540 9 540} +} {0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 0 1010 + 0 1010 0 1010 1 930 1 930 1 930 1 930 1 930 1 930 1 930 + 1 930 1 930 1 930 2 950 2 950 2 950 2 950 2 950 2 950 + 2 950 2 950 2 950 2 950 3 970 3 970 3 970 3 970 3 970 + 3 970 3 970 3 970 3 970 3 970 4 990 4 990 4 990 4 990 + 4 990 4 990 4 990 4 990 4 990 4 990 5 1010 5 1010 5 1010 + 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 5 1010 6 1030 + 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 6 1030 + 6 1030 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 7 1050 + 7 1050 7 1050 7 1050 8 1070 8 1070 8 1070 8 1070 8 1070 + 8 1070 8 1070 8 1070 8 1070 8 1070 9 540 9 540 9 540 9 540 + 9 540 9 540 9 540 9 540 9 540 9 540} do_execsql_test 1.8.2 { SELECT a, sum(b) OVER ( ORDER BY a DESC RANGE BETWEEN 0 PRECEDING AND 1 FOLLOWING ) FROM t3 ORDER BY 1; -} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 2 930 2 930 2 930 2 930 2 930 2 930 2 930 2 930 2 930 2 930 3 950 3 950 3 950 3 950 3 950 3 950 3 950 3 950 3 950 3 950 4 970 4 970 4 970 4 970 4 970 4 970 4 970 4 970 4 970 4 970 5 990 5 990 5 990 5 990 5 990 5 990 5 990 5 990 5 990 5 990 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070} +} {0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 0 550 + 0 550 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 1 1010 + 1 1010 1 1010 1 1010 2 930 2 930 2 930 2 930 2 930 2 930 + 2 930 2 930 2 930 2 930 3 950 3 950 3 950 3 950 3 950 + 3 950 3 950 3 950 3 950 3 950 4 970 4 970 4 970 4 970 + 4 970 4 970 4 970 4 970 4 970 4 970 5 990 5 990 5 990 + 5 990 5 990 5 990 5 990 5 990 5 990 5 990 6 1010 6 1010 + 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 6 1010 + 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 7 1030 + 7 1030 7 1030 8 1050 8 1050 8 1050 8 1050 8 1050 8 1050 + 8 1050 8 1050 8 1050 8 1050 9 1070 9 1070 9 1070 9 1070 + 9 1070 9 1070 9 1070 9 1070 9 1070 9 1070} finish_test diff --git a/test/window8.tcl b/test/window8.tcl index df1fd78ab7..a8333f1907 100644 --- a/test/window8.tcl +++ b/test/window8.tcl @@ -197,30 +197,67 @@ execsql_test 4.2.1 { ORDER BY a RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING ) FROM t1 ORDER BY 1 NULLS FIRST; } - execsql_test 4.2.2 { + SELECT sum(b) OVER ( + ORDER BY a RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} + +execsql_test 4.2.3 { SELECT sum(b) OVER ( ORDER BY a DESC RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING ) FROM t1 ORDER BY 1 NULLS FIRST; } +execsql_test 4.2.4 { + SELECT sum(b) OVER ( + ORDER BY a DESC RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} execsql_test 4.3.1 { SELECT sum(b) OVER ( ORDER BY a NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING ) FROM t1 ORDER BY 1 NULLS FIRST; } +execsql_test 4.3.2 { + SELECT sum(b) OVER ( + ORDER BY a NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} execsql_test 4.4.1 { SELECT sum(b) OVER ( ORDER BY a NULLS FIRST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) FROM t1 ORDER BY 1 NULLS FIRST; } - execsql_test 4.4.2 { + SELECT sum(b) OVER ( + ORDER BY a NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} + +execsql_test 4.4.3 { SELECT sum(b) OVER ( ORDER BY a DESC NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) FROM t1 ORDER BY 1 NULLS FIRST; } +execsql_test 4.4.4 { + SELECT sum(b) OVER ( + ORDER BY a DESC NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} + +execsql_test 4.5.1 { + SELECT sum(b) OVER ( + ORDER BY a ASC NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} +execsql_test 4.5.2 { + SELECT sum(b) OVER ( + ORDER BY a DESC NULLS FIRST RANGE + BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} ========== @@ -248,6 +285,17 @@ foreach {tn ex} { 6 { ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING } 7 { ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING } + + 8 { RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING } + 9 { ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING } + 10 { PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING } + 11 { ORDER BY a NULLS LAST GROUPS 6 PRECEDING } + 12 { ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING } + 13 { ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING } + 14 { ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING } } { execsql_test 5.$tn.$tn2.1 " SELECT max(c) OVER win, @@ -293,6 +341,84 @@ execsql_test 6.2 { FROM t2 } +========== + +execsql_test 7.0 { + DROP TABLE IF EXISTS t2; + CREATE TABLE t2(a INTEGER, b INTEGER); + + INSERT INTO t2 VALUES(1, 65); + INSERT INTO t2 VALUES(2, NULL); + INSERT INTO t2 VALUES(3, NULL); + INSERT INTO t2 VALUES(4, NULL); + INSERT INTO t2 VALUES(5, 66); + INSERT INTO t2 VALUES(6, 67); +} + +foreach {tn f ex} { + 1 sum "" + 2 min "" + 3 sum "EXCLUDE CURRENT ROW" + 4 max "EXCLUDE CURRENT ROW" +} { +execsql_test 7.$tn.1 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING + ); +" +execsql_test 7.$tn.2 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +" +execsql_test 7.$tn.3 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +" +execsql_test 7.$tn.4 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +" +execsql_test 7.$tn.5 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +" + +execsql_test 7.$tn.6 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING + ); +" +execsql_test 7.$tn.7 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +" +execsql_test 7.$tn.8 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING + ); +" +execsql_test 7.$tn.9 " + SELECT $f (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +" +} + + finish_test diff --git a/test/window8.test b/test/window8.test index 829bd0b252..ed720ebd41 100644 --- a/test/window8.test +++ b/test/window8.test @@ -3522,33 +3522,76 @@ do_execsql_test 4.1.2 { do_execsql_test 4.2.1 { SELECT sum(b) OVER ( ORDER BY a RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING - ) FROM t1 ORDER BY 1 ; + ) FROM t1 ORDER BY 1 NULLS FIRST; } {{} {} 6 6 6} do_execsql_test 4.2.2 { + SELECT sum(b) OVER ( + ORDER BY a RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} {6 6 6 {} {}} + +do_execsql_test 4.2.3 { SELECT sum(b) OVER ( ORDER BY a DESC RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING - ) FROM t1 ORDER BY 1 ; + ) FROM t1 ORDER BY 1 NULLS FIRST; } {{} {} 6 6 6} +do_execsql_test 4.2.4 { + SELECT sum(b) OVER ( + ORDER BY a DESC RANGE BETWEEN 5 FOLLOWING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} {6 6 6 {} {}} + do_execsql_test 4.3.1 { SELECT sum(b) OVER ( - ORDER BY a RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING - ) FROM t1 ORDER BY 1 ; + ORDER BY a NULLS FIRST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS FIRST; } {6 6 6 15 15} +do_execsql_test 4.3.2 { + SELECT sum(b) OVER ( + ORDER BY a NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} {9 9 15 15 15} + do_execsql_test 4.4.1 { SELECT sum(b) OVER ( - ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING - ) FROM t1 ORDER BY 1 ; + ORDER BY a NULLS FIRST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS FIRST; } {3 6 9 9 12} do_execsql_test 4.4.2 { SELECT sum(b) OVER ( - ORDER BY a DESC ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING - ) FROM t1 ORDER BY 1 ; + ORDER BY a NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; } {5 6 8 9 10} +do_execsql_test 4.4.3 { + SELECT sum(b) OVER ( + ORDER BY a DESC NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS FIRST; +} {5 6 8 9 10} + +do_execsql_test 4.4.4 { + SELECT sum(b) OVER ( + ORDER BY a DESC NULLS LAST ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} {5 6 8 9 10} + +do_execsql_test 4.5.1 { + SELECT sum(b) OVER ( + ORDER BY a ASC NULLS LAST RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} {9 9 15 15 15} + +do_execsql_test 4.5.2 { + SELECT sum(b) OVER ( + ORDER BY a DESC NULLS FIRST RANGE + BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING + ) FROM t1 ORDER BY 1 NULLS LAST; +} {6 6 6 15 15} + #========================================================================== do_execsql_test 5.0 { @@ -3564,7 +3607,7 @@ do_execsql_test 5.1.1.1 { count(a) OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 @@ -3587,7 +3630,7 @@ do_execsql_test 5.1.1.2 { dense_rank() OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 @@ -3609,9 +3652,9 @@ do_execsql_test 5.1.2.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 16 899 113 16 899 113 16 899 113 16 899 113 16 899 113 16 899 113 16 979 102 44 979 102 44 @@ -3633,9 +3676,9 @@ do_execsql_test 5.1.2.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {2947 81 11 2947 81 11 2947 81 11 2947 81 11 2947 81 11 2947 81 11 2947 81 11 2947 81 11 2947 81 11 5287 74 10 5287 74 10 5287 74 10 5287 74 10 5287 74 10 5287 74 10 5287 74 10 8400 65 9 8400 65 9 @@ -3659,7 +3702,7 @@ do_execsql_test 5.1.3.1 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {777 113 5 777 113 5 777 113 5 777 113 5 777 113 5 805 250 7 805 250 7 805 250 7 805 250 7 805 250 7 805 250 7 805 250 7 822 158 6 822 158 6 822 158 6 822 158 6 822 158 6 822 158 6 @@ -3683,7 +3726,7 @@ do_execsql_test 5.1.3.2 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1366 1 1 1366 1 1 @@ -3703,8 +3746,8 @@ do_execsql_test 5.1.4.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 934 158 8 934 158 8 934 158 8 934 158 8 934 158 8 934 158 8 934 158 8 934 158 8 934 158 21 934 158 21 934 158 21 934 158 21 @@ -3726,8 +3769,8 @@ do_execsql_test 5.1.4.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {2050 1 1 2050 1 1 2050 1 1 2050 1 1 2050 1 1 2050 1 1 4359 7 2 4359 7 2 4359 7 2 4359 7 2 4359 7 2 4359 7 2 4359 7 2 4359 7 2 7840 15 3 7840 15 3 7840 15 3 7840 15 3 7840 15 3 7840 15 3 @@ -3750,8 +3793,8 @@ do_execsql_test 5.1.5.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {102 102 1 113 113 2 113 113 2 133 133 1 148 148 1 160 158 2 160 158 2 160 158 2 208 208 1 224 223 2 224 223 2 239 234 3 239 234 3 239 234 3 252 247 3 257 247 5 257 247 5 257 250 4 @@ -3773,8 +3816,8 @@ do_execsql_test 5.1.5.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 25 23 {} 34 29 {} 36 31 {} 38 33 {} 38 33 {} 40 34 {} 41 35 {} 43 37 {} 43 37 {} 50 42 {} 60 51 {} 61 52 {} 64 55 {} 64 55 {} 67 57 {} 68 58 @@ -3795,8 +3838,8 @@ do_execsql_test 5.1.6.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {102 102 1 113 113 2 113 113 2 133 133 1 148 148 1 158 158 1 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 @@ -3818,8 +3861,8 @@ do_execsql_test 5.1.6.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 11 9 {} 12 10 {} 13 11 {} 16 14 {} 17 15 {} 18 16 {} 22 20 {} 24 22 {} 25 23 {} 26 24 {} 31 27 {} 34 29 {} 36 31 {} 38 33 {} 38 33 {} 40 34 @@ -3840,9 +3883,9 @@ do_execsql_test 5.1.7.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 113 81 979 113 82 979 133 80 979 148 79 979 158 77 979 158 78 979 160 77 979 208 76 979 223 75 979 224 74 979 234 73 @@ -3864,9 +3907,335 @@ do_execsql_test 5.1.7.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {3830 89 89 4741 88 88 5640 84 84 5640 85 85 5640 86 86 5640 87 87 + 6485 81 81 6485 82 82 6485 83 83 7324 80 80 8163 78 78 8163 79 79 + 8968 73 73 8968 74 74 8968 75 75 8968 76 76 8968 77 77 9745 69 69 + 9745 70 70 9745 71 71 9745 72 72 10504 65 65 10504 66 66 + 10504 67 67 10504 68 68 11215 64 64 11920 63 63 12603 62 62 + 13274 60 60 13274 61 61 13941 59 59 14608 55 55 14608 56 56 + 14608 57 57 14608 58 58 15241 54 54 15870 53 53 16499 52 52 + 17126 49 49 17126 50 50 17126 51 51 17733 44 44 17733 45 45 + 17733 46 46 17733 47 47 17733 48 48 18176 42 42 18176 43 43 + 18597 40 40 18597 41 41 18996 39 39 19395 37 37 19395 38 38 + 19788 36 36 20181 35 35 20536 34 34 20891 30 30 20891 31 31 + 20891 32 32 20891 33 33 21226 28 28 21226 29 29 21535 27 27 + 21830 26 26 22087 22 22 22087 23 23 22087 24 24 22087 25 25 + 22334 21 21 22573 17 17 22573 18 18 22573 19 19 22573 20 20 + 22796 11 11 22796 12 12 22796 13 13 22796 14 14 22796 15 15 + 22796 16 16 22929 10 10 23042 9 9 23155 1 1 23155 2 2 23155 3 3 + 23155 4 4 23155 5 5 23155 6 6 23155 7 7 23155 8 8} + +do_execsql_test 5.1.8.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83} + +do_execsql_test 5.1.8.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1} + +do_execsql_test 5.1.9.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 + 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 + 899 113 9 899 113 9 899 113 9 899 113 16 899 113 16 899 113 16 + 899 113 16 899 113 16 899 113 16 899 113 16 979 102 44 979 102 44 + 979 102 44 979 102 44 979 102 44 979 102 44 979 102 44 979 102 44 + 979 102 44 979 102 44 979 102 44 979 102 49 979 102 49 979 102 49 + 979 102 49 979 102 49 979 102 56 979 102 56 979 102 56 979 102 56 + 979 102 56 979 102 56 979 102 56 979 102 62 979 102 62 979 102 62 + 979 102 62 979 102 62 979 102 62 979 102 75 979 102 75 979 102 75 + 979 102 75 979 102 75 979 102 75 979 102 75 979 102 75 979 102 75 + 979 102 75 979 102 75 979 102 75 979 102 75 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 113 25 979 113 25 979 113 25 979 113 25 979 113 25 979 113 25 + 979 113 25 979 113 25 979 113 25 979 113 33 979 113 33 979 113 33 + 979 113 33 979 113 33 979 113 33 979 113 33 979 113 33} + +do_execsql_test 5.1.9.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {2050 84 11 2050 84 11 2050 84 11 2050 84 11 2050 84 11 2050 84 11 + 4997 75 10 4997 75 10 4997 75 10 4997 75 10 4997 75 10 4997 75 10 + 4997 75 10 4997 75 10 4997 75 10 7337 68 9 7337 68 9 7337 68 9 + 7337 68 9 7337 68 9 7337 68 9 7337 68 9 10450 59 8 10450 59 8 + 10450 59 8 10450 59 8 10450 59 8 10450 59 8 10450 59 8 10450 59 8 + 10450 59 8 11714 51 7 11714 51 7 11714 51 7 11714 51 7 11714 51 7 + 11714 51 7 11714 51 7 11714 51 7 12676 40 6 12676 40 6 12676 40 6 + 12676 40 6 12676 40 6 12676 40 6 12676 40 6 12676 40 6 12676 40 6 + 12676 40 6 12676 40 6 14195 35 5 14195 35 5 14195 35 5 14195 35 5 + 14195 35 5 15999 28 4 15999 28 4 15999 28 4 15999 28 4 15999 28 4 + 15999 28 4 15999 28 4 17365 22 3 17365 22 3 17365 22 3 17365 22 3 + 17365 22 3 17365 22 3 20846 9 2 20846 9 2 20846 9 2 20846 9 2 + 20846 9 2 20846 9 2 20846 9 2 20846 9 2 20846 9 2 20846 9 2 + 20846 9 2 20846 9 2 20846 9 2 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1} + +do_execsql_test 5.1.10.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {777 113 5 777 113 5 777 113 5 777 113 5 777 113 5 805 250 7 + 805 250 7 805 250 7 805 250 7 805 250 7 805 250 7 805 250 7 + 822 158 6 822 158 6 822 158 6 822 158 6 822 158 6 822 158 6 + 840 247 13 840 247 13 840 247 13 840 247 13 840 247 13 840 247 13 + 840 247 13 840 247 13 840 247 13 840 247 13 840 247 13 840 247 13 + 840 247 13 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 + 870 158 0 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 + 899 113 9 899 113 9 899 113 9 899 113 9 934 223 8 934 223 8 + 934 223 8 934 223 8 934 223 8 934 223 8 934 223 8 934 223 8 + 938 102 11 938 102 11 938 102 11 938 102 11 938 102 11 938 102 11 + 938 102 11 938 102 11 938 102 11 938 102 11 938 102 11 938 148 8 + 938 148 8 938 148 8 938 148 8 938 148 8 938 148 8 938 148 8 + 938 148 8 959 224 7 959 224 7 959 224 7 959 224 7 959 224 7 + 959 224 7 959 224 7 979 133 9 979 133 9 979 133 9 979 133 9 + 979 133 9 979 133 9 979 133 9 979 133 9 979 133 9} + +do_execsql_test 5.1.10.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 + 962 1 1 962 1 1 962 1 1 962 1 1 1264 1 1 1264 1 1 1264 1 1 + 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1366 1 1 1366 1 1 + 1366 1 1 1366 1 1 1366 1 1 1366 1 1 1519 1 1 1519 1 1 1519 1 1 + 1519 1 1 1519 1 1 1804 1 1 1804 1 1 1804 1 1 1804 1 1 1804 1 1 + 1804 1 1 1804 1 1 2050 1 1 2050 1 1 2050 1 1 2050 1 1 2050 1 1 + 2050 1 1 2309 1 1 2309 1 1 2309 1 1 2309 1 1 2309 1 1 2309 1 1 + 2309 1 1 2309 1 1 2340 1 1 2340 1 1 2340 1 1 2340 1 1 2340 1 1 + 2340 1 1 2340 1 1 2947 1 1 2947 1 1 2947 1 1 2947 1 1 2947 1 1 + 2947 1 1 2947 1 1 2947 1 1 2947 1 1 3113 1 1 3113 1 1 3113 1 1 + 3113 1 1 3113 1 1 3113 1 1 3113 1 1 3113 1 1 3113 1 1 3481 1 1 + 3481 1 1 3481 1 1 3481 1 1 3481 1 1 3481 1 1 3481 1 1 3481 1 1 + 3481 1 1 3481 1 1 3481 1 1 3481 1 1 3481 1 1} + +do_execsql_test 5.1.11.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {934 158 27 934 158 27 934 158 27 934 158 27 934 158 27 934 158 27 + 934 223 8 934 223 8 934 223 8 934 223 8 934 223 8 934 223 8 + 934 223 8 934 223 8 934 223 21 934 223 21 934 223 21 934 223 21 + 934 223 21 934 223 21 934 223 21 934 223 21 934 223 21 934 223 21 + 934 223 21 934 223 21 934 223 21 959 102 50 959 102 50 959 102 50 + 959 102 50 959 102 50 959 102 50 959 102 50 959 102 50 959 102 50 + 959 102 50 959 102 50 959 102 58 959 102 58 959 102 58 959 102 58 + 959 102 58 959 102 58 959 102 58 959 102 58 959 113 39 959 113 39 + 959 113 39 959 113 39 959 113 39 959 158 34 959 158 34 959 158 34 + 959 158 34 959 158 34 959 158 34 959 158 34 979 102 49 979 102 49 + 979 102 49 979 102 49 979 102 49 979 102 49 979 102 53 979 102 53 + 979 102 53 979 102 53 979 102 53 979 102 53 979 102 53 979 102 56 + 979 102 56 979 102 56 979 102 56 979 102 56 979 102 56 979 102 56 + 979 102 56 979 102 56 979 102 59 979 102 59 979 102 59 979 102 59 + 979 102 59 979 102 59 979 102 59 979 102 59 979 102 59} + +do_execsql_test 5.1.11.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {2309 1 1 2309 1 1 2309 1 1 2309 1 1 2309 1 1 2309 1 1 2309 1 1 + 2309 1 1 5790 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 + 5790 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 + 7156 22 3 7156 22 3 7156 22 3 7156 22 3 7156 22 3 7156 22 3 + 8960 28 4 8960 28 4 8960 28 4 8960 28 4 8960 28 4 8960 28 4 + 8960 28 4 10479 35 5 10479 35 5 10479 35 5 10479 35 5 10479 35 5 + 11441 40 6 11441 40 6 11441 40 6 11441 40 6 11441 40 6 11441 40 6 + 11441 40 6 11441 40 6 11441 40 6 11441 40 6 11441 40 6 12368 68 9 + 12368 68 9 12368 68 9 12368 68 9 12368 68 9 12368 68 9 12368 68 9 + 12705 51 7 12705 51 7 12705 51 7 12705 51 7 12705 51 7 12705 51 7 + 12705 51 7 12705 51 7 13509 59 8 13509 59 8 13509 59 8 13509 59 8 + 13509 59 8 13509 59 8 13509 59 8 13509 59 8 13509 59 8 + 13949 75 10 13949 75 10 13949 75 10 13949 75 10 13949 75 10 + 13949 75 10 13949 75 10 13949 75 10 13949 75 10 14195 84 11 + 14195 84 11 14195 84 11 14195 84 11 14195 84 11 14195 84 11} + +do_execsql_test 5.1.12.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {102 102 1 113 113 2 113 113 2 133 133 1 148 148 1 160 158 2 + 160 158 2 160 158 2 208 208 1 224 223 2 224 223 2 239 234 3 + 239 234 3 239 234 3 252 247 3 257 247 5 257 247 5 257 250 4 + 257 252 3 295 295 1 309 309 1 336 330 3 336 330 3 336 330 3 + 346 346 1 355 354 2 355 354 2 355 354 2 399 393 4 399 393 4 + 399 393 4 399 393 4 399 393 4 412 412 1 421 421 1 430 430 1 + 443 443 1 480 480 2 480 480 2 574 572 2 574 572 2 607 607 1 + 618 618 2 618 618 2 634 627 4 634 627 4 634 627 4 634 627 4 + 634 629 3 652 652 1 667 660 2 671 667 3 671 667 3 671 667 3 + 671 667 3 683 683 1 711 705 2 716 705 3 716 711 2 730 726 2 + 730 726 2 762 759 2 768 759 4 768 762 3 768 762 3 777 777 1 + 792 786 3 794 786 4 794 786 4 794 790 3 805 805 1 822 822 1 + 845 839 5 845 839 5 845 839 5 845 839 5 845 839 5 870 870 2 + 870 870 2 870 870 2 899 899 1 911 911 1 934 929 2 938 929 4 + 938 934 3 938 934 3 963 959 2 963 959 2 979 979 1} + +do_execsql_test 5.1.12.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 25 23 {} 34 29 + {} 36 31 {} 38 33 {} 38 33 {} 40 34 {} 41 35 {} 43 37 {} 43 37 + {} 50 42 {} 60 51 {} 61 52 {} 64 55 {} 64 55 {} 67 57 {} 68 58 + {} 69 59 {} 70 60 {} 72 62 {} 78 67 {} 78 67 {} 78 67 {} 85 72 + {} 85 72 133 4 3 223 10 8 223 11 9 226 2 2 226 2 2 239 12 10 + 239 13 11 239 14 12 247 15 13 257 18 16 257 19 17 295 20 18 + 309 21 19 335 22 20 335 23 21 335 24 22 421 35 30 443 37 32 + 504 16 14 504 17 15 607 42 36 683 56 47 710 26 24 710 27 25 + 710 27 25 711 59 50 759 62 53 759 63 54 777 66 56 805 71 61 + 899 81 68 911 82 69 929 83 70 929 84 71 979 89 75 1334 51 43 + 1416 57 48 1416 58 49 1584 29 26 1584 29 26 1584 31 27 1584 32 28 + 1584 32 28 1891 49 41 1922 87 73 1922 88 74 2005 52 44 2005 52 44 + 2005 54 45 2005 55 46 2518 45 38 2518 46 39 2518 46 39 2518 48 40 + 2523 73 63 2523 73 63 2523 75 64 2523 76 65 2523 77 66} + +do_execsql_test 5.1.13.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {102 102 1 113 113 2 113 113 2 133 133 1 148 148 1 158 158 1 + 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 + 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 + 257 257 1 295 295 1 309 309 1 330 330 1 335 335 1 336 336 1 + 346 346 1 354 354 1 355 355 1 355 355 1 393 393 2 393 393 2 + 398 398 1 399 399 1 399 399 1 412 412 1 421 421 1 430 430 1 + 443 443 1 480 480 2 480 480 2 572 572 1 574 574 1 607 607 1 + 618 618 2 618 618 2 627 627 1 629 629 1 629 629 1 633 633 1 + 634 634 1 652 652 1 660 660 1 667 667 1 667 667 1 670 670 1 + 671 671 1 683 683 1 705 705 1 711 711 1 716 716 1 726 726 1 + 730 730 1 759 759 1 762 762 1 768 768 2 768 768 2 777 777 1 + 786 786 1 790 790 1 792 792 1 794 794 1 805 805 1 822 822 1 + 839 839 2 839 839 2 840 840 1 844 844 1 845 845 1 870 870 2 + 870 870 2 870 870 2 899 899 1 911 911 1 929 929 1 934 934 1 + 938 938 2 938 938 2 959 959 1 963 963 1 979 979 1} + +do_execsql_test 5.1.13.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 11 9 {} 12 10 + {} 13 11 {} 16 14 {} 17 15 {} 18 16 {} 22 20 {} 24 22 {} 25 23 + {} 26 24 {} 31 27 {} 34 29 {} 36 31 {} 38 33 {} 38 33 {} 40 34 + {} 41 35 {} 43 37 {} 43 37 {} 49 41 {} 50 42 {} 51 43 {} 54 45 + {} 59 50 {} 60 51 {} 61 52 {} 63 54 {} 64 55 {} 64 55 {} 67 57 + {} 68 58 {} 69 59 {} 70 60 {} 72 62 {} 75 64 {} 76 65 {} 78 67 + {} 78 67 {} 78 67 {} 84 71 {} 85 72 {} 85 72 133 4 3 223 10 8 + 226 2 2 226 2 2 239 14 12 247 15 13 257 19 17 295 20 18 + 309 21 19 335 23 21 421 35 30 443 37 32 607 42 36 627 45 38 + 633 48 40 671 55 46 683 56 47 705 57 48 710 27 25 710 27 25 + 711 58 49 759 62 53 777 66 56 786 29 26 786 29 26 798 32 28 + 798 32 28 805 71 61 845 77 66 899 81 68 911 82 69 929 83 70 + 959 87 73 963 88 74 979 89 75 1258 46 39 1258 46 39 1334 52 44 + 1334 52 44 1678 73 63 1678 73 63} + +do_execsql_test 5.1.14.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 113 81 979 113 82 979 133 80 979 148 79 979 158 77 + 979 158 78 979 160 77 979 208 76 979 223 75 979 224 74 979 234 73 + 979 238 72 979 239 71 979 247 70 979 250 69 979 252 68 979 256 67 + 979 257 66 979 295 65 979 309 64 979 330 63 979 335 62 979 336 61 + 979 346 60 979 354 59 979 355 57 979 355 58 979 393 56 979 393 57 + 979 398 55 979 399 53 979 399 54 979 412 53 979 421 52 979 430 51 + 979 443 50 979 480 48 979 480 49 979 572 47 979 574 46 979 607 45 + 979 618 43 979 618 44 979 627 42 979 629 40 979 629 41 979 633 40 + 979 634 39 979 652 38 979 660 37 979 667 35 979 667 36 979 670 35 + 979 671 34 979 683 33 979 705 32 979 711 31 979 716 30 979 726 29 + 979 730 28 979 759 27 979 762 26 979 768 24 979 768 25 979 777 23 + 979 786 22 979 790 21 979 792 20 979 794 19 979 805 18 979 822 17 + 979 839 15 979 839 16 979 840 14 979 844 13 979 845 12 979 870 9 + 979 870 10 979 870 11 979 899 9 979 911 8 979 929 7} + +do_execsql_test 5.1.14.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE NO OTHERS ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {3830 89 89 4741 88 88 5640 84 84 5640 85 85 5640 86 86 5640 87 87 6485 81 81 6485 82 82 6485 83 83 7324 80 80 8163 78 78 8163 79 79 8968 73 73 8968 74 74 8968 75 75 8968 76 76 8968 77 77 9745 69 69 @@ -3891,7 +4260,7 @@ do_execsql_test 5.2.1.1 { count(a) OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {963 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 @@ -3914,7 +4283,7 @@ do_execsql_test 5.2.1.2 { dense_rank() OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {22176 1 1 22192 1 1 22196 1 1 22226 1 1 22244 1 1 22256 1 1 22310 1 1 22316 1 1 22316 1 1 22350 1 1 22378 1 1 22396 1 1 22444 1 1 22450 1 1 22472 1 1 22484 1 1 22488 1 1 22488 1 1 @@ -3936,9 +4305,9 @@ do_execsql_test 5.2.2.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {839 113 8 899 113 8 899 113 8 899 113 8 899 113 8 899 113 8 899 113 8 899 113 8 899 113 15 899 113 15 899 113 15 899 113 15 899 113 15 899 113 15 899 113 15 899 234 8 963 113 24 979 102 43 @@ -3960,9 +4329,9 @@ do_execsql_test 5.2.2.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {2048 81 11 2108 81 11 2108 81 11 2690 81 11 2834 81 11 2947 81 11 2947 81 11 2947 81 11 2947 81 11 4482 74 10 4616 74 10 4844 74 10 4866 74 10 5287 74 10 5287 74 10 5287 74 10 7421 65 9 7437 65 9 @@ -3986,7 +4355,7 @@ do_execsql_test 5.2.3.1 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {667 158 0 671 250 6 759 158 5 768 113 4 777 113 4 777 113 4 777 113 4 777 252 4 792 247 12 805 250 6 805 250 6 805 250 6 805 250 6 805 250 6 805 398 6 822 158 5 822 158 5 822 158 5 @@ -4010,7 +4379,7 @@ do_execsql_test 5.2.3.2 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {295 1 1 335 1 1 607 1 1 667 1 1 742 1 1 759 1 1 845 1 1 890 1 1 929 1 1 959 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 1264 1 1 1264 1 1 @@ -4030,8 +4399,8 @@ do_execsql_test 5.2.4.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {667 158 0 870 158 0 870 158 0 870 158 0 870 158 0 870 355 0 911 158 7 934 158 7 934 158 7 934 158 7 934 158 7 934 158 7 934 158 7 934 158 7 934 158 20 934 158 20 934 158 20 934 158 20 @@ -4053,8 +4422,8 @@ do_execsql_test 5.2.4.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {1383 1 1 1421 1 1 1651 1 1 1695 1 1 2050 1 1 2050 1 1 3448 7 2 3732 7 2 4050 7 2 4120 7 2 4136 7 2 4359 7 2 4359 7 2 4359 7 2 7129 15 3 7135 15 3 7207 15 3 7441 15 3 7447 15 3 7447 15 3 @@ -4077,8 +4446,8 @@ do_execsql_test 5.2.5.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 113 113 1 @@ -4100,8 +4469,8 @@ do_execsql_test 5.2.5.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 10 8 {} 14 12 {} 15 13 {} 19 17 {} 20 18 {} 21 19 {} 23 21 {} 25 23 {} 34 29 {} 35 30 {} 36 31 {} 37 32 {} 38 33 {} 38 33 {} 40 34 @@ -4122,8 +4491,8 @@ do_execsql_test 5.2.6.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 @@ -4144,8 +4513,8 @@ do_execsql_test 5.2.6.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 10 8 {} 11 9 {} 12 10 {} 13 11 {} 14 12 {} 15 13 {} 16 14 {} 17 15 {} 18 16 {} 19 17 {} 20 18 {} 21 19 {} 22 20 {} 23 21 {} 24 22 @@ -4165,9 +4534,9 @@ do_execsql_test 5.2.7.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {963 929 6 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 83 979 113 80 979 113 81 979 113 82 979 133 79 979 148 78 979 158 76 979 158 77 979 160 76 979 208 75 979 223 74 979 224 73 @@ -4189,9 +4558,334 @@ do_execsql_test 5.2.7.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {2851 89 89 3778 88 88 4681 87 87 5556 83 83 5574 82 82 5586 81 81 + 5640 84 84 5640 85 85 5640 86 86 7324 80 80 8123 77 77 8129 73 73 + 8129 74 74 8163 78 78 8163 79 79 8940 71 71 8968 75 75 8968 76 76 + 9727 66 66 9745 69 69 9745 70 70 9745 72 72 10504 65 65 + 10504 67 67 10504 68 68 11215 64 64 11844 62 62 11920 63 63 + 13274 60 60 13274 61 61 13897 58 58 13903 57 57 13925 56 56 + 13937 55 55 13941 59 59 15203 53 53 15241 54 54 15832 52 52 + 17100 48 48 17104 46 46 17104 47 47 17106 45 45 17126 49 49 + 17126 50 50 17126 51 51 17569 42 42 17733 44 44 18176 43 43 + 18597 40 40 18597 41 41 18952 37 37 18996 39 39 19395 38 38 + 19760 35 35 19788 36 36 20492 32 32 20492 33 33 20498 30 30 + 20536 34 34 20833 29 29 20871 28 28 20891 31 31 21180 27 27 + 21752 23 23 21830 26 26 22025 21 21 22087 22 22 22087 24 24 + 22087 25 25 22278 20 20 22316 19 19 22549 15 15 22557 14 14 + 22573 17 17 22573 18 18 22706 10 10 22796 11 11 22796 12 12 + 22796 13 13 22796 16 16 23022 4 4 23042 2 2 23042 3 3 23042 9 9 + 23155 1 1 23155 5 5 23155 6 6 23155 7 7 23155 8 8} + +do_execsql_test 5.2.8.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {963 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 83 979 102 83 + 979 102 83 979 102 83 979 102 83 979 102 83 979 113 82} + +do_execsql_test 5.2.8.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {22176 1 1 22192 1 1 22196 1 1 22226 1 1 22244 1 1 22256 1 1 + 22310 1 1 22316 1 1 22316 1 1 22350 1 1 22378 1 1 22396 1 1 + 22444 1 1 22450 1 1 22472 1 1 22484 1 1 22488 1 1 22488 1 1 + 22522 1 1 22526 1 1 22526 1 1 22528 1 1 22548 1 1 22712 1 1 + 22734 1 1 22756 1 1 22756 1 1 22762 1 1 22762 1 1 22800 1 1 + 22800 1 1 22820 1 1 22846 1 1 22860 1 1 22898 1 1 22908 1 1 + 22916 1 1 22932 1 1 23022 1 1 23042 1 1 23042 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1 + 23155 1 1 23155 1 1 23155 1 1 23155 1 1 23155 1 1} + +do_execsql_test 5.2.9.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {667 158 0 870 113 8 870 158 0 870 158 0 870 158 0 870 158 0 + 870 355 0 899 113 8 899 113 8 899 113 8 899 113 8 899 113 8 + 899 113 8 899 113 8 899 113 15 899 113 15 899 113 15 899 113 15 + 899 113 15 899 113 15 899 113 15 899 158 8 963 113 24 979 102 43 + 979 102 43 979 102 43 979 102 43 979 102 43 979 102 43 979 102 43 + 979 102 43 979 102 43 979 102 43 979 102 48 979 102 48 979 102 48 + 979 102 48 979 102 48 979 102 55 979 102 55 979 102 55 979 102 55 + 979 102 55 979 102 55 979 102 55 979 102 61 979 102 61 979 102 61 + 979 102 61 979 102 61 979 102 61 979 102 74 979 102 74 979 102 74 + 979 102 74 979 102 74 979 102 74 979 102 74 979 102 74 979 102 74 + 979 102 74 979 102 74 979 102 74 979 102 74 979 102 82 979 102 82 + 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 113 24 979 113 24 979 113 24 979 113 24 979 113 24 979 113 24 + 979 113 24 979 113 24 979 113 32 979 113 32 979 113 32 979 113 32 + 979 113 32 979 113 32 979 113 32 979 113 32 979 113 43} + +do_execsql_test 5.2.9.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {1383 84 11 1421 84 11 1651 84 11 1695 84 11 2050 84 11 2050 84 11 + 4098 75 10 4158 75 10 4158 75 10 4740 75 10 4884 75 10 4997 75 10 + 4997 75 10 4997 75 10 4997 75 10 6532 68 9 6666 68 9 6894 68 9 + 6916 68 9 7337 68 9 7337 68 9 7337 68 9 9471 59 8 9487 59 8 + 9767 59 8 10095 59 8 10317 59 8 10450 59 8 10450 59 8 10450 59 8 + 10450 59 8 10785 51 7 11379 51 7 11714 51 7 11714 51 7 11714 51 7 + 11714 51 7 11714 51 7 11714 51 7 12009 40 6 12381 40 6 12676 40 6 + 12676 40 6 12676 40 6 12676 40 6 12676 40 6 12676 40 6 12676 40 6 + 12676 40 6 12676 40 6 13418 35 5 13566 35 5 14082 35 5 14195 35 5 + 14195 35 5 15040 28 4 15154 28 4 15999 28 4 15999 28 4 15999 28 4 + 15999 28 4 15999 28 4 16606 22 3 16758 22 3 17365 22 3 17365 22 3 + 17365 22 3 17365 22 3 20135 9 2 20141 9 2 20213 9 2 20447 9 2 + 20453 9 2 20453 9 2 20599 9 2 20846 9 2 20846 9 2 20846 9 2 + 20846 9 2 20846 9 2 20846 9 2 22244 1 1 22528 1 1 22846 1 1 + 22916 1 1 22932 1 1 23155 1 1 23155 1 1 23155 1 1} + +do_execsql_test 5.2.10.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {667 158 0 671 250 6 759 158 5 768 113 4 777 113 4 777 113 4 + 777 113 4 777 252 4 792 247 12 805 250 6 805 250 6 805 250 6 + 805 250 6 805 250 6 805 398 6 822 158 5 822 158 5 822 158 5 + 822 158 5 822 346 5 839 113 8 840 247 12 840 247 12 840 247 12 + 840 247 12 840 247 12 840 247 12 840 247 12 840 247 12 840 247 12 + 840 247 12 840 247 12 840 393 12 845 224 6 870 102 10 870 158 0 + 870 158 0 870 158 0 870 158 0 870 355 0 899 113 8 899 113 8 + 899 113 8 899 113 8 899 113 8 899 113 8 899 113 8 899 234 8 + 911 223 7 929 148 7 934 223 7 934 223 7 934 223 7 934 223 7 + 934 223 7 934 223 7 934 239 7 938 102 10 938 102 10 938 102 10 + 938 102 10 938 102 10 938 102 10 938 102 10 938 102 10 938 102 10 + 938 148 7 938 148 7 938 148 7 938 148 7 938 148 7 938 148 7 + 938 160 7 938 208 10 959 224 6 959 224 6 959 224 6 959 224 6 + 959 224 6 959 238 6 963 133 8 979 133 8 979 133 8 979 133 8 + 979 133 8 979 133 8 979 133 8 979 133 8 979 330 8} + +do_execsql_test 5.2.10.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {295 1 1 335 1 1 607 1 1 667 1 1 742 1 1 759 1 1 845 1 1 + 890 1 1 929 1 1 959 1 1 962 1 1 962 1 1 962 1 1 962 1 1 + 962 1 1 962 1 1 962 1 1 962 1 1 962 1 1 1264 1 1 1264 1 1 + 1264 1 1 1264 1 1 1264 1 1 1264 1 1 1366 1 1 1366 1 1 1366 1 1 + 1366 1 1 1383 1 1 1398 1 1 1406 1 1 1421 1 1 1519 1 1 1519 1 1 + 1535 1 1 1651 1 1 1669 1 1 1682 1 1 1695 1 1 1804 1 1 1804 1 1 + 1804 1 1 1804 1 1 1804 1 1 1897 1 1 1919 1 1 2000 1 1 2048 1 1 + 2050 1 1 2050 1 1 2070 1 1 2086 1 1 2108 1 1 2108 1 1 2134 1 1 + 2150 1 1 2309 1 1 2309 1 1 2309 1 1 2340 1 1 2340 1 1 2340 1 1 + 2430 1 1 2690 1 1 2758 1 1 2770 1 1 2776 1 1 2834 1 1 2848 1 1 + 2947 1 1 2947 1 1 2947 1 1 2947 1 1 2980 1 1 3082 1 1 3088 1 1 + 3088 1 1 3113 1 1 3113 1 1 3113 1 1 3113 1 1 3234 1 1 3481 1 1 + 3481 1 1 3481 1 1 3481 1 1 3481 1 1 3481 1 1} + +do_execsql_test 5.2.11.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {911 223 7 934 158 26 934 158 26 934 158 26 934 158 26 934 158 26 + 934 158 33 934 223 7 934 223 7 934 223 7 934 223 7 934 223 7 + 934 223 7 934 223 20 934 223 20 934 223 20 934 223 20 934 223 20 + 934 223 20 934 223 20 934 223 20 934 223 20 934 223 20 934 223 20 + 934 223 20 934 223 20 934 223 26 934 239 7 959 102 49 959 102 49 + 959 102 49 959 102 49 959 102 49 959 102 49 959 102 49 959 102 49 + 959 102 49 959 102 49 959 102 57 959 102 57 959 102 57 959 102 57 + 959 102 57 959 102 57 959 102 57 959 102 57 959 113 38 959 113 38 + 959 113 38 959 113 38 959 113 49 959 158 33 959 158 33 959 158 33 + 959 158 33 959 158 33 959 158 33 959 158 38 963 102 58 979 102 49 + 979 102 49 979 102 49 979 102 49 979 102 49 979 102 49 979 102 52 + 979 102 52 979 102 52 979 102 52 979 102 52 979 102 52 979 102 52 + 979 102 55 979 102 55 979 102 55 979 102 55 979 102 55 979 102 55 + 979 102 55 979 102 55 979 102 55 979 102 58 979 102 58 979 102 58 + 979 102 58 979 102 58 979 102 58 979 102 58 979 102 58} + +do_execsql_test 5.2.11.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {1398 1 1 1682 1 1 2000 1 1 2070 1 1 2086 1 1 2309 1 1 2309 1 1 + 2309 1 1 5079 9 2 5085 9 2 5157 9 2 5391 9 2 5397 9 2 5397 9 2 + 5543 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 5790 9 2 + 6397 22 3 6549 22 3 7156 22 3 7156 22 3 7156 22 3 7156 22 3 + 8001 28 4 8115 28 4 8960 28 4 8960 28 4 8960 28 4 8960 28 4 + 8960 28 4 9702 35 5 9850 35 5 10366 35 5 10479 35 5 10479 35 5 + 10774 40 6 11146 40 6 11441 40 6 11441 40 6 11441 40 6 11441 40 6 + 11441 40 6 11441 40 6 11441 40 6 11441 40 6 11441 40 6 11563 68 9 + 11697 68 9 11776 51 7 11925 68 9 11947 68 9 12368 68 9 12368 68 9 + 12368 68 9 12370 51 7 12530 59 8 12546 59 8 12705 51 7 12705 51 7 + 12705 51 7 12705 51 7 12705 51 7 12705 51 7 12826 59 8 + 13050 75 10 13110 75 10 13110 75 10 13154 59 8 13376 59 8 + 13509 59 8 13509 59 8 13509 59 8 13509 59 8 13528 84 11 + 13566 84 11 13692 75 10 13796 84 11 13836 75 10 13840 84 11 + 13949 75 10 13949 75 10 13949 75 10 13949 75 10 14195 84 11 + 14195 84 11} + +do_execsql_test 5.2.12.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 113 113 1 + 113 113 1 158 158 1 160 158 1 160 158 2 223 223 1 224 224 1 + 238 234 2 239 234 2 239 238 2 252 250 2 256 252 2 257 247 4 + 257 247 4 257 250 3 335 330 2 336 330 2 336 335 2 355 354 1 + 355 354 2 355 355 1 399 393 3 399 393 3 399 393 3 399 393 3 + 399 393 4 480 480 1 480 480 1 572 572 1 574 574 1 618 618 1 + 618 618 1 633 629 2 634 627 3 634 627 3 634 627 4 634 629 3 + 667 667 1 670 667 2 671 667 2 671 667 2 671 667 3 711 711 1 + 711 711 1 716 705 2 726 726 1 730 730 1 762 762 1 768 759 3 + 768 762 2 768 762 2 792 790 2 792 790 2 794 786 3 794 786 3 + 844 839 4 845 839 4 845 839 4 845 839 4 845 839 4 870 870 1 + 870 870 1 870 870 2 934 934 1 938 929 3 938 934 2 938 934 2 + 959 959 1 963 963 1} + +do_execsql_test 5.2.12.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 10 8 + {} 14 12 {} 15 13 {} 19 17 {} 20 18 {} 21 19 {} 23 21 {} 25 23 + {} 34 29 {} 35 30 {} 36 31 {} 37 32 {} 38 33 {} 38 33 {} 40 34 + {} 41 35 {} 42 36 {} 43 37 {} 43 37 {} 50 42 {} 56 47 {} 60 51 + {} 61 52 {} 62 53 {} 64 55 {} 64 55 {} 66 56 {} 67 57 {} 68 58 + {} 69 59 {} 70 60 {} 71 61 {} 72 62 {} 78 67 {} 78 67 {} 78 67 + {} 81 68 {} 82 69 {} 83 70 {} 85 72 {} 85 72 {} 89 75 113 2 2 + 113 2 2 223 11 9 239 12 10 239 13 11 257 18 16 335 22 20 + 335 24 22 355 27 25 355 27 25 504 16 14 504 17 15 705 58 49 + 710 26 24 711 57 48 711 59 50 759 63 54 929 84 71 959 88 74 + 963 87 73 1185 32 28 1185 32 28 1191 29 26 1191 29 26 1334 51 43 + 1334 55 46 1338 52 44 1338 52 44 1584 31 27 1678 77 66 1684 73 63 + 1684 73 63 1885 48 40 1889 46 39 1889 46 39 1891 45 38 1891 49 41 + 2005 54 45 2523 75 64 2523 76 65} + +do_execsql_test 5.2.13.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 113 113 1 + 113 113 1 158 158 0 158 158 1 355 355 0 355 355 1 393 393 1 + 393 393 1 399 399 0 399 399 1 480 480 1 480 480 1 618 618 1 + 618 618 1 629 629 0 629 629 1 667 667 0 667 667 1 768 768 1 + 768 768 1 839 839 1 839 839 1 870 870 1 870 870 1 870 870 2 + 938 938 1 938 938 1} + +do_execsql_test 5.2.13.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 10 8 + {} 11 9 {} 12 10 {} 13 11 {} 14 12 {} 15 13 {} 16 14 {} 17 15 + {} 18 16 {} 19 17 {} 20 18 {} 21 19 {} 22 20 {} 23 21 {} 24 22 + {} 25 23 {} 26 24 {} 31 27 {} 34 29 {} 35 30 {} 36 31 {} 37 32 + {} 38 33 {} 38 33 {} 40 34 {} 41 35 {} 42 36 {} 43 37 {} 43 37 + {} 45 38 {} 48 40 {} 49 41 {} 50 42 {} 51 43 {} 54 45 {} 55 46 + {} 56 47 {} 57 48 {} 58 49 {} 59 50 {} 60 51 {} 61 52 {} 62 53 + {} 63 54 {} 64 55 {} 64 55 {} 66 56 {} 67 57 {} 68 58 {} 69 59 + {} 70 60 {} 71 61 {} 72 62 {} 75 64 {} 76 65 {} 77 66 {} 78 67 + {} 78 67 {} 78 67 {} 81 68 {} 82 69 {} 83 70 {} 84 71 {} 85 72 + {} 85 72 {} 87 73 {} 88 74 {} 89 75 113 2 2 113 2 2 355 27 25 + 355 27 25 393 29 26 393 29 26 399 32 28 399 32 28 629 46 39 + 629 46 39 667 52 44 667 52 44 839 73 63 839 73 63} + +do_execsql_test 5.2.14.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {963 929 6 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 83 979 113 80 979 113 81 979 113 82 979 133 79 979 148 78 + 979 158 76 979 158 77 979 160 76 979 208 75 979 223 74 979 224 73 + 979 234 72 979 238 71 979 239 70 979 247 69 979 250 68 979 252 67 + 979 256 66 979 257 65 979 295 64 979 309 63 979 330 63 979 335 61 + 979 336 60 979 346 59 979 354 58 979 355 56 979 355 58 979 393 55 + 979 393 56 979 398 54 979 399 52 979 399 53 979 412 52 979 421 51 + 979 430 50 979 443 49 979 480 47 979 480 48 979 572 46 979 574 46 + 979 607 44 979 618 42 979 618 43 979 627 41 979 629 40 979 629 40 + 979 633 39 979 634 38 979 652 37 979 660 36 979 667 34 979 667 35 + 979 670 34 979 671 33 979 683 32 979 705 31 979 711 30 979 716 29 + 979 726 28 979 730 27 979 759 26 979 762 25 979 768 23 979 768 24 + 979 777 22 979 786 21 979 790 20 979 792 19 979 794 18 979 805 17 + 979 822 16 979 839 15 979 839 15 979 840 13 979 844 12 979 845 11 + 979 870 8 979 870 9 979 870 10 979 899 8 979 911 7} + +do_execsql_test 5.2.14.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE CURRENT ROW ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {2851 89 89 3778 88 88 4681 87 87 5556 83 83 5574 82 82 5586 81 81 5640 84 84 5640 85 85 5640 86 86 7324 80 80 8123 77 77 8129 73 73 8129 74 74 8163 78 78 8163 79 79 8940 71 71 8968 75 75 8968 76 76 @@ -4216,7 +4910,7 @@ do_execsql_test 5.3.1.1 { count(a) OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 @@ -4237,7 +4931,7 @@ do_execsql_test 5.3.1.2 { dense_rank() OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 @@ -4256,9 +4950,9 @@ do_execsql_test 5.3.2.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 9 899 113 16 899 113 16 899 113 16 @@ -4280,9 +4974,9 @@ do_execsql_test 5.3.2.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 81 11 {} 81 11 {} 81 11 {} 81 11 {} 81 11 {} 81 11 {} 81 11 {} 81 11 {} 81 11 2947 74 10 2947 74 10 2947 74 10 2947 74 10 2947 74 10 2947 74 10 2947 74 10 5287 65 9 5287 65 9 5287 65 9 @@ -4306,7 +5000,7 @@ do_execsql_test 5.3.3.1 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 @@ -4328,7 +5022,7 @@ do_execsql_test 5.3.3.2 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 @@ -4347,8 +5041,8 @@ do_execsql_test 5.3.4.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 934 158 8 934 158 8 934 158 8 934 158 8 934 158 8 @@ -4370,8 +5064,8 @@ do_execsql_test 5.3.4.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 2050 7 2 2050 7 2 2050 7 2 2050 7 2 2050 7 2 2050 7 2 2050 7 2 2050 7 2 4359 15 3 4359 15 3 4359 15 3 4359 15 3 4359 15 3 4359 15 3 4359 15 3 @@ -4393,8 +5087,8 @@ do_execsql_test 5.3.5.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 @@ -4416,8 +5110,8 @@ do_execsql_test 5.3.5.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 2 2 {} 2 2 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 10 8 {} 14 12 {} 15 13 {} 19 17 {} 20 18 {} 21 19 {} 23 21 {} 25 23 {} 27 25 {} 27 25 {} 34 29 {} 35 30 {} 36 31 @@ -4438,8 +5132,8 @@ do_execsql_test 5.3.6.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 @@ -4459,8 +5153,8 @@ do_execsql_test 5.3.6.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 2 2 {} 2 2 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 10 8 {} 11 9 {} 12 10 {} 13 11 {} 14 12 {} 15 13 {} 16 14 {} 17 15 {} 18 16 {} 19 17 {} 20 18 {} 21 19 {} 22 20 @@ -4480,9 +5174,9 @@ do_execsql_test 5.3.7.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {963 929 6 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 979 102 83 979 113 80 979 113 81 979 113 82 979 133 79 979 148 78 979 158 76 979 158 77 979 160 76 979 208 75 979 223 74 979 224 73 @@ -4504,9 +5198,324 @@ do_execsql_test 5.3.7.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {2851 89 89 3778 88 88 4681 87 87 5556 83 83 5574 82 82 5586 81 81 + 5640 84 84 5640 85 85 5640 86 86 7324 80 80 8123 77 77 8129 73 73 + 8129 74 74 8163 78 78 8163 79 79 8940 71 71 8968 75 75 8968 76 76 + 9727 66 66 9745 69 69 9745 70 70 9745 72 72 10504 65 65 + 10504 67 67 10504 68 68 11215 64 64 11844 62 62 11920 63 63 + 13274 60 60 13274 61 61 13897 58 58 13903 57 57 13925 56 56 + 13937 55 55 13941 59 59 15203 53 53 15241 54 54 15832 52 52 + 17100 48 48 17104 46 46 17104 47 47 17106 45 45 17126 49 49 + 17126 50 50 17126 51 51 17569 42 42 17733 44 44 18176 43 43 + 18597 40 40 18597 41 41 18952 37 37 18996 39 39 19395 38 38 + 19760 35 35 19788 36 36 20492 32 32 20492 33 33 20498 30 30 + 20536 34 34 20833 29 29 20871 28 28 20891 31 31 21180 27 27 + 21752 23 23 21830 26 26 22025 21 21 22087 22 22 22087 24 24 + 22087 25 25 22278 20 20 22316 19 19 22549 15 15 22557 14 14 + 22573 17 17 22573 18 18 22706 10 10 22796 11 11 22796 12 12 + 22796 13 13 22796 16 16 23022 4 4 23042 2 2 23042 3 3 23042 9 9 + 23155 1 1 23155 5 5 23155 6 6 23155 7 7 23155 8 8} + +do_execsql_test 5.3.8.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0} + +do_execsql_test 5.3.8.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1} + +do_execsql_test 5.3.9.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 870 158 0 + 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 870 158 0 + 870 158 0 870 158 0 899 113 9 899 113 9 899 113 9 899 113 9 + 899 113 9 899 113 9 899 113 9 899 113 16 899 113 16 899 113 16 + 899 113 16 899 113 16 899 113 16 899 113 16 899 113 16 899 113 16 + 979 102 44 979 102 44 979 102 44 979 102 44 979 102 44 979 102 49 + 979 102 49 979 102 49 979 102 49 979 102 49 979 102 49 979 102 49 + 979 102 56 979 102 56 979 102 56 979 102 56 979 102 56 979 102 56 + 979 102 62 979 102 62 979 102 62 979 102 62 979 102 62 979 102 62 + 979 102 62 979 102 62 979 102 62 979 102 62 979 102 62 979 102 62 + 979 102 62 979 102 75 979 102 75 979 102 75 979 102 75 979 102 75 + 979 102 75 979 102 75 979 102 75 979 113 25 979 113 25 979 113 25 + 979 113 25 979 113 25 979 113 25 979 113 25 979 113 25 979 113 33 + 979 113 33 979 113 33 979 113 33 979 113 33 979 113 33 979 113 33 + 979 113 33 979 113 33 979 113 33 979 113 33} + +do_execsql_test 5.3.9.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 84 11 {} 84 11 {} 84 11 {} 84 11 {} 84 11 {} 84 11 + 2050 75 10 2050 75 10 2050 75 10 2050 75 10 2050 75 10 2050 75 10 + 2050 75 10 2050 75 10 2050 75 10 4997 68 9 4997 68 9 4997 68 9 + 4997 68 9 4997 68 9 4997 68 9 4997 68 9 7337 59 8 7337 59 8 + 7337 59 8 7337 59 8 7337 59 8 7337 59 8 7337 59 8 7337 59 8 + 7337 59 8 10450 51 7 10450 51 7 10450 51 7 10450 51 7 10450 51 7 + 10450 51 7 10450 51 7 10450 51 7 11714 40 6 11714 40 6 11714 40 6 + 11714 40 6 11714 40 6 11714 40 6 11714 40 6 11714 40 6 11714 40 6 + 11714 40 6 11714 40 6 12676 35 5 12676 35 5 12676 35 5 12676 35 5 + 12676 35 5 14195 28 4 14195 28 4 14195 28 4 14195 28 4 14195 28 4 + 14195 28 4 14195 28 4 15999 22 3 15999 22 3 15999 22 3 15999 22 3 + 15999 22 3 15999 22 3 17365 9 2 17365 9 2 17365 9 2 17365 9 2 + 17365 9 2 17365 9 2 17365 9 2 17365 9 2 17365 9 2 17365 9 2 + 17365 9 2 17365 9 2 17365 9 2 20846 1 1 20846 1 1 20846 1 1 + 20846 1 1 20846 1 1 20846 1 1 20846 1 1 20846 1 1} + +do_execsql_test 5.3.10.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0} + +do_execsql_test 5.3.10.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1} + +do_execsql_test 5.3.11.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 934 158 27 934 158 27 934 158 27 934 158 27 934 158 27 + 934 158 27 934 158 27 934 223 8 934 223 8 934 223 8 934 223 8 + 934 223 8 934 223 8 934 223 8 934 223 8 934 223 8 934 223 8 + 934 223 8 934 223 8 934 223 8 934 223 21 934 223 21 934 223 21 + 934 223 21 934 223 21 934 223 21 959 102 50 959 102 50 959 102 50 + 959 102 50 959 102 50 959 102 50 959 102 50 959 102 50 959 102 50 + 959 102 50 959 102 50 959 102 50 959 102 50 959 102 50 959 102 50 + 959 102 50 959 102 50 959 113 39 959 113 39 959 113 39 959 113 39 + 959 113 39 959 113 39 959 113 39 959 113 39 959 113 39 959 113 39 + 959 113 39 959 158 34 959 158 34 959 158 34 959 158 34 959 158 34 + 979 102 46 979 102 46 979 102 46 979 102 46 979 102 46 979 102 46 + 979 102 46 979 102 47 979 102 47 979 102 47 979 102 47 979 102 47 + 979 102 47 979 102 47 979 102 47 979 102 47 979 102 49 979 102 49 + 979 102 49 979 102 49 979 102 49 979 102 49} + +do_execsql_test 5.3.11.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2309 9 2 + 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2309 9 2 5790 22 3 + 5790 22 3 5790 22 3 5790 22 3 5790 22 3 5790 22 3 7156 28 4 + 7156 28 4 7156 28 4 7156 28 4 7156 28 4 7156 28 4 7156 28 4 + 8960 35 5 8960 35 5 8960 35 5 8960 35 5 8960 35 5 10028 68 9 + 10028 68 9 10028 68 9 10028 68 9 10028 68 9 10028 68 9 10028 68 9 + 10396 59 8 10396 59 8 10396 59 8 10396 59 8 10396 59 8 10396 59 8 + 10396 59 8 10396 59 8 10396 59 8 10479 40 6 10479 40 6 10479 40 6 + 10479 40 6 10479 40 6 10479 40 6 10479 40 6 10479 40 6 10479 40 6 + 10479 40 6 10479 40 6 11002 75 10 11002 75 10 11002 75 10 + 11002 75 10 11002 75 10 11002 75 10 11002 75 10 11002 75 10 + 11002 75 10 11441 51 7 11441 51 7 11441 51 7 11441 51 7 + 11441 51 7 11441 51 7 11441 51 7 11441 51 7 12145 84 11 + 12145 84 11 12145 84 11 12145 84 11 12145 84 11 12145 84 11} + +do_execsql_test 5.3.12.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 158 158 1 160 160 1 160 160 1 223 223 1 224 224 1 + 238 234 2 239 234 2 239 238 2 252 250 2 256 252 2 257 247 4 + 257 247 4 257 250 3 335 330 2 336 330 2 336 335 2 354 354 1 + 354 354 1 355 355 1 398 393 3 398 393 3 399 393 3 399 398 2 + 399 398 2 572 572 1 574 574 1 633 629 2 634 627 3 634 627 3 + 634 627 3 634 629 3 667 667 1 670 667 2 671 667 2 671 670 2 + 671 670 2 711 711 1 711 711 1 716 705 2 726 726 1 730 730 1 + 762 762 1 762 762 1 762 762 1 768 759 3 792 790 2 792 790 2 + 794 786 3 794 786 3 844 839 4 845 839 4 845 839 4 845 840 3 + 845 840 3 934 934 1 934 934 1 934 934 1 938 929 3 959 959 1 + 963 963 1} + +do_execsql_test 5.3.12.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 2 2 {} 2 2 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 + {} 9 7 {} 10 8 {} 14 12 {} 15 13 {} 19 17 {} 20 18 {} 21 19 + {} 23 21 {} 25 23 {} 27 25 {} 27 25 {} 34 29 {} 35 30 {} 36 31 + {} 37 32 {} 38 33 {} 38 33 {} 40 34 {} 41 35 {} 42 36 {} 43 37 + {} 43 37 {} 50 42 {} 56 47 {} 60 51 {} 61 52 {} 62 53 {} 64 55 + {} 64 55 {} 66 56 {} 67 57 {} 68 58 {} 69 59 {} 70 60 {} 71 61 + {} 72 62 {} 78 67 {} 78 67 {} 78 67 {} 81 68 {} 82 69 {} 83 70 + {} 85 72 {} 85 72 {} 89 75 223 11 9 239 12 10 239 13 11 + 257 18 16 335 22 20 335 24 22 504 16 14 504 17 15 671 52 44 + 671 52 44 705 58 49 710 26 24 711 57 48 711 59 50 759 63 54 + 786 32 28 786 32 28 798 29 26 798 29 26 845 73 63 845 73 63 + 929 84 71 959 88 74 963 87 73 1260 46 39 1260 46 39 1334 51 43 + 1334 55 46 1584 31 27 1678 77 66 1885 48 40 1891 45 38 1891 49 41 + 2005 54 45 2523 75 64 2523 76 65} + +do_execsql_test 5.3.13.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0 + {} {} 0 {} {} 0 {} {} 0 {} {} 0 {} {} 0} + +do_execsql_test 5.3.13.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 2 2 {} 2 2 {} 4 3 {} 5 4 {} 6 5 {} 6 5 {} 8 6 + {} 9 7 {} 10 8 {} 11 9 {} 12 10 {} 13 11 {} 14 12 {} 15 13 + {} 16 14 {} 17 15 {} 18 16 {} 19 17 {} 20 18 {} 21 19 {} 22 20 + {} 23 21 {} 24 22 {} 25 23 {} 26 24 {} 27 25 {} 27 25 {} 29 26 + {} 29 26 {} 31 27 {} 32 28 {} 32 28 {} 34 29 {} 35 30 {} 36 31 + {} 37 32 {} 38 33 {} 38 33 {} 40 34 {} 41 35 {} 42 36 {} 43 37 + {} 43 37 {} 45 38 {} 46 39 {} 46 39 {} 48 40 {} 49 41 {} 50 42 + {} 51 43 {} 52 44 {} 52 44 {} 54 45 {} 55 46 {} 56 47 {} 57 48 + {} 58 49 {} 59 50 {} 60 51 {} 61 52 {} 62 53 {} 63 54 {} 64 55 + {} 64 55 {} 66 56 {} 67 57 {} 68 58 {} 69 59 {} 70 60 {} 71 61 + {} 72 62 {} 73 63 {} 73 63 {} 75 64 {} 76 65 {} 77 66 {} 78 67 + {} 78 67 {} 78 67 {} 81 68 {} 82 69 {} 83 70 {} 84 71 {} 85 72 + {} 85 72 {} 87 73 {} 88 74 {} 89 75} + +do_execsql_test 5.3.14.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {963 929 6 979 102 82 979 102 82 979 102 82 979 102 82 979 102 82 + 979 102 83 979 113 80 979 113 81 979 113 82 979 133 79 979 148 78 + 979 158 76 979 158 77 979 160 76 979 208 75 979 223 74 979 224 73 + 979 234 72 979 238 71 979 239 70 979 247 69 979 250 68 979 252 67 + 979 256 66 979 257 65 979 295 64 979 309 63 979 330 63 979 335 61 + 979 336 60 979 346 59 979 354 58 979 355 56 979 355 58 979 393 55 + 979 393 56 979 398 54 979 399 52 979 399 53 979 412 52 979 421 51 + 979 430 50 979 443 49 979 480 47 979 480 48 979 572 46 979 574 46 + 979 607 44 979 618 42 979 618 43 979 627 41 979 629 40 979 629 40 + 979 633 39 979 634 38 979 652 37 979 660 36 979 667 34 979 667 35 + 979 670 34 979 671 33 979 683 32 979 705 31 979 711 30 979 716 29 + 979 726 28 979 730 27 979 759 26 979 762 25 979 768 23 979 768 24 + 979 777 22 979 786 21 979 790 20 979 792 19 979 794 18 979 805 17 + 979 822 16 979 839 15 979 839 15 979 840 13 979 844 12 979 845 11 + 979 870 8 979 870 9 979 870 10 979 899 8 979 911 7} + +do_execsql_test 5.3.14.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE GROUP ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {2851 89 89 3778 88 88 4681 87 87 5556 83 83 5574 82 82 5586 81 81 5640 84 84 5640 85 85 5640 86 86 7324 80 80 8123 77 77 8129 73 73 8129 74 74 8163 78 78 8163 79 79 8940 71 71 8968 75 75 8968 76 76 @@ -4531,7 +5540,7 @@ do_execsql_test 5.4.1.1 { count(a) OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 158 158 0 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 @@ -4554,7 +5563,7 @@ do_execsql_test 5.4.1.2 { dense_rank() OVER win FROM t3 WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 @@ -4573,9 +5582,9 @@ do_execsql_test 5.4.2.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {113 113 1 234 234 1 257 257 1 336 336 1 354 354 1 768 768 1 839 839 1 839 839 1 899 113 10 899 113 10 899 113 10 899 113 10 899 113 10 899 113 10 899 113 10 899 113 17 899 113 17 899 113 17 @@ -4597,9 +5606,9 @@ do_execsql_test 5.4.2.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a + WINDOW win AS ( ORDER BY a NULLS FIRST RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 81 11 {} 81 11 {} 81 11 {} 81 11 113 81 11 257 81 11 839 81 11 839 81 11 899 81 11 2947 74 10 2947 74 10 2947 74 10 3368 74 10 3390 74 10 3618 74 10 3752 74 10 5287 65 9 5287 65 9 @@ -4623,7 +5632,7 @@ do_execsql_test 5.4.3.1 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 158 158 0 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 @@ -4647,7 +5656,7 @@ do_execsql_test 5.4.3.2 { FROM t3 WINDOW win AS ( PARTITION BY coalesce(a, '') RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 @@ -4666,8 +5675,8 @@ do_execsql_test 5.4.4.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {158 158 0 355 355 0 399 399 0 629 629 0 667 667 0 870 158 1 870 158 1 870 158 1 870 158 1 870 158 1 870 158 1 870 870 0 911 158 1 934 158 1 934 158 9 934 158 9 934 158 9 934 158 9 @@ -4689,8 +5698,8 @@ do_execsql_test 5.4.4.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY a GROUPS 6 PRECEDING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY a NULLS FIRST GROUPS 6 PRECEDING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 1 1 355 1 1 399 1 1 629 1 1 667 1 1 2050 7 2 2050 7 2 2050 7 2 2273 7 2 2289 7 2 2359 7 2 2677 7 2 2961 7 2 4359 15 3 4359 15 3 4359 15 3 4359 15 3 4359 15 3 4359 15 3 @@ -4713,8 +5722,8 @@ do_execsql_test 5.4.5.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 160 158 1 160 158 2 160 158 2 208 208 1 224 223 2 224 223 2 239 234 3 239 234 3 239 234 3 252 247 3 257 247 5 257 247 5 257 250 4 @@ -4736,8 +5745,8 @@ do_execsql_test 5.4.5.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 25 23 {} 34 29 {} 36 31 {} 38 33 {} 38 33 {} 40 34 {} 41 35 {} 43 37 {} 43 37 {} 50 42 {} 60 51 {} 61 52 {} 64 55 {} 64 55 {} 67 57 {} 68 58 @@ -4758,8 +5767,8 @@ do_execsql_test 5.4.6.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 158 158 0 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 @@ -4781,8 +5790,8 @@ do_execsql_test 5.4.6.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + WINDOW win AS ( ORDER BY c NULLS FIRST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 11 9 {} 12 10 {} 13 11 {} 16 14 {} 17 15 {} 18 16 {} 22 20 {} 24 22 {} 25 23 {} 26 24 {} 31 27 {} 34 29 {} 36 31 {} 38 33 {} 38 33 {} 40 34 @@ -4803,9 +5812,9 @@ do_execsql_test 5.4.7.1 { min(c) OVER win, count(a) OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 113 81 979 113 82 979 133 80 979 148 79 979 158 77 979 158 78 979 160 77 979 208 76 979 223 75 979 224 74 979 234 73 @@ -4827,9 +5836,331 @@ do_execsql_test 5.4.7.2 { rank() OVER win, dense_rank() OVER win FROM t3 - WINDOW win AS ( ORDER BY c , b , a + WINDOW win AS ( ORDER BY c NULLS FIRST, b NULLS FIRST, a NULLS FIRST ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES ) - ORDER BY 1 , 2 , 3 + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {3830 89 89 4741 88 88 5640 84 84 5640 85 85 5640 86 86 5640 87 87 + 6485 81 81 6485 82 82 6485 83 83 7324 80 80 8163 78 78 8163 79 79 + 8968 73 73 8968 74 74 8968 75 75 8968 76 76 8968 77 77 9745 69 69 + 9745 70 70 9745 71 71 9745 72 72 10504 65 65 10504 66 66 + 10504 67 67 10504 68 68 11215 64 64 11920 63 63 12603 62 62 + 13274 60 60 13274 61 61 13941 59 59 14608 55 55 14608 56 56 + 14608 57 57 14608 58 58 15241 54 54 15870 53 53 16499 52 52 + 17126 49 49 17126 50 50 17126 51 51 17733 44 44 17733 45 45 + 17733 46 46 17733 47 47 17733 48 48 18176 42 42 18176 43 43 + 18597 40 40 18597 41 41 18996 39 39 19395 37 37 19395 38 38 + 19788 36 36 20181 35 35 20536 34 34 20891 30 30 20891 31 31 + 20891 32 32 20891 33 33 21226 28 28 21226 29 29 21535 27 27 + 21830 26 26 22087 22 22 22087 23 23 22087 24 24 22087 25 25 + 22334 21 21 22573 17 17 22573 18 18 22573 19 19 22573 20 20 + 22796 11 11 22796 12 12 22796 13 13 22796 14 14 22796 15 15 + 22796 16 16 22929 10 10 23042 9 9 23155 1 1 23155 2 2 23155 3 3 + 23155 4 4 23155 5 5 23155 6 6 23155 7 7 23155 8 8} + +do_execsql_test 5.4.8.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 158 158 0 + 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 + 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 + 257 257 1 295 295 1 309 309 1 330 330 1 335 335 1 336 336 1 + 346 346 1 354 354 1 355 355 0 355 355 1 393 393 1 393 393 1 + 398 398 1 399 399 0 399 399 1 412 412 1 421 421 1 430 430 1 + 443 443 1 480 480 1 480 480 1 572 572 1 574 574 1 607 607 1 + 618 618 1 618 618 1 627 627 1 629 629 0 629 629 1 633 633 1 + 634 634 1 652 652 1 660 660 1 667 667 0 667 667 1 670 670 1 + 671 671 1 683 683 1 705 705 1 711 711 1 716 716 1 726 726 1 + 730 730 1 759 759 1 762 762 1 768 768 1 768 768 1 777 777 1 + 786 786 1 790 790 1 792 792 1 794 794 1 805 805 1 822 822 1 + 839 839 1 839 839 1 840 840 1 844 844 1 845 845 1 870 870 0 + 870 870 1 870 870 1 899 899 1 911 911 1 929 929 1 934 934 1 + 938 938 1 938 938 1 959 959 1 963 963 1 979 979 1} + +do_execsql_test 5.4.8.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + 113 1 1 113 1 1 133 1 1 223 1 1 239 1 1 247 1 1 257 1 1 + 295 1 1 309 1 1 335 1 1 355 1 1 355 1 1 393 1 1 393 1 1 + 399 1 1 399 1 1 421 1 1 443 1 1 607 1 1 627 1 1 629 1 1 + 629 1 1 633 1 1 667 1 1 667 1 1 671 1 1 683 1 1 705 1 1 + 711 1 1 759 1 1 777 1 1 805 1 1 839 1 1 839 1 1 845 1 1 + 899 1 1 911 1 1 929 1 1 959 1 1 963 1 1 979 1 1} + +do_execsql_test 5.4.9.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {158 158 0 355 355 0 399 399 0 629 629 0 667 667 0 870 113 1 + 870 158 1 870 158 1 870 158 1 870 158 1 870 158 1 870 158 1 + 870 158 1 870 870 0 899 113 10 899 113 10 899 113 10 899 113 10 + 899 113 10 899 113 10 899 113 10 899 113 17 899 113 17 899 113 17 + 899 113 17 899 113 17 899 113 17 899 113 17 899 158 1 963 113 17 + 979 102 34 979 102 45 979 102 45 979 102 45 979 102 45 979 102 45 + 979 102 50 979 102 50 979 102 50 979 102 50 979 102 50 979 102 50 + 979 102 50 979 102 57 979 102 57 979 102 57 979 102 57 979 102 57 + 979 102 57 979 102 63 979 102 63 979 102 63 979 102 63 979 102 63 + 979 102 63 979 102 63 979 102 63 979 102 63 979 102 63 979 102 63 + 979 102 63 979 102 63 979 102 76 979 102 76 979 102 76 979 102 76 + 979 102 76 979 102 76 979 102 76 979 102 76 979 113 17 979 113 26 + 979 113 26 979 113 26 979 113 26 979 113 26 979 113 26 979 113 26 + 979 113 26 979 113 34 979 113 34 979 113 34 979 113 34 979 113 34 + 979 113 34 979 113 34 979 113 34 979 113 34 979 113 34} + +do_execsql_test 5.4.9.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 84 11 {} 84 11 355 84 11 399 84 11 629 84 11 667 84 11 + 2050 75 10 2050 75 10 2050 75 10 2050 75 10 2163 75 10 2307 75 10 + 2889 75 10 2889 75 10 2949 75 10 4997 68 9 4997 68 9 4997 68 9 + 5418 68 9 5440 68 9 5668 68 9 5802 68 9 7337 59 8 7337 59 8 + 7337 59 8 7337 59 8 7470 59 8 7692 59 8 8020 59 8 8300 59 8 + 8316 59 8 10450 51 7 10450 51 7 10450 51 7 10450 51 7 10450 51 7 + 10450 51 7 10785 51 7 11379 51 7 11714 40 6 11714 40 6 11714 40 6 + 11714 40 6 11714 40 6 11714 40 6 11714 40 6 11714 40 6 11714 40 6 + 12009 40 6 12381 40 6 12676 35 5 12676 35 5 12789 35 5 13305 35 5 + 13453 35 5 14195 28 4 14195 28 4 14195 28 4 14195 28 4 14195 28 4 + 15040 28 4 15154 28 4 15999 22 3 15999 22 3 15999 22 3 15999 22 3 + 16606 22 3 16758 22 3 17365 9 2 17365 9 2 17365 9 2 17365 9 2 + 17365 9 2 17365 9 2 17612 9 2 17758 9 2 17758 9 2 17764 9 2 + 17998 9 2 18070 9 2 18076 9 2 20846 1 1 20846 1 1 20846 1 1 + 21069 1 1 21085 1 1 21155 1 1 21473 1 1 21757 1 1} + +do_execsql_test 5.4.10.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 158 158 0 + 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 + 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 + 257 257 1 295 295 1 309 309 1 330 330 1 335 335 1 336 336 1 + 346 346 1 354 354 1 355 355 0 355 355 1 393 393 1 393 393 1 + 398 398 1 399 399 0 399 399 1 412 412 1 421 421 1 430 430 1 + 443 443 1 480 480 1 480 480 1 572 572 1 574 574 1 607 607 1 + 618 618 1 618 618 1 627 627 1 629 629 0 629 629 1 633 633 1 + 634 634 1 652 652 1 660 660 1 667 667 0 667 667 1 670 670 1 + 671 671 1 683 683 1 705 705 1 711 711 1 716 716 1 726 726 1 + 730 730 1 759 759 1 762 762 1 768 768 1 768 768 1 777 777 1 + 786 786 1 790 790 1 792 792 1 794 794 1 805 805 1 822 822 1 + 839 839 1 839 839 1 840 840 1 844 844 1 845 845 1 870 870 0 + 870 870 1 870 870 1 899 899 1 911 911 1 929 929 1 934 934 1 + 938 938 1 938 938 1 959 959 1 963 963 1 979 979 1} + +do_execsql_test 5.4.10.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( PARTITION BY coalesce(a, '') + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 {} 1 1 + 113 1 1 113 1 1 133 1 1 223 1 1 239 1 1 247 1 1 257 1 1 + 295 1 1 309 1 1 335 1 1 355 1 1 355 1 1 393 1 1 393 1 1 + 399 1 1 399 1 1 421 1 1 443 1 1 607 1 1 627 1 1 629 1 1 + 629 1 1 633 1 1 667 1 1 667 1 1 671 1 1 683 1 1 705 1 1 + 711 1 1 759 1 1 777 1 1 805 1 1 839 1 1 839 1 1 845 1 1 + 899 1 1 911 1 1 929 1 1 959 1 1 963 1 1 979 1 1} + +do_execsql_test 5.4.11.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {223 223 1 239 239 1 309 309 1 572 572 1 627 627 1 870 870 1 + 911 911 1 934 158 22 934 158 28 934 158 28 934 158 28 934 158 28 + 934 158 28 934 158 28 934 223 9 934 223 9 934 223 9 934 223 9 + 934 223 9 934 223 9 934 223 9 934 223 9 934 223 9 934 223 9 + 934 223 9 934 223 9 934 223 9 934 223 22 934 223 22 934 223 22 + 934 223 22 934 223 22 934 934 1 959 102 40 959 102 51 959 102 51 + 959 102 51 959 102 51 959 102 51 959 102 51 959 102 51 959 102 51 + 959 102 51 959 102 51 959 102 51 959 102 51 959 102 51 959 102 51 + 959 102 51 959 113 35 959 113 40 959 113 40 959 113 40 959 113 40 + 959 113 40 959 113 40 959 113 40 959 113 40 959 113 40 959 113 40 + 959 158 28 959 158 35 959 158 35 959 158 35 959 158 35 963 102 51 + 979 102 47 979 102 47 979 102 47 979 102 47 979 102 47 979 102 47 + 979 102 47 979 102 48 979 102 48 979 102 48 979 102 48 979 102 48 + 979 102 48 979 102 48 979 102 48 979 102 48 979 102 49 979 102 49 + 979 102 49 979 102 49 979 102 49 979 102 49 979 102 51} + +do_execsql_test 5.4.11.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY a NULLS LAST GROUPS 6 PRECEDING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 1 1 {} 1 1 223 1 1 239 1 1 309 1 1 627 1 1 911 1 1 + 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2309 9 2 2556 9 2 + 2702 9 2 2702 9 2 2708 9 2 2942 9 2 3014 9 2 3020 9 2 5790 22 3 + 5790 22 3 5790 22 3 5790 22 3 6397 22 3 6549 22 3 7156 28 4 + 7156 28 4 7156 28 4 7156 28 4 7156 28 4 8001 28 4 8115 28 4 + 8960 35 5 8960 35 5 9073 35 5 9589 35 5 9737 35 5 10028 68 9 + 10028 68 9 10028 68 9 10396 59 8 10396 59 8 10396 59 8 10396 59 8 + 10449 68 9 10471 68 9 10479 40 6 10479 40 6 10479 40 6 10479 40 6 + 10479 40 6 10479 40 6 10479 40 6 10479 40 6 10479 40 6 10529 59 8 + 10699 68 9 10751 59 8 10774 40 6 10833 68 9 11002 75 10 + 11002 75 10 11002 75 10 11002 75 10 11079 59 8 11115 75 10 + 11146 40 6 11259 75 10 11359 59 8 11375 59 8 11441 51 7 + 11441 51 7 11441 51 7 11441 51 7 11441 51 7 11441 51 7 11776 51 7 + 11841 75 10 11841 75 10 11901 75 10 12145 84 11 12145 84 11 + 12370 51 7 12500 84 11 12544 84 11 12774 84 11 12812 84 11} + +do_execsql_test 5.4.12.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 160 158 1 + 160 158 2 160 158 2 208 208 1 224 223 2 224 223 2 239 234 3 + 239 234 3 239 234 3 252 247 3 257 247 5 257 247 5 257 250 4 + 257 252 3 295 295 1 309 309 1 336 330 3 336 330 3 336 330 3 + 346 346 1 355 354 1 355 354 2 355 354 2 399 393 3 399 393 3 + 399 393 3 399 393 4 399 393 4 412 412 1 421 421 1 430 430 1 + 443 443 1 480 480 1 480 480 1 574 572 2 574 572 2 607 607 1 + 618 618 1 618 618 1 634 627 3 634 627 4 634 627 4 634 627 4 + 634 629 3 652 652 1 667 660 2 671 667 2 671 667 3 671 667 3 + 671 667 3 683 683 1 711 705 2 716 705 3 716 711 2 730 726 2 + 730 726 2 762 759 2 768 759 4 768 762 2 768 762 2 777 777 1 + 792 786 3 794 786 4 794 786 4 794 790 3 805 805 1 822 822 1 + 845 839 4 845 839 4 845 839 5 845 839 5 845 839 5 870 870 0 + 870 870 1 870 870 1 899 899 1 911 911 1 934 929 2 938 929 4 + 938 934 2 938 934 2 963 959 2 963 959 2 979 979 1} + +do_execsql_test 5.4.12.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 6 PRECEDING AND 7 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 25 23 {} 34 29 + {} 36 31 {} 38 33 {} 38 33 {} 40 34 {} 41 35 {} 43 37 {} 43 37 + {} 50 42 {} 60 51 {} 61 52 {} 64 55 {} 64 55 {} 67 57 {} 68 58 + {} 69 59 {} 70 60 {} 72 62 {} 78 67 {} 78 67 {} 78 67 {} 85 72 + {} 85 72 113 2 2 113 2 2 133 4 3 223 10 8 223 11 9 239 12 10 + 239 13 11 239 14 12 247 15 13 257 18 16 257 19 17 295 20 18 + 309 21 19 335 22 20 335 23 21 335 24 22 355 27 25 355 27 25 + 421 35 30 443 37 32 504 16 14 504 17 15 607 42 36 683 56 47 + 710 26 24 711 59 50 759 62 53 759 63 54 777 66 56 805 71 61 + 899 81 68 911 82 69 929 83 70 929 84 71 979 89 75 1185 32 28 + 1185 32 28 1191 29 26 1191 29 26 1334 51 43 1338 52 44 1338 52 44 + 1416 57 48 1416 58 49 1584 31 27 1684 73 63 1684 73 63 1889 46 39 + 1889 46 39 1891 49 41 1922 87 73 1922 88 74 2005 54 45 2005 55 46 + 2518 45 38 2518 48 40 2523 75 64 2523 76 65 2523 77 66} + +do_execsql_test 5.4.13.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {102 102 1 113 113 1 113 113 1 133 133 1 148 148 1 158 158 0 + 158 158 1 160 160 1 208 208 1 223 223 1 224 224 1 234 234 1 + 238 238 1 239 239 1 247 247 1 250 250 1 252 252 1 256 256 1 + 257 257 1 295 295 1 309 309 1 330 330 1 335 335 1 336 336 1 + 346 346 1 354 354 1 355 355 0 355 355 1 393 393 1 393 393 1 + 398 398 1 399 399 0 399 399 1 412 412 1 421 421 1 430 430 1 + 443 443 1 480 480 1 480 480 1 572 572 1 574 574 1 607 607 1 + 618 618 1 618 618 1 627 627 1 629 629 0 629 629 1 633 633 1 + 634 634 1 652 652 1 660 660 1 667 667 0 667 667 1 670 670 1 + 671 671 1 683 683 1 705 705 1 711 711 1 716 716 1 726 726 1 + 730 730 1 759 759 1 762 762 1 768 768 1 768 768 1 777 777 1 + 786 786 1 790 790 1 792 792 1 794 794 1 805 805 1 822 822 1 + 839 839 1 839 839 1 840 840 1 844 844 1 845 845 1 870 870 0 + 870 870 1 870 870 1 899 899 1 911 911 1 929 929 1 934 934 1 + 938 938 1 938 938 1 959 959 1 963 963 1 979 979 1} + +do_execsql_test 5.4.13.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST RANGE BETWEEN 0 PRECEDING AND 0 FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {{} 1 1 {} 5 4 {} 6 5 {} 6 5 {} 8 6 {} 9 7 {} 11 9 {} 12 10 + {} 13 11 {} 16 14 {} 17 15 {} 18 16 {} 22 20 {} 24 22 {} 25 23 + {} 26 24 {} 31 27 {} 34 29 {} 36 31 {} 38 33 {} 38 33 {} 40 34 + {} 41 35 {} 43 37 {} 43 37 {} 49 41 {} 50 42 {} 51 43 {} 54 45 + {} 59 50 {} 60 51 {} 61 52 {} 63 54 {} 64 55 {} 64 55 {} 67 57 + {} 68 58 {} 69 59 {} 70 60 {} 72 62 {} 75 64 {} 76 65 {} 78 67 + {} 78 67 {} 78 67 {} 84 71 {} 85 72 {} 85 72 113 2 2 113 2 2 + 133 4 3 223 10 8 239 14 12 247 15 13 257 19 17 295 20 18 + 309 21 19 335 23 21 355 27 25 355 27 25 393 29 26 393 29 26 + 399 32 28 399 32 28 421 35 30 443 37 32 607 42 36 627 45 38 + 629 46 39 629 46 39 633 48 40 667 52 44 667 52 44 671 55 46 + 683 56 47 705 57 48 711 58 49 759 62 53 777 66 56 805 71 61 + 839 73 63 839 73 63 845 77 66 899 81 68 911 82 69 929 83 70 + 959 87 73 963 88 74 979 89 75} + +do_execsql_test 5.4.14.1 { + SELECT max(c) OVER win, + min(c) OVER win, + count(a) OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST +} {979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 979 102 83 + 979 102 83 979 113 81 979 113 82 979 133 80 979 148 79 979 158 77 + 979 158 78 979 160 77 979 208 76 979 223 75 979 224 74 979 234 73 + 979 238 72 979 239 71 979 247 70 979 250 69 979 252 68 979 256 67 + 979 257 66 979 295 65 979 309 64 979 330 63 979 335 62 979 336 61 + 979 346 60 979 354 59 979 355 57 979 355 58 979 393 56 979 393 57 + 979 398 55 979 399 53 979 399 54 979 412 53 979 421 52 979 430 51 + 979 443 50 979 480 48 979 480 49 979 572 47 979 574 46 979 607 45 + 979 618 43 979 618 44 979 627 42 979 629 40 979 629 41 979 633 40 + 979 634 39 979 652 38 979 660 37 979 667 35 979 667 36 979 670 35 + 979 671 34 979 683 33 979 705 32 979 711 31 979 716 30 979 726 29 + 979 730 28 979 759 27 979 762 26 979 768 24 979 768 25 979 777 23 + 979 786 22 979 790 21 979 792 20 979 794 19 979 805 18 979 822 17 + 979 839 15 979 839 16 979 840 14 979 844 13 979 845 12 979 870 9 + 979 870 10 979 870 11 979 899 9 979 911 8 979 929 7} + +do_execsql_test 5.4.14.2 { + SELECT sum(c) FILTER (WHERE (c%2)!=0) OVER win, + rank() OVER win, + dense_rank() OVER win + FROM t3 + WINDOW win AS ( ORDER BY c NULLS LAST, b NULLS LAST, a NULLS LAST + ROWS BETWEEN 6 PRECEDING AND UNBOUNDED FOLLOWING EXCLUDE TIES ) + ORDER BY 1 NULLS FIRST, 2 NULLS FIRST, 3 NULLS FIRST } {3830 89 89 4741 88 88 5640 84 84 5640 85 85 5640 86 86 5640 87 87 6485 81 81 6485 82 82 6485 83 83 7324 80 80 8163 78 78 8163 79 79 8968 73 73 8968 74 74 8968 75 75 8968 76 76 8968 77 77 9745 69 69 @@ -4860,16 +6191,282 @@ do_execsql_test 6.0 { do_execsql_test 6.1 { SELECT group_concat(a, '.') OVER ( - ORDER BY b RANGE BETWEEN 7 PRECEDING AND 2 PRECEDING + ORDER BY b NULLS FIRST RANGE BETWEEN 7 PRECEDING AND 2 PRECEDING ) FROM t2 } {A.B A.B {}} do_execsql_test 6.2 { SELECT group_concat(a, '.') OVER ( - ORDER BY b DESC RANGE BETWEEN 7 PRECEDING AND 2 PRECEDING + ORDER BY b DESC NULLS LAST RANGE BETWEEN 7 PRECEDING AND 2 PRECEDING ) FROM t2 } {{} A.B A.B} +#========================================================================== + +do_execsql_test 7.0 { + DROP TABLE IF EXISTS t2; + CREATE TABLE t2(a INTEGER, b INTEGER); + + INSERT INTO t2 VALUES(1, 65); + INSERT INTO t2 VALUES(2, NULL); + INSERT INTO t2 VALUES(3, NULL); + INSERT INTO t2 VALUES(4, NULL); + INSERT INTO t2 VALUES(5, 66); + INSERT INTO t2 VALUES(6, 67); +} {} + +do_execsql_test 7.1.1 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING + ); +} {9 9 9 9 9 9} + +do_execsql_test 7.1.2 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {{} {} {} 9 9 9} + +do_execsql_test 7.1.3 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {{} {} {} 9 9 9} + +do_execsql_test 7.1.4 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.1.5 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.1.6 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING + ); +} {{} {} 1 9 9 9} + +do_execsql_test 7.1.7 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {{} {} {} 9 9 9} + +do_execsql_test 7.1.8 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.1.9 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.2.1 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING + ); +} {2 2 2 2 2 2} + +do_execsql_test 7.2.2 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {{} {} {} 2 2 2} + +do_execsql_test 7.2.3 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {{} {} {} 2 2 2} + +do_execsql_test 7.2.4 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {2 2 2 {} {} {}} + +do_execsql_test 7.2.5 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {2 2 2 {} {} {}} + +do_execsql_test 7.2.6 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING + ); +} {{} {} 1 2 2 2} + +do_execsql_test 7.2.7 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {{} {} {} 2 2 2} + +do_execsql_test 7.2.8 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING + ); +} {2 2 2 {} {} {}} + +do_execsql_test 7.2.9 { + SELECT min (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {2 2 2 {} {} {}} + +do_execsql_test 7.3.1 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING + ); +} {9 9 9 9 9 9} + +do_execsql_test 7.3.2 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {{} {} {} 9 9 9} + +do_execsql_test 7.3.3 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {{} {} {} 9 9 9} + +do_execsql_test 7.3.4 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.3.5 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.3.6 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING + ); +} {{} {} 1 9 9 9} + +do_execsql_test 7.3.7 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {{} {} {} 9 9 9} + +do_execsql_test 7.3.8 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.3.9 { + SELECT sum (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {9 9 9 {} {} {}} + +do_execsql_test 7.4.1 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 6 FOLLOWING AND UNBOUNDED FOLLOWING + ); +} {4 4 4 4 4 4} + +do_execsql_test 7.4.2 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {{} {} {} 4 4 4} + +do_execsql_test 7.4.3 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {{} {} {} 4 4 4} + +do_execsql_test 7.4.4 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING + ); +} {4 4 4 {} {} {}} + +do_execsql_test 7.4.5 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2 FOLLOWING AND 1 FOLLOWING + ); +} {4 4 4 {} {} {}} + +do_execsql_test 7.4.6 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 1000 PRECEDING AND 2 PRECEDING + ); +} {{} {} 1 4 4 4} + +do_execsql_test 7.4.7 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS LAST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {{} {} {} 4 4 4} + +do_execsql_test 7.4.8 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 1000 PRECEDING AND 2000 PRECEDING + ); +} {4 4 4 {} {} {}} + +do_execsql_test 7.4.9 { + SELECT max (a) OVER win FROM t2 + WINDOW win AS ( + ORDER BY b NULLS FIRST RANGE BETWEEN 2000 FOLLOWING AND 1000 FOLLOWING + ); +} {4 4 4 {} {} {}} + finish_test diff --git a/test/window9.test b/test/window9.test index cf4d83ae8e..d79e5f3d00 100644 --- a/test/window9.test +++ b/test/window9.test @@ -171,6 +171,29 @@ foreach {tn sql} { } {~/ORDER/} } +#------------------------------------------------------------------------- +reset_db +do_execsql_test 6.0 { + CREATE TABLE t0(c0); + INSERT INTO t0(c0) VALUES (0); +} + +do_execsql_test 6.1 { + SELECT * FROM t0 WHERE + EXISTS ( + SELECT MIN(c0) OVER (), CUME_DIST() OVER () FROM t0 + ) >=1 AND + EXISTS ( + SELECT MIN(c0) OVER (), CUME_DIST() OVER () FROM t0 + ) <=1; +} {0} + +do_execsql_test 6.2 { + SELECT * FROM t0 WHERE EXISTS ( + SELECT MIN(c0) OVER (), CUME_DIST() OVER () FROM t0 + ) + BETWEEN 1 AND 1; +} {0} finish_test diff --git a/test/windowA.test b/test/windowA.test new file mode 100644 index 0000000000..e94ae57e43 --- /dev/null +++ b/test/windowA.test @@ -0,0 +1,309 @@ +# 2019-08-30 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# Test cases for RANGE BETWEEN and especially with NULLS LAST +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix windowA + +ifcapable !windowfunc { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b CHAR(1), d FLOAT); + INSERT INTO t1 VALUES + (1, 'A', 5.4), + (2, 'B', 5.55), + (3, 'C', 8.0), + (4, 'D', 10.25), + (5, 'E', 10.26), + (6, 'N', NULL), + (7, 'N', NULL); +} {} + +do_execsql_test 1.1 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN 2.50 PRECEDING AND 2.25 FOLLOWING) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 ED \ + 4 D 10.25 EDC \ + 3 C 8.0 EDC \ + 2 B 5.55 CBA \ + 1 A 5.4 BA \ + 6 N NULL NN \ + 7 N NULL NN \ +] + +do_execsql_test 1.2 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN 2.50 PRECEDING AND 2.25 FOLLOWING) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NN \ + 7 N NULL NN \ + 5 E 10.26 ED \ + 4 D 10.25 EDC \ + 3 C 8.0 EDC \ + 2 B 5.55 CBA \ + 1 A 5.4 BA \ +] + +do_execsql_test 1.3 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN 2.50 PRECEDING AND UNBOUNDED FOLLOWING) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 EDCBANN \ + 4 D 10.25 EDCBANN \ + 3 C 8.0 EDCBANN \ + 2 B 5.55 CBANN \ + 1 A 5.4 BANN \ + 6 N NULL NN \ + 7 N NULL NN \ +] + +do_execsql_test 1.4 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN 2.50 PRECEDING AND UNBOUNDED FOLLOWING) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NNEDCBA \ + 7 N NULL NNEDCBA \ + 5 E 10.26 EDCBA \ + 4 D 10.25 EDCBA \ + 3 C 8.0 EDCBA \ + 2 B 5.55 CBA \ + 1 A 5.4 BA \ +] + +do_execsql_test 1.5 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN 2.50 PRECEDING AND CURRENT ROW) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 E \ + 4 D 10.25 ED \ + 3 C 8.0 EDC \ + 2 B 5.55 CB \ + 1 A 5.4 BA \ + 6 N NULL NN \ + 7 N NULL NN \ +] + +do_execsql_test 1.6 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN 2.50 PRECEDING AND CURRENT ROW) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NN \ + 7 N NULL NN \ + 5 E 10.26 E \ + 4 D 10.25 ED \ + 3 C 8.0 EDC \ + 2 B 5.55 CB \ + 1 A 5.4 BA \ +] + +do_execsql_test 2.1 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN UNBOUNDED PRECEDING AND 2.25 FOLLOWING) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 ED \ + 4 D 10.25 EDC \ + 3 C 8.0 EDC \ + 2 B 5.55 EDCBA \ + 1 A 5.4 EDCBA \ + 6 N NULL EDCBANN \ + 7 N NULL EDCBANN \ +] + +do_execsql_test 2.2 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN UNBOUNDED PRECEDING AND 2.25 FOLLOWING) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NN \ + 7 N NULL NN \ + 5 E 10.26 NNED \ + 4 D 10.25 NNEDC \ + 3 C 8.0 NNEDC \ + 2 B 5.55 NNEDCBA \ + 1 A 5.4 NNEDCBA \ +] + +do_execsql_test 2.3 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 EDCBANN \ + 4 D 10.25 EDCBANN \ + 3 C 8.0 EDCBANN \ + 2 B 5.55 EDCBANN \ + 1 A 5.4 EDCBANN \ + 6 N NULL EDCBANN \ + 7 N NULL EDCBANN \ +] + +do_execsql_test 2.4 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NNEDCBA \ + 7 N NULL NNEDCBA \ + 5 E 10.26 NNEDCBA \ + 4 D 10.25 NNEDCBA \ + 3 C 8.0 NNEDCBA \ + 2 B 5.55 NNEDCBA \ + 1 A 5.4 NNEDCBA \ +] + +do_execsql_test 2.5 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 E \ + 4 D 10.25 ED \ + 3 C 8.0 EDC \ + 2 B 5.55 EDCB \ + 1 A 5.4 EDCBA \ + 6 N NULL EDCBANN \ + 7 N NULL EDCBANN \ +] + +do_execsql_test 2.6 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NN \ + 7 N NULL NN \ + 5 E 10.26 NNE \ + 4 D 10.25 NNED \ + 3 C 8.0 NNEDC \ + 2 B 5.55 NNEDCB \ + 1 A 5.4 NNEDCBA \ +] + + +do_execsql_test 3.1 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN CURRENT ROW AND 2.25 FOLLOWING) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 ED \ + 4 D 10.25 DC \ + 3 C 8.0 C \ + 2 B 5.55 BA \ + 1 A 5.4 A \ + 6 N NULL NN \ + 7 N NULL NN \ +] + +do_execsql_test 3.2 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN CURRENT ROW AND 2.25 FOLLOWING) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NN \ + 7 N NULL NN \ + 5 E 10.26 ED \ + 4 D 10.25 DC \ + 3 C 8.0 C \ + 2 B 5.55 BA \ + 1 A 5.4 A \ +] + +do_execsql_test 3.3 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS LAST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + ORDER BY +d DESC NULLS LAST, +a; +} [list \ + 5 E 10.26 EDCBANN \ + 4 D 10.25 DCBANN \ + 3 C 8.0 CBANN \ + 2 B 5.55 BANN \ + 1 A 5.4 ANN \ + 6 N NULL NN \ + 7 N NULL NN \ +] + +do_execsql_test 3.4 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NNEDCBA \ + 7 N NULL NNEDCBA \ + 5 E 10.26 EDCBA \ + 4 D 10.25 DCBA \ + 3 C 8.0 CBA \ + 2 B 5.55 BA \ + 1 A 5.4 A \ +] + +do_execsql_test 4.0 { + SELECT a, b, quote(d), group_concat(b,'') OVER w1 FROM t1 + WINDOW w1 AS + (ORDER BY d DESC NULLS FIRST + RANGE BETWEEN 2.50 PRECEDING AND 0.5 PRECEDING) + ORDER BY +d DESC NULLS FIRST, +a; +} [list \ + 6 N NULL NN \ + 7 N NULL NN \ + 5 E 10.26 {} \ + 4 D 10.25 {} \ + 3 C 8.0 ED \ + 2 B 5.55 C \ + 1 A 5.4 {} \ +] + + +finish_test diff --git a/test/windowB.test b/test/windowB.test new file mode 100644 index 0000000000..d28ee0da19 --- /dev/null +++ b/test/windowB.test @@ -0,0 +1,233 @@ +# 2019-08-30 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# Test cases for RANGE BETWEEN and especially with NULLS LAST +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix windowB + +ifcapable !windowfunc { + finish_test + return +} + +do_execsql_test 1.0 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(NULL, 1); + INSERT INTO t1 VALUES(NULL, 2); + INSERT INTO t1 VALUES(NULL, 3); +} {} + +foreach {tn win} { + 1 { ORDER BY a RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING } + 2 { ORDER BY a NULLS LAST RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING } + 3 { ORDER BY a DESC RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING } + 4 { ORDER BY a DESC NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING } + + 5 { ORDER BY a NULLS LAST RANGE BETWEEN 1 FOLLOWING AND 2 FOLLOWING } + 6 { ORDER BY a DESC NULLS FIRST RANGE BETWEEN 1 FOLLOWING AND 2 FOLLOWING } + + 7 { ORDER BY a NULLS LAST RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING } + 8 { ORDER BY a DESC NULLS FIRST RANGE BETWEEN 2 PRECEDING AND 1 PRECEDING } +} { + do_execsql_test 1.$tn " + SELECT sum(b) OVER win FROM t1 + WINDOW win AS ( $win ) + " {6 6 6} +} + +do_execsql_test 1.2 { + SELECT sum(b) OVER win FROM t1 + WINDOW win AS ( + ORDER BY a DESC NULLS FIRST RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) +} {6 6 6} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 2.0 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(1, NULL); + INSERT INTO t1 VALUES(2, 45); + INSERT INTO t1 VALUES(3, 66.2); + INSERT INTO t1 VALUES(4, 'hello world'); + INSERT INTO t1 VALUES(5, 'hello world'); + INSERT INTO t1 VALUES(6, X'1234'); + INSERT INTO t1 VALUES(7, X'1234'); + INSERT INTO t1 VALUES(8, NULL); +} + +foreach {tn win} { + 1 "ORDER BY b RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING" + 2 "ORDER BY b RANGE BETWEEN 2 FOLLOWING AND 2 FOLLOWING" + 3 "ORDER BY b NULLS LAST RANGE BETWEEN 1 PRECEDING AND 2 PRECEDING" + 4 "ORDER BY b NULLS LAST RANGE BETWEEN 2 FOLLOWING AND 2 FOLLOWING" +} { + do_execsql_test 2.1.$tn " + SELECT a, sum(a) OVER win FROM t1 + WINDOW win AS ( $win ) + ORDER BY 1 + " {1 9 2 {} 3 {} 4 9 5 9 6 13 7 13 8 9} +} + +#------------------------------------------------------------------------- +ifcapable json1 { + reset_db + do_execsql_test 3.0 { + CREATE TABLE testjson(id INTEGER PRIMARY KEY, j TEXT, x TEXT); + INSERT INTO testjson VALUES(1, '{"a":1}', 'a'); + INSERT INTO testjson VALUES(2, '{"b":2}', 'b'); + INSERT INTO testjson VALUES(3, '{"c":3}', 'c'); + INSERT INTO testjson VALUES(4, '{"d":4}', 'd'); + } + + do_execsql_test 3.1 { + SELECT json_group_array(json(j)) FROM testjson; + } { + {[{"a":1},{"b":2},{"c":3},{"d":4}]} + } + + do_execsql_test 3.2 { + SELECT json_group_array(json(j)) OVER (ORDER BY id) FROM testjson; + } { + {[{"a":1}]} + {[{"a":1},{"b":2}]} + {[{"a":1},{"b":2},{"c":3}]} + {[{"a":1},{"b":2},{"c":3},{"d":4}]} + } + + do_execsql_test 3.3 { + SELECT json_group_array(json(j)) OVER ( + ORDER BY id RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + EXCLUDE TIES + ) FROM testjson; + } { + {[{"a":1}]} + {[{"a":1},{"b":2}]} + {[{"a":1},{"b":2},{"c":3}]} + {[{"a":1},{"b":2},{"c":3},{"d":4}]} + } + + do_execsql_test 3.4 { + SELECT json_group_array(json(j)) OVER ( + ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING + ) FROM testjson; + } { + {[{"a":1},{"b":2}]} + {[{"a":1},{"b":2},{"c":3}]} + {[{"b":2},{"c":3},{"d":4}]} + {[{"c":3},{"d":4}]} + } + + do_execsql_test 3.5 { + SELECT json_group_array(json(j)) OVER ( + ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING + ) FROM testjson; + } { + {[]} + {[{"a":1}]} + {[{"a":1},{"b":2}]} + {[{"b":2},{"c":3}]} + } + + do_execsql_test 3.5a { + UPDATE testjson SET j = replace(j,char(125),',"e":9'||char(125)); + SELECT j FROM testjson; + } { + {{"a":1,"e":9}} + {{"b":2,"e":9}} + {{"c":3,"e":9}} + {{"d":4,"e":9}} + } + do_execsql_test 3.5b { + SELECT group_concat(x,'') OVER ( + ORDER BY id ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING + ) FROM testjson ORDER BY id; + } {bc cd d {}} + do_execsql_test 3.5c { + SELECT json_group_array(json(j)) OVER ( + ORDER BY id ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING + ) FROM testjson; + } { + {[{"b":2,"e":9},{"c":3,"e":9}]} + {[{"c":3,"e":9},{"d":4,"e":9}]} + {[{"d":4,"e":9}]} + {[]} + } + do_execsql_test 3.5d { + SELECT json_group_object(x,json(j)) OVER ( + ORDER BY id ROWS BETWEEN 1 FOLLOWING AND 2 FOLLOWING + ) FROM testjson; + } { + {{"b":{"b":2,"e":9},"c":{"c":3,"e":9}}} + {{"c":{"c":3,"e":9},"d":{"d":4,"e":9}}} + {{"d":{"d":4,"e":9}}} + {{}} + } + + do_execsql_test 3.7b { + SELECT group_concat(x,'') FILTER (WHERE id!=2) OVER ( + ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING + ) FROM testjson; + } {{} a a c} + + do_execsql_test 3.7c { + SELECT json_group_array(json(j)) FILTER (WHERE id!=2) OVER ( + ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING + ) FROM testjson + } { + {[]} + {[{"a":1,"e":9}]} + {[{"a":1,"e":9}]} + {[{"c":3,"e":9}]} + } + do_execsql_test 3.7d { + SELECT json_group_object(x,json(j)) FILTER (WHERE id!=2) OVER ( + ORDER BY id ROWS BETWEEN 2 PRECEDING AND 1 PRECEDING + ) FROM testjson + } { + {{}} + {{"a":{"a":1,"e":9}}} + {{"a":{"a":1,"e":9}}} + {{"c":{"c":3,"e":9}}} + } +} + +#------------------------------------------------------------------------- +reset_db +do_execsql_test 4.0 { + CREATE TABLE x(a); + INSERT INTO x VALUES(1); + INSERT INTO x VALUES(2); +} + +do_execsql_test 4.1 { + WITH y AS ( + SELECT Row_Number() OVER (win) FROM x WINDOW win AS (PARTITION BY a) + ) + SELECT * FROM y; +} { + 1 1 +} + +do_catchsql_test 4.2 { + WITH y AS ( + SELECT Row_Number() OVER (win) FROM x WINDOW win AS (PARTITION + BY fake_column)) + SELECT * FROM y; +} {1 {no such column: fake_column}} + +do_catchsql_test 4.3 { + SELECT 1 WINDOW win AS (PARTITION BY fake_column); +} {0 1} + +finish_test diff --git a/test/windowfault.test b/test/windowfault.test index 41c4bb6ad0..e037c467b0 100644 --- a/test/windowfault.test +++ b/test/windowfault.test @@ -224,4 +224,26 @@ do_faultsim_test 9 -end 25 -faults tmpread -body { catch {db close} tvfs delete +reset_db +do_execsql_test 10.0 { + CREATE TABLE t1(a, b, c, d); + CREATE TABLE t2(a, b, c, d); +} + +do_faultsim_test 1 -faults oom* -prep { +} -body { + execsql { + SELECT row_number() OVER win + FROM t1 + WINDOW win AS ( + ORDER BY ( + SELECT percent_rank() OVER win2 FROM t2 + WINDOW win2 AS (ORDER BY a) + ) + ) + } +} -test { + faultsim_test_result {0 {}} +} + finish_test diff --git a/tool/lemon.c b/tool/lemon.c index 4416f67bb2..6efc6af301 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -4153,6 +4153,7 @@ void ReportTable( struct rule *rp; struct acttab *pActtab; int i, j, n, sz; + int nLookAhead; int szActionType; /* sizeof(YYACTIONTYPE) */ int szCodeType; /* sizeof(YYCODETYPE) */ const char *name; @@ -4403,13 +4404,29 @@ void ReportTable( if( la<0 ) la = lemp->nsymbol; if( j==0 ) fprintf(out," /* %5d */ ", i); fprintf(out, " %4d,", la); - if( j==9 || i==n-1 ){ + if( j==9 ){ fprintf(out, "\n"); lineno++; j = 0; }else{ j++; } } + /* Add extra entries to the end of the yy_lookahead[] table so that + ** yy_shift_ofst[]+iToken will always be a valid index into the array, + ** even for the largest possible value of yy_shift_ofst[] and iToken. */ + nLookAhead = lemp->nterminal + lemp->nactiontab; + while( interminal); + if( j==9 ){ + fprintf(out, "\n"); lineno++; + j = 0; + }else{ + j++; + } + i++; + } + if( j>0 ){ fprintf(out, "\n"); lineno++; } fprintf(out, "};\n"); lineno++; /* Output the yy_shift_ofst[] table */ @@ -4489,7 +4506,9 @@ void ReportTable( */ if( lemp->has_fallback ){ int mx = lemp->nterminal - 1; - while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; } + /* 2019-08-28: Generate fallback entries for every token to avoid + ** having to do a range check on the index */ + /* while( mx>0 && lemp->symbols[mx]->fallback==0 ){ mx--; } */ lemp->tablesize += (mx+1)*szCodeType; for(i=0; i<=mx; i++){ struct symbol *p = lemp->symbols[i]; diff --git a/tool/lempar.c b/tool/lempar.c index 1c088080d4..f75ad51c39 100644 --- a/tool/lempar.c +++ b/tool/lempar.c @@ -521,15 +521,18 @@ static YYACTIONTYPE yy_find_shift_action( do{ i = yy_shift_ofst[stateno]; assert( i>=0 ); - /* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */ + assert( i<=YY_ACTTAB_COUNT ); + assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); assert( iLookAhead!=YYNOCODE ); assert( iLookAhead < YYNTOKEN ); i += iLookAhead; - if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){ + assert( i<(int)YY_NLOOKAHEAD ); + if( yy_lookahead[i]!=iLookAhead ){ #ifdef YYFALLBACK YYCODETYPE iFallback; /* Fallback token */ - if( iLookAhead %s\n", @@ -544,16 +547,8 @@ static YYACTIONTYPE yy_find_shift_action( #ifdef YYWILDCARD { int j = i - iLookAhead + YYWILDCARD; - if( -#if YY_SHIFT_MIN+YYWILDCARD<0 - j>=0 && -#endif -#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT - j0 - ){ + assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) ); + if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){ #ifndef NDEBUG if( yyTraceFILE ){ fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", @@ -1069,9 +1064,8 @@ void Parse( */ int ParseFallback(int iToken){ #ifdef YYFALLBACK - if( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ){ - return yyFallback[iToken]; - } + assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ); + return yyFallback[iToken]; #else (void)iToken; #endif diff --git a/tool/mkkeywordhash.c b/tool/mkkeywordhash.c index ece8b63e19..77bc4ac5c0 100644 --- a/tool/mkkeywordhash.c +++ b/tool/mkkeywordhash.c @@ -210,6 +210,7 @@ static Keyword aKeywordTable[] = { { "EXPLAIN", "TK_EXPLAIN", EXPLAIN }, { "FAIL", "TK_FAIL", CONFLICT|TRIGGER }, { "FILTER", "TK_FILTER", WINDOWFUNC }, + { "FIRST", "TK_FIRST", ALWAYS }, { "FOLLOWING", "TK_FOLLOWING", WINDOWFUNC }, { "FOR", "TK_FOR", TRIGGER }, { "FOREIGN", "TK_FOREIGN", FKEY }, @@ -235,6 +236,7 @@ static Keyword aKeywordTable[] = { { "ISNULL", "TK_ISNULL", ALWAYS }, { "JOIN", "TK_JOIN", ALWAYS }, { "KEY", "TK_KEY", ALWAYS }, + { "LAST", "TK_LAST", ALWAYS }, { "LEFT", "TK_JOIN_KW", ALWAYS }, { "LIKE", "TK_LIKE_KW", ALWAYS }, { "LIMIT", "TK_LIMIT", ALWAYS }, @@ -245,6 +247,7 @@ static Keyword aKeywordTable[] = { { "NOTHING", "TK_NOTHING", UPSERT }, { "NOTNULL", "TK_NOTNULL", ALWAYS }, { "NULL", "TK_NULL", ALWAYS }, + { "NULLS", "TK_NULLS", ALWAYS }, { "OF", "TK_OF", ALWAYS }, { "OFFSET", "TK_OFFSET", ALWAYS }, { "ON", "TK_ON", ALWAYS }, diff --git a/tool/mkpragmatab.tcl b/tool/mkpragmatab.tcl index f2e12ab9d3..cda9f36f52 100644 --- a/tool/mkpragmatab.tcl +++ b/tool/mkpragmatab.tcl @@ -264,19 +264,19 @@ set pragma_def { FLAG: Result0 COLS: name builtin IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) - IF: defined(SQLITE_INTROSPECTION_PRAGMAS) + IF: !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) NAME: module_list FLAG: Result0 COLS: name IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS) IF: !defined(SQLITE_OMIT_VIRTUALTABLE) - IF: defined(SQLITE_INTROSPECTION_PRAGMAS) + IF: !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) NAME: pragma_list FLAG: Result0 COLS: name - IF: defined(SQLITE_INTROSPECTION_PRAGMAS) + IF: !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS) NAME: collation_list FLAG: Result0