/ Check-in [6b21d0fd]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Further improvements to coverage of fts3 module.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 6b21d0fdebdccfaf63590d9ca9a279c22b8baec07c1a669b9f617f25bd857384
User & Date: dan 2017-04-19 13:25:45
Context
2017-04-21
16:04
Fix an FTS5 bug that could cause a prefix-query without a prefix-index on a database that contains delete-markers to return extra, non-matching, rows. check-in: 840042cb user: dan tags: trunk
2017-04-20
17:35
Merge latest trunk changes into this branch. check-in: b1533bc4 user: dan tags: schemalint
2017-04-19
13:25
Further improvements to coverage of fts3 module. check-in: 6b21d0fd user: dan tags: trunk
07:33
Further modifications and test cases to improve test coverage of fts3. check-in: ea8a0d2c user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

  3558   3558   */
  3559   3559   static int fts3FunctionArg(
  3560   3560     sqlite3_context *pContext,      /* SQL function call context */
  3561   3561     const char *zFunc,              /* Function name */
  3562   3562     sqlite3_value *pVal,            /* argv[0] passed to function */
  3563   3563     Fts3Cursor **ppCsr              /* OUT: Store cursor handle here */
  3564   3564   ){
  3565         -  Fts3Cursor *pRet;
  3566         -  if( sqlite3_value_type(pVal)!=SQLITE_BLOB 
  3567         -   || sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
  3568         -  ){
         3565  +  int rc = SQLITE_OK;
         3566  +  if( sqlite3_value_subtype(pVal)==SQLITE_BLOB ){
         3567  +    *ppCsr = *(Fts3Cursor**)sqlite3_value_blob(pVal);
         3568  +  }else{
  3569   3569       char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
  3570   3570       sqlite3_result_error(pContext, zErr, -1);
  3571   3571       sqlite3_free(zErr);
  3572         -    return SQLITE_ERROR;
         3572  +    rc = SQLITE_ERROR;
  3573   3573     }
  3574         -  memcpy(&pRet, sqlite3_value_blob(pVal), sizeof(Fts3Cursor *));
  3575         -  *ppCsr = pRet;
  3576         -  return SQLITE_OK;
         3574  +  return rc;
  3577   3575   }
  3578   3576   
  3579   3577   /*
  3580   3578   ** Implementation of the snippet() function for FTS3
  3581   3579   */
  3582   3580   static void fts3SnippetFunc(
  3583   3581     sqlite3_context *pContext,      /* SQLite function call context */
................................................................................
  5287   5285     **
  5288   5286     ** The right-hand child of a NEAR node is always a phrase. The 
  5289   5287     ** left-hand child may be either a phrase or a NEAR node. There are
  5290   5288     ** no exceptions to this - it's the way the parser in fts3_expr.c works.
  5291   5289     */
  5292   5290     if( *pRc==SQLITE_OK 
  5293   5291      && pExpr->eType==FTSQUERY_NEAR 
  5294         -   && pExpr->bEof==0
  5295   5292      && (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
  5296   5293     ){
  5297   5294       Fts3Expr *p; 
  5298   5295       int nTmp = 0;                 /* Bytes of temp space */
  5299   5296       char *aTmp;                   /* Temp space for PoslistNearMerge() */
  5300   5297   
  5301   5298       /* Allocate temporary working space. */
  5302   5299       for(p=pExpr; p->pLeft; p=p->pLeft){
         5300  +      assert( p->pRight->pPhrase->doclist.nList>0 );
  5303   5301         nTmp += p->pRight->pPhrase->doclist.nList;
  5304   5302       }
  5305   5303       nTmp += p->pPhrase->doclist.nList;
  5306         -    if( nTmp==0 ){
         5304  +    aTmp = sqlite3_malloc(nTmp*2);
         5305  +    if( !aTmp ){
         5306  +      *pRc = SQLITE_NOMEM;
  5307   5307         res = 0;
  5308   5308       }else{
  5309         -      aTmp = sqlite3_malloc(nTmp*2);
  5310         -      if( !aTmp ){
  5311         -        *pRc = SQLITE_NOMEM;
  5312         -        res = 0;
  5313         -      }else{
  5314         -        char *aPoslist = p->pPhrase->doclist.pList;
  5315         -        int nToken = p->pPhrase->nToken;
  5316         -
  5317         -        for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
  5318         -          Fts3Phrase *pPhrase = p->pRight->pPhrase;
  5319         -          int nNear = p->nNear;
  5320         -          res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
  5321         -        }
  5322         -
  5323         -        aPoslist = pExpr->pRight->pPhrase->doclist.pList;
  5324         -        nToken = pExpr->pRight->pPhrase->nToken;
  5325         -        for(p=pExpr->pLeft; p && res; p=p->pLeft){
  5326         -          int nNear;
  5327         -          Fts3Phrase *pPhrase;
  5328         -          assert( p->pParent && p->pParent->pLeft==p );
  5329         -          nNear = p->pParent->nNear;
  5330         -          pPhrase = (
  5331         -              p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
  5332         -              );
  5333         -          res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
  5334         -        }
         5309  +      char *aPoslist = p->pPhrase->doclist.pList;
         5310  +      int nToken = p->pPhrase->nToken;
         5311  +
         5312  +      for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
         5313  +        Fts3Phrase *pPhrase = p->pRight->pPhrase;
         5314  +        int nNear = p->nNear;
         5315  +        res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
         5316  +      }
         5317  +
         5318  +      aPoslist = pExpr->pRight->pPhrase->doclist.pList;
         5319  +      nToken = pExpr->pRight->pPhrase->nToken;
         5320  +      for(p=pExpr->pLeft; p && res; p=p->pLeft){
         5321  +        int nNear;
         5322  +        Fts3Phrase *pPhrase;
         5323  +        assert( p->pParent && p->pParent->pLeft==p );
         5324  +        nNear = p->pParent->nNear;
         5325  +        pPhrase = (
         5326  +            p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
         5327  +        );
         5328  +        res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
  5335   5329         }
         5330  +    }
  5336   5331   
  5337         -      sqlite3_free(aTmp);
  5338         -    }
         5332  +    sqlite3_free(aTmp);
  5339   5333     }
  5340   5334   
  5341   5335     return res;
  5342   5336   }
  5343   5337   
  5344   5338   /*
  5345   5339   ** This function is a helper function for sqlite3Fts3EvalTestDeferred().

Changes to test/fts3misc.test.

   167    167   } {1 {database disk image is malformed}}
   168    168   do_execsql_test 4.5 {
   169    169     UPDATE t4_stat SET value = X'00C03EC0B204C0A608' WHERE id=0;
   170    170   }
   171    171   do_catchsql_test 4.6 {
   172    172     SELECT count(*) FROM t4 WHERE t4 MATCH '"a b c" OR "c a b"'
   173    173   } {1 {database disk image is malformed}}
          174  +
          175  +#-------------------------------------------------------------------------
          176  +#
          177  +reset_db
          178  +do_execsql_test 5.0 {
          179  +  CREATE VIRTUAL TABLE t5 USING fts4;
          180  +  INSERT INTO t5 VALUES('a x x x x b x x x x c');
          181  +  INSERT INTO t5 VALUES('a x x x x b x x x x c');
          182  +  INSERT INTO t5 VALUES('a x x x x b x x x x c');
          183  +}
          184  +do_execsql_test 5.1 {
          185  +  SELECT rowid FROM t5 WHERE t5 MATCH 'a NEAR/4 b NEAR/4 c'
          186  +} {1 2 3}
          187  +do_execsql_test 5.2 {
          188  +  SELECT rowid FROM t5 WHERE t5 MATCH 'a NEAR/3 b NEAR/4 c'
          189  +} {}
          190  +do_execsql_test 5.3 {
          191  +  SELECT rowid FROM t5 WHERE t5 MATCH 'a NEAR/4 b NEAR/3 c'
          192  +} {}
          193  +do_execsql_test 5.4 {
          194  +  SELECT rowid FROM t5 WHERE t5 MATCH 'y NEAR/4 b NEAR/4 c'
          195  +} {}
          196  +do_execsql_test 5.5 {
          197  +  SELECT rowid FROM t5 WHERE t5 MATCH 'x OR a NEAR/3 b NEAR/3 c'
          198  +} {1 2 3}
          199  +do_execsql_test 5.5 {
          200  +  SELECT rowid FROM t5 WHERE t5 MATCH 'x OR y NEAR/3 b NEAR/3 c'
          201  +} {1 2 3}
          202  +
          203  +#-------------------------------------------------------------------------
          204  +#
          205  +reset_db
          206  +do_execsql_test 6.0 {
          207  +  CREATE VIRTUAL TABLE t6 USING fts4;
          208  +
          209  +  BEGIN;
          210  +  WITH s(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000)
          211  +    INSERT INTO t6 SELECT 'x x x x x x x x x x x' FROM s;
          212  +
          213  +  INSERT INTO t6 VALUES('x x x x x x x x x x x A');
          214  +  INSERT INTO t6 VALUES('x x x x x x x x x x x B');
          215  +  INSERT INTO t6 VALUES('x x x x x x x x x x x A');
          216  +  INSERT INTO t6 VALUES('x x x x x x x x x x x B');
          217  +
          218  +  WITH s(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000)
          219  +    INSERT INTO t6 SELECT 'x x x x x x x x x x x' FROM s;
          220  +  COMMIT;
          221  +}
          222  +breakpoint
          223  +do_execsql_test 6.1 {
          224  +  SELECT rowid FROM t6 WHERE t6 MATCH 'b OR "x a"'
          225  +} {50001 50002 50003 50004}
   174    226   
   175    227   
   176    228   finish_test