From: dan Date: Sat, 2 May 2015 20:35:24 +0000 (+0000) Subject: Reorganize some of the fts5 expression parsing code. Improve test coverage of the... X-Git-Tag: version-3.8.11~114^2~50 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7c479d51e5ad209db5b9c3c8e6c456b33f09f7c1;p=thirdparty%2Fsqlite.git Reorganize some of the fts5 expression parsing code. Improve test coverage of the same. FossilOrigin-Name: c4456dc5f5f8f45f04e3bbae53b6bcc209fc27d5 --- diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h index 34190bdec1..07c3a767b2 100644 --- a/ext/fts5/fts5Int.h +++ b/ext/fts5/fts5Int.h @@ -228,6 +228,7 @@ int sqlite3Fts5PoslistNext64( /* Malloc utility */ void *sqlite3Fts5MallocZero(int *pRc, int nByte); +char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn); /* ** End of interface to code in fts5_buffer.c. diff --git a/ext/fts5/fts5_buffer.c b/ext/fts5/fts5_buffer.c index 26304f68aa..dbe51fafc4 100644 --- a/ext/fts5/fts5_buffer.c +++ b/ext/fts5/fts5_buffer.c @@ -239,5 +239,30 @@ void *sqlite3Fts5MallocZero(int *pRc, int nByte){ } return pRet; } + +/* +** Return a nul-terminated copy of the string indicated by pIn. If nIn +** is non-negative, then it is the length of the string in bytes. Otherwise, +** the length of the string is determined using strlen(). +** +** It is the responsibility of the caller to eventually free the returned +** buffer using sqlite3_free(). If an OOM error occurs, NULL is returned. +*/ +char *sqlite3Fts5Strndup(int *pRc, const char *pIn, int nIn){ + char *zRet = 0; + if( *pRc==SQLITE_OK ){ + if( nIn<0 ){ + nIn = strlen(pIn); + } + zRet = (char*)sqlite3_malloc(nIn+1); + if( zRet ){ + memcpy(zRet, pIn, nIn); + zRet[nIn] = '\0'; + }else{ + *pRc = SQLITE_NOMEM; + } + } + return zRet; +} #endif /* SQLITE_ENABLE_FTS5 */ diff --git a/ext/fts5/fts5_config.c b/ext/fts5/fts5_config.c index eae18dce27..1b29351ec2 100644 --- a/ext/fts5/fts5_config.c +++ b/ext/fts5/fts5_config.c @@ -203,21 +203,6 @@ void sqlite3Fts5Dequote(char *z){ } } -/* -** Duplicate the string passed as the only argument into a buffer allocated -** by sqlite3_malloc(). -** -** Return 0 if an OOM error is encountered. -*/ -static char *fts5Strdup(int *pRc, const char *z){ - char *pRet = 0; - if( *pRc==SQLITE_OK ){ - pRet = sqlite3_mprintf("%s", z); - if( pRet==0 ) *pRc = SQLITE_NOMEM; - } - return pRet; -} - /* ** Argument z points to a nul-terminated string containing an SQL identifier. ** This function returns a copy of the identifier enclosed in backtick @@ -368,7 +353,7 @@ static int fts5ConfigParseSpecial( *pzErr = sqlite3_mprintf("multiple content_rowid=... directives"); rc = SQLITE_ERROR; }else{ - pConfig->zContentRowid = fts5Strdup(&rc, zArg); + pConfig->zContentRowid = sqlite3Fts5Strndup(&rc, zArg, -1); } return rc; } @@ -526,8 +511,8 @@ int sqlite3Fts5ConfigParse( nByte = nArg * (sizeof(char*) + sizeof(u8)); pRet->azCol = (char**)sqlite3Fts5MallocZero(&rc, nByte); pRet->abUnindexed = (u8*)&pRet->azCol[nArg]; - pRet->zDb = fts5Strdup(&rc, azArg[1]); - pRet->zName = fts5Strdup(&rc, azArg[2]); + pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1); + pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1); if( rc==SQLITE_OK && sqlite3_stricmp(pRet->zName, FTS5_RANK_NAME)==0 ){ *pzErr = sqlite3_mprintf("reserved fts5 table name: %s", pRet->zName); rc = SQLITE_ERROR; @@ -591,7 +576,7 @@ int sqlite3Fts5ConfigParse( } } if( rc==SQLITE_OK && pRet->zContentRowid==0 ){ - pRet->zContentRowid = fts5Strdup(&rc, "rowid"); + pRet->zContentRowid = sqlite3Fts5Strndup(&rc, "rowid", -1); } /* Formulate the zContentExprlist text */ diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c index 79dfec5667..570331bfb1 100644 --- a/ext/fts5/fts5_expr.c +++ b/ext/fts5/fts5_expr.c @@ -231,33 +231,6 @@ int sqlite3Fts5ExprNew( return sParse.rc; } -static char *fts5ExprStrdup(int *pRc, const char *zIn){ - char *zRet = 0; - if( *pRc==SQLITE_OK ){ - int nByte = strlen(zIn) + 1; - zRet = sqlite3_malloc(nByte); - if( zRet ){ - memcpy(zRet, zIn, nByte); - }else{ - *pRc = SQLITE_NOMEM; - } - } - return zRet; -} - -static void *fts5ExprMalloc(int *pRc, int nByte){ - void *pRet = 0; - if( *pRc==SQLITE_OK ){ - pRet = sqlite3_malloc(nByte); - if( pRet ){ - memset(pRet, 0, nByte); - }else{ - *pRc = SQLITE_NOMEM; - } - } - return pRet; -} - /* ** Create a new FTS5 expression by cloning phrase iPhrase of the ** expression passed as the second argument. @@ -274,7 +247,7 @@ int sqlite3Fts5ExprPhraseExpr( Fts5Expr *pNew = 0; /* Expression to return via *ppNew */ pOrig = pExpr->apExprPhrase[iPhrase]; - pCopy = (Fts5ExprPhrase*)fts5ExprMalloc(&rc, + pCopy = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * pOrig->nTerm ); if( pCopy ){ @@ -283,15 +256,17 @@ int sqlite3Fts5ExprPhraseExpr( Fts5ExprNode *pNode; Fts5ExprNearset *pNear; - pNew = (Fts5Expr*)fts5ExprMalloc(&rc, sizeof(Fts5Expr)); - apPhrase = (Fts5ExprPhrase**)fts5ExprMalloc(&rc, sizeof(Fts5ExprPhrase*)); - pNode = (Fts5ExprNode*)fts5ExprMalloc(&rc, sizeof(Fts5ExprNode)); - pNear = (Fts5ExprNearset*)fts5ExprMalloc(&rc, + pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr)); + apPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc, + sizeof(Fts5ExprPhrase*) + ); + pNode = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprNode)); + pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*) ); for(i=0; inTerm; i++){ - pCopy->aTerm[i].zTerm = fts5ExprStrdup(&rc, pOrig->aTerm[i].zTerm); + pCopy->aTerm[i].zTerm = sqlite3Fts5Strndup(&rc, pOrig->aTerm[i].zTerm,-1); pCopy->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix; } @@ -576,29 +551,29 @@ static int fts5ExprNearIsMatch(Fts5ExprNearset *pNear, int *pbMatch){ } /* -** Advance each term iterator in each phrase in pNear. If any reach EOF, -** set output variable *pbEof to true before returning. +** Advance the first term iterator in the first phrase of pNear. Set output +** variable *pbEof to true if it reaches EOF or if an error occurs. +** +** Return SQLITE_OK if successful, or an SQLite error code if an error +** occurs. */ -static int fts5ExprNearAdvanceAll( +static int fts5ExprNearAdvanceFirst( Fts5Expr *pExpr, /* Expression pPhrase belongs to */ - Fts5ExprNearset *pNear, /* Near object to advance iterators of */ - int *pbEof /* OUT: Set to true if phrase at EOF */ + Fts5ExprNode *pNode, /* FTS5_STRING node */ + int bFromValid, + i64 iFrom ){ - int i, j; /* Phrase and token index, respectively */ + Fts5IndexIter *pIter = pNode->pNear->apPhrase[0]->aTerm[0].pIter; + int rc; - for(i=0; inPhrase; i++){ - Fts5ExprPhrase *pPhrase = pNear->apPhrase[i]; - for(j=0; jnTerm; j++){ - Fts5IndexIter *pIter = pPhrase->aTerm[j].pIter; - int rc = sqlite3Fts5IterNext(pIter); - if( rc || sqlite3Fts5IterEof(pIter) ){ - *pbEof = 1; - return rc; - } - } + if( bFromValid ){ + rc = sqlite3Fts5IterNextFrom(pIter, iFrom); + }else{ + rc = sqlite3Fts5IterNext(pIter); } - return SQLITE_OK; + pNode->bEof = (rc || sqlite3Fts5IterEof(pIter)); + return rc; } /* @@ -649,9 +624,7 @@ static int fts5ExprAdvanceto( */ static int fts5ExprNearNextRowidMatch( Fts5Expr *pExpr, /* Expression pPhrase belongs to */ - Fts5ExprNode *pNode, - int bFromValid, - i64 iFrom + Fts5ExprNode *pNode ){ Fts5ExprNearset *pNear = pNode->pNear; int rc = SQLITE_OK; @@ -664,10 +637,6 @@ static int fts5ExprNearNextRowidMatch( ** the maximum rowid. Or, if the iterator is "ORDER BY rowid DESC", then it ** means the minimum rowid. */ iLast = sqlite3Fts5IterRowid(pNear->apPhrase[0]->aTerm[0].pIter); - if( bFromValid && (iFrom>iLast)==(pExpr->bDesc==0) ){ - assert( pExpr->bDesc || iFrom>=iLast ); - iLast = iFrom; - } do { bMatch = 1; @@ -707,9 +676,7 @@ static int fts5ExprNearNextRowidMatch( */ static int fts5ExprNearNextMatch( Fts5Expr *pExpr, /* Expression that pNear is a part of */ - Fts5ExprNode *pNode, /* The "NEAR" node (FTS5_STRING) */ - int bFromValid, - i64 iFrom + Fts5ExprNode *pNode /* The "NEAR" node (FTS5_STRING) */ ){ int rc = SQLITE_OK; Fts5ExprNearset *pNear = pNode->pNear; @@ -717,7 +684,7 @@ static int fts5ExprNearNextMatch( int i; /* Advance the iterators until they all point to the same rowid */ - rc = fts5ExprNearNextRowidMatch(pExpr, pNode, bFromValid, iFrom); + rc = fts5ExprNearNextRowidMatch(pExpr, pNode); if( rc!=SQLITE_OK || pNode->bEof ) break; /* Check that each phrase in the nearset matches the current row. @@ -748,7 +715,7 @@ static int fts5ExprNearNextMatch( /* If control flows to here, then the current rowid is not a match. ** Advance all term iterators in all phrases to the next rowid. */ if( rc==SQLITE_OK ){ - rc = fts5ExprNearAdvanceAll(pExpr, pNear, &pNode->bEof); + rc = fts5ExprNearAdvanceFirst(pExpr, pNode, 0, 0); } if( pNode->bEof || rc!=SQLITE_OK ) break; } @@ -797,7 +764,23 @@ static int fts5ExprNearInitAll( } /* fts5ExprNodeNext() calls fts5ExprNodeNextMatch(). And vice-versa. */ -static int fts5ExprNodeNextMatch(Fts5Expr*, Fts5ExprNode*, int, i64); +static int fts5ExprNodeNextMatch(Fts5Expr*, Fts5ExprNode*); + + +static int fts5RowidCmp( + Fts5Expr *pExpr, + i64 iLhs, + i64 iRhs +){ + assert( pExpr->bDesc==0 || pExpr->bDesc==1 ); + if( pExpr->bDesc==0 ){ + if( iLhs iRhs); + }else{ + if( iLhs>iRhs ) return -1; + return (iLhs < iRhs); + } +} /* ** Compare the values currently indicated by the two nodes as follows: @@ -818,13 +801,7 @@ static int fts5NodeCompare( ){ if( p2->bEof ) return -1; if( p1->bEof ) return +1; - if( pExpr->bDesc==0 ){ - if( p1->iRowidiRowid ) return -1; - return (p1->iRowid > p2->iRowid); - }else{ - if( p1->iRowid>p2->iRowid ) return -1; - return (p1->iRowid < p2->iRowid); - } + return fts5RowidCmp(pExpr, p1->iRowid, p2->iRowid); } /* @@ -845,7 +822,7 @@ static int fts5ExprNodeNext( if( pNode->bEof==0 ){ switch( pNode->eType ){ case FTS5_STRING: { - rc = fts5ExprNearAdvanceAll(pExpr, pNode->pNear, &pNode->bEof); + rc = fts5ExprNearAdvanceFirst(pExpr, pNode, bFromValid, iFrom); break; }; @@ -863,13 +840,14 @@ static int fts5ExprNodeNext( Fts5ExprNode *p2 = pNode->pRight; int cmp = fts5NodeCompare(pExpr, p1, p2); - if( cmp==0 ){ + if( cmp<=0 || (bFromValid && fts5RowidCmp(pExpr,p1->iRowid,iFrom)<0) ){ rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); + } + + if( cmp>=0 || (bFromValid && fts5RowidCmp(pExpr,p2->iRowid,iFrom)<0) ){ if( rc==SQLITE_OK ){ rc = fts5ExprNodeNext(pExpr, p2, bFromValid, iFrom); } - }else{ - rc = fts5ExprNodeNext(pExpr, (cmp < 0) ? p1 : p2, bFromValid, iFrom); } break; @@ -882,10 +860,22 @@ static int fts5ExprNodeNext( } if( rc==SQLITE_OK ){ - rc = fts5ExprNodeNextMatch(pExpr, pNode, bFromValid, iFrom); + rc = fts5ExprNodeNextMatch(pExpr, pNode); } } + /* Assert that if bFromValid was true, either: + ** + ** a) an error occurred, or + ** b) the node is now at EOF, or + ** c) the node is now at or past rowid iFrom. + */ + assert( bFromValid==0 + || rc!=SQLITE_OK /* a */ + || pNode->bEof /* b */ + || pNode->iRowid==iFrom || pExpr->bDesc==(pNode->iRowidbEof==0 ){ switch( pNode->eType ){ case FTS5_STRING: { - rc = fts5ExprNearNextMatch(pExpr, pNode, bFromValid, iFrom); + rc = fts5ExprNearNextMatch(pExpr, pNode); break; } @@ -921,17 +911,14 @@ static int fts5ExprNodeNextMatch( while( p1->bEof==0 && p2->bEof==0 && p2->iRowid!=p1->iRowid ){ Fts5ExprNode *pAdv; + i64 iFrom; assert( pExpr->bDesc==0 || pExpr->bDesc==1 ); if( pExpr->bDesc==(p1->iRowid > p2->iRowid) ){ pAdv = p1; - if( bFromValid==0 || pExpr->bDesc==(p2->iRowid < iFrom) ){ - iFrom = p2->iRowid; - } + iFrom = p2->iRowid; }else{ pAdv = p2; - if( bFromValid==0 || pExpr->bDesc==(p1->iRowid < iFrom) ){ - iFrom = p1->iRowid; - } + iFrom = p1->iRowid; } rc = fts5ExprNodeNext(pExpr, pAdv, 1, iFrom); if( rc!=SQLITE_OK ) break; @@ -955,13 +942,16 @@ static int fts5ExprNodeNextMatch( default: assert( pNode->eType==FTS5_NOT ); { Fts5ExprNode *p1 = pNode->pLeft; Fts5ExprNode *p2 = pNode->pRight; - while( rc==SQLITE_OK ){ - int cmp; - while( rc==SQLITE_OK && (cmp = fts5NodeCompare(pExpr, p1, p2))>0 ){ - rc = fts5ExprNodeNext(pExpr, p2, bFromValid, iFrom); + + while( rc==SQLITE_OK && p1->bEof==0 ){ + int cmp = fts5NodeCompare(pExpr, p1, p2); + if( cmp>0 ){ + rc = fts5ExprNodeNext(pExpr, p2, 1, p1->iRowid); + cmp = fts5NodeCompare(pExpr, p1, p2); } - if( rc || cmp ) break; - rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom); + assert( rc!=SQLITE_OK || cmp<=0 ); + if( rc || cmp<0 ) break; + rc = fts5ExprNodeNext(pExpr, p1, 0, 0); } pNode->bEof = p1->bEof; pNode->iRowid = p1->iRowid; @@ -991,7 +981,7 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ /* Attempt to advance to the first match */ if( rc==SQLITE_OK && pNode->bEof==0 ){ - rc = fts5ExprNearNextMatch(pExpr, pNode, 0, 0); + rc = fts5ExprNearNextMatch(pExpr, pNode); } }else{ @@ -1000,7 +990,7 @@ static int fts5ExprNodeFirst(Fts5Expr *pExpr, Fts5ExprNode *pNode){ rc = fts5ExprNodeFirst(pExpr, pNode->pRight); } if( rc==SQLITE_OK ){ - rc = fts5ExprNodeNextMatch(pExpr, pNode, 0, 0); + rc = fts5ExprNodeNextMatch(pExpr, pNode); } } return rc; @@ -1047,31 +1037,9 @@ i64 sqlite3Fts5ExprRowid(Fts5Expr *p){ return p->pRoot->iRowid; } -/* -** Argument pIn points to a buffer of nIn bytes. This function allocates -** and returns a new buffer populated with a copy of (pIn/nIn) with a -** nul-terminator byte appended to it. -** -** It is the responsibility of the caller to eventually free the returned -** buffer using sqlite3_free(). If an OOM error occurs, NULL is returned. -*/ -static char *fts5Strndup(int *pRc, const char *pIn, int nIn){ - char *zRet = 0; - if( *pRc==SQLITE_OK ){ - zRet = (char*)sqlite3_malloc(nIn+1); - if( zRet ){ - memcpy(zRet, pIn, nIn); - zRet[nIn] = '\0'; - }else{ - *pRc = SQLITE_NOMEM; - } - } - return zRet; -} - static int fts5ParseStringFromToken(Fts5Token *pToken, char **pz){ int rc = SQLITE_OK; - *pz = fts5Strndup(&rc, pToken->p, pToken->n); + *pz = sqlite3Fts5Strndup(&rc, pToken->p, pToken->n); return rc; } @@ -1123,7 +1091,7 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset( pRet->iCol = -1; } }else if( (pNear->nPhrase % SZALLOC)==0 ){ - int nNew = pRet->nPhrase + SZALLOC; + int nNew = pNear->nPhrase + SZALLOC; int nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*); pRet = (Fts5ExprNearset*)sqlite3_realloc(pNear, nByte); @@ -1181,7 +1149,7 @@ static int fts5ParseTokenize( pTerm = &pPhrase->aTerm[pPhrase->nTerm++]; memset(pTerm, 0, sizeof(Fts5ExprTerm)); - pTerm->zTerm = fts5Strndup(&rc, pToken, nToken); + pTerm->zTerm = sqlite3Fts5Strndup(&rc, pToken, nToken); return rc; } @@ -1272,12 +1240,10 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm( ** in the pParse object. */ void sqlite3Fts5ParseNear(Fts5Parse *pParse, Fts5Token *pTok){ - if( pParse->rc==SQLITE_OK ){ - if( pTok->n!=4 || memcmp("NEAR", pTok->p, 4) ){ - sqlite3Fts5ParseError( - pParse, "fts5: syntax error near \"%.*s\"", pTok->n, pTok->p - ); - } + if( pTok->n!=4 || memcmp("NEAR", pTok->p, 4) ){ + sqlite3Fts5ParseError( + pParse, "fts5: syntax error near \"%.*s\"", pTok->n, pTok->p + ); } } @@ -1310,23 +1276,25 @@ void sqlite3Fts5ParseSetColumn( Fts5ExprNearset *pNear, Fts5Token *p ){ - char *z = 0; - int rc = fts5ParseStringFromToken(p, &z); - if( rc==SQLITE_OK ){ - Fts5Config *pConfig = pParse->pConfig; - int i; - for(i=0; inCol; i++){ - if( 0==sqlite3_stricmp(pConfig->azCol[i], z) ){ - pNear->iCol = i; - break; + if( pParse->rc==SQLITE_OK ){ + char *z = 0; + int rc = fts5ParseStringFromToken(p, &z); + if( rc==SQLITE_OK ){ + Fts5Config *pConfig = pParse->pConfig; + int i; + for(i=0; inCol; i++){ + if( 0==sqlite3_stricmp(pConfig->azCol[i], z) ){ + pNear->iCol = i; + break; + } } + if( i==pConfig->nCol ){ + sqlite3Fts5ParseError(pParse, "no such column: %s", z); + } + sqlite3_free(z); + }else{ + pParse->rc = rc; } - if( i==pConfig->nCol ){ - sqlite3Fts5ParseError(pParse, "no such column: %s", z); - } - sqlite3_free(z); - }else{ - pParse->rc = rc; } } diff --git a/ext/fts5/test/fts5ea.test b/ext/fts5/test/fts5ea.test index 7b58d8cd8f..1248edea0b 100644 --- a/ext/fts5/test/fts5ea.test +++ b/ext/fts5/test/fts5ea.test @@ -66,11 +66,15 @@ foreach {tn expr err} { 3 {abc OR AND} {fts5: syntax error near "AND"} 4 {(a OR b) abc} {fts5: syntax error near "abc"} 5 {NEaR (a b)} {fts5: syntax error near "NEaR"} - 6 {(a OR b) NOT c)} {fts5: syntax error near ")"} - 7 {nosuch: a nosuch2: b} {no such column: nosuch} - 8 {addr: a nosuch2: b} {no such column: nosuch2} - 9 {NOT} {fts5: syntax error near "NOT"} - 10 {a AND "abc} {unterminated string} + 6 {NEa (a b)} {fts5: syntax error near "NEa"} + 7 {(a OR b) NOT c)} {fts5: syntax error near ")"} + 8 {nosuch: a nosuch2: b} {no such column: nosuch} + 9 {addr: a nosuch2: b} {no such column: nosuch2} + 10 {NOT} {fts5: syntax error near "NOT"} + 11 {a AND "abc} {unterminated string} + + 12 {NEAR(a b, xyz)} {expected integer, got "xyz"} + 13 {NEAR(a b, // )} {expected integer, got "//"} } { do_catchsql_test 3.$tn {SELECT fts5_expr($expr, 'name', 'addr')} [list 1 $err] } diff --git a/ext/fts5/test/fts5fault4.test b/ext/fts5/test/fts5fault4.test index 8e6c827ad3..943d331db8 100644 --- a/ext/fts5/test/fts5fault4.test +++ b/ext/fts5/test/fts5fault4.test @@ -201,6 +201,8 @@ do_faultsim_test 6.2 -faults oom-t* -body { faultsim_test_result {0 {0 2 7}} {1 SQLITE_NOMEM} } +} + #------------------------------------------------------------------------- # OOM error when querying for a phrase with many tokens. # @@ -218,6 +220,10 @@ do_execsql_test 7.0 { INSERT INTO tt VALUES('e a e b e e', 'd c c f f f'); -- 9 INSERT INTO tt VALUES('f a g g c c', 'e g d g c e'); -- 10 INSERT INTO tt VALUES('c d b a e f', 'f g e h e e'); -- 11 + + CREATE VIRTUAL TABLE tt2 USING fts5(o); + INSERT INTO tt2(rowid, o) SELECT rowid, x||' '||y FROM tt; + INSERT INTO tt2(rowid, o) VALUES(12, 'a b c d e f g h i j k l'); } do_faultsim_test 7.2 -faults oom-* -body { @@ -232,6 +238,22 @@ do_faultsim_test 7.3 -faults oom-* -body { faultsim_test_result {0 11} {1 SQLITE_NOMEM} } +do_faultsim_test 7.4 -faults oom-t* -body { + db eval { SELECT rowid FROM tt2 WHERE tt2 MATCH '"g c f c e f e e a f"' } +} -test { + faultsim_test_result {0 8} {1 SQLITE_NOMEM} +} + +do_faultsim_test 7.5 -faults oom-* -body { + db eval {SELECT rowid FROM tt2 WHERE tt2 MATCH 'NEAR(a b c d e f g h i j k)'} +} -test { + faultsim_test_result {0 12} {1 SQLITE_NOMEM} +} + +do_faultsim_test 7.6 -faults oom-* -body { + db eval {SELECT rowid FROM tt WHERE tt MATCH 'y: "c c"'} +} -test { + faultsim_test_result {0 {1 9}} {1 SQLITE_NOMEM} } #------------------------------------------------------------------------- @@ -261,6 +283,27 @@ do_faultsim_test 8.2 -faults oom-t* -body { } +#------------------------------------------------------------------------- +# Fault in NOT query. +# +reset_db +do_execsql_test 9.0 { + CREATE VIRTUAL TABLE tt USING fts5(x); + INSERT INTO tt(tt, rank) VALUES('pgsz', 32); + BEGIN; + WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<200) + INSERT INTO tt(rowid, x) + SELECT i, CASE WHEN (i%50)==0 THEN 'a a a a a a' ELSE 'a x a x a x' END + FROM ii; + COMMIT; +} + +do_faultsim_test 9.1 -faults oom-* -body { + db eval { SELECT rowid FROM tt WHERE tt MATCH 'a NOT x' } +} -test { + faultsim_test_result {0 {50 100 150 200}} {1 SQLITE_NOMEM} +} + finish_test diff --git a/manifest b/manifest index 92d1a1bb51..53ddbec52d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Further\simprovements\sto\stest\scoverage\sof\sfts5\scode. -D 2015-05-01T20:38:57.153 +C Reorganize\ssome\sof\sthe\sfts5\sexpression\sparsing\scode.\sImprove\stest\scoverage\sof\sthe\ssame. +D 2015-05-02T20:35:24.467 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 31b38b9da2e4b36f54a013bd71a5c3f6e45ca78f F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -106,11 +106,11 @@ F ext/fts3/unicode/mkunicode.tcl 159c1194da0bc72f51b3c2eb71022568006dc5ad F ext/fts5/extract_api_docs.tcl 55a6d648d516f35d9a1e580ac00de27154e1904a F ext/fts5/fts5.c 3a0a73bcfbcb7e65ccda099cfb8fd268d2480c7e F ext/fts5/fts5.h 24a2cc35b5e76eec57b37ba48c12d9d2cb522b3a -F ext/fts5/fts5Int.h 2e0a1a6b77e1e014b7e9b1479ca686ff79930457 +F ext/fts5/fts5Int.h 05e97ffb2911e8c8cfcb8bdb009e17347c24eb2d F ext/fts5/fts5_aux.c d53f00f31ad615ca4f139dd8751f9041afa00971 -F ext/fts5/fts5_buffer.c 8c8cfe7f09ca2767ab53ea883f9a0af0edb6bbae -F ext/fts5/fts5_config.c ecbbd5163758a958106867051892e0dfecf68b5c -F ext/fts5/fts5_expr.c e2005ba7823f4ac51d46a8e5aaa1ff66c701b32e +F ext/fts5/fts5_buffer.c 70b971e13503566f1e257941c60817ba0920a16b +F ext/fts5/fts5_config.c 4e0de8bea4746a7560740b9dcf8be4dced68ef4f +F ext/fts5/fts5_expr.c f49d68411dc72cb66f2b55cc109dbf3dce368eef F ext/fts5/fts5_hash.c 29d8b0668727863cc1f1efa65efe4dd78635b016 F ext/fts5/fts5_index.c de588982b0237b1605d6c37afd115b34c95c3da1 F ext/fts5/fts5_storage.c ef60fc9dcc4e274f9589165e26833173c273ae18 @@ -140,12 +140,12 @@ F ext/fts5/test/fts5corrupt.test 138aecc75c36c3dac9259c7f57c5bc3d009255f8 F ext/fts5/test/fts5corrupt2.test 494111fd4f2dab36499cf97718eaba1f7c11e9d0 F ext/fts5/test/fts5dlidx.test 748a84ceb74a4154725096a26dfa854260b0182f F ext/fts5/test/fts5doclist.test 635b80ac785627841a59c583bac702b55d49fdc5 -F ext/fts5/test/fts5ea.test 7cc498993c16849bb866dbdfb008d91a29f9870b +F ext/fts5/test/fts5ea.test f4d35cd2776dab9358206f7d88a67ea187fdec22 F ext/fts5/test/fts5eb.test 728a1f23f263548f5c29b29dfb851b5f2dbe723e F ext/fts5/test/fts5fault1.test ed71717a479bef32d05f02d9c48691011d160d4d F ext/fts5/test/fts5fault2.test 26c3d70648f691e2cc9391e14bbc11a973656383 F ext/fts5/test/fts5fault3.test d6e9577d4312e331a913c72931bf131704efc8f3 -F ext/fts5/test/fts5fault4.test 4090af395d8d3342c0a0b27349dd71eb7cc6262d +F ext/fts5/test/fts5fault4.test 09728cadb4897c97cea092edb9c431d9ec25b88b F ext/fts5/test/fts5full.test 0924bdca5416a242103239ace79c6f5aa34bab8d F ext/fts5/test/fts5hash.test adb7b0442cc1c77c507f07e16d11490486e75dfa F ext/fts5/test/fts5merge.test 453a0717881aa7784885217b2040f3f275caff03 @@ -1315,7 +1315,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P add4f4681c648dcbecaa68d08f7b2f4e6d63003c -R 58de859125935eeaf7ecede3ffbb5a07 +P d4331943dff259380c4025bb740d8aba6972d351 +R 5651f6663bbd8efe3d630621e3f4b900 U dan -Z fc00d731e9356a3f17b66c35cad599ad +Z 822e7611ba479003f18b45bbb7ca820a diff --git a/manifest.uuid b/manifest.uuid index ee6ce26d11..ddc1ccf8f3 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d4331943dff259380c4025bb740d8aba6972d351 \ No newline at end of file +c4456dc5f5f8f45f04e3bbae53b6bcc209fc27d5 \ No newline at end of file