/ Check-in [a8b1d998]
Login

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

Overview
Comment:Test coverage improvements for fts3.c.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1:a8b1d99899678b72c2a487909eabed321593d55f
User & Date: dan 2010-10-25 12:47:43
Context
2010-10-25
19:01
Further improvements to coverage of fts3.c. Fixes for bugs revealed by the same. check-in: 918b6092 user: dan tags: experimental
12:47
Test coverage improvements for fts3.c. check-in: a8b1d998 user: dan tags: experimental
09:01
Add test for matchinfo when a phrase includes some common tokens. check-in: 80a54ebc user: dan tags: experimental
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
....
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
....
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
....
2579
2580
2581
2582
2583
2584
2585

2586
2587
2588
2589
2590
2591
2592
....
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
....
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
....
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
....
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
....
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
....
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
....
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
    }
    assert( nOut==0 || pOut!=0 );

    iPrevTok = iTok;
  }

  if( rc==SQLITE_OK ){
    if( ii!=pPhrase->nToken && pCsr->eEvalmode==FTS3_EVAL_FILTER ){
      assert( pCsr->eEvalmode==FTS3_EVAL_FILTER && isReqPos==0 );
      fts3DoclistStripPositions(pOut, &nOut);
    }
    *paOut = pOut;
    *pnOut = nOut;
  }else{
    sqlite3_free(pOut);
................................................................................
static int fts3ExprAllocateSegReaders(
  Fts3Cursor *pCsr,               /* FTS3 table */
  Fts3Expr *pExpr,                /* Expression to create seg-readers for */
  int *pnExpr                     /* OUT: Number of AND'd expressions */
){
  int rc = SQLITE_OK;             /* Return code */

  assert( pCsr->eEvalmode!=FTS3_EVAL_MATCHINFO );
  if( pCsr->eEvalmode==FTS3_EVAL_NEXT ) return SQLITE_OK;
  if( pnExpr && pExpr->eType!=FTSQUERY_AND ){
    (*pnExpr)++;
    pnExpr = 0;
  }

  if( pExpr->eType==FTSQUERY_PHRASE ){
    Fts3Phrase *pPhrase = pExpr->pPhrase;
................................................................................
  *pnOut = 0;

  if( pExpr ){
    assert( pExpr->eType==FTSQUERY_NEAR   || pExpr->eType==FTSQUERY_OR     
         || pExpr->eType==FTSQUERY_AND    || pExpr->eType==FTSQUERY_NOT
         || pExpr->eType==FTSQUERY_PHRASE
    );
    assert( pExpr->eType==FTSQUERY_PHRASE 
         || pExpr->eType==FTSQUERY_NEAR 
         || isReqPos==0
    );

    if( pExpr->eType==FTSQUERY_PHRASE ){
      rc = fts3PhraseSelect(p, pExpr->pPhrase,
          isReqPos || (pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR),
          paOut, pnOut
      );
      fts3ExprFreeSegReaders(pExpr);
................................................................................
      int nRet = 0;               /* Length of aRet[] in bytes */
      int nDoc = 0x7FFFFFFF;

      assert( !isReqPos );

      rc = fts3ExprAllocateSegReaders(p, pExpr, &nExpr);
      if( rc==SQLITE_OK ){

        aExpr = sqlite3_malloc(sizeof(ExprAndCost) * nExpr);
        if( !aExpr ) rc = SQLITE_NOMEM;
      }
      if( rc==SQLITE_OK ){
        int ii;                   /* Used to iterate through expressions */

        fts3ExprAssignCosts(pExpr, &aExpr);
................................................................................
          }else{
            rc = fts3EvalExpr(p, pBest->pExpr, &aNew, &nNew, 0);
            if( rc!=SQLITE_OK ) break;
            pBest->pExpr = 0;
            if( ii==0 ){
              aRet = aNew;
              nRet = nNew;
              if( nExpr>1 ){
                nDoc = fts3DoclistCountDocids(0, aRet, nRet);
              }
            }else{
              fts3DoclistMerge(
                  MERGE_AND, 0, 0, aRet, &nRet, aRet, nRet, aNew, nNew, &nDoc
              );
              sqlite3_free(aNew);
            }
          }
................................................................................
      if( 0==(rc = fts3EvalExpr(p, pExpr->pRight, &aRight, &nRight, isReqPos))
       && 0==(rc = fts3EvalExpr(p, pExpr->pLeft, &aLeft, &nLeft, isReqPos))
      ){
        switch( pExpr->eType ){
          case FTSQUERY_NEAR: {
            Fts3Expr *pLeft;
            Fts3Expr *pRight;
            int mergetype = isReqPos ? MERGE_POS_NEAR : MERGE_NEAR;
           
            if( pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR ){
              mergetype = MERGE_POS_NEAR;
            }
            pLeft = pExpr->pLeft;
            while( pLeft->eType==FTSQUERY_NEAR ){ 
              pLeft=pLeft->pRight;
            }
................................................................................
    if( rc!=SQLITE_OK ) return rc;

    rc = fts3EvalExpr(pCsr, pCsr->pExpr, &pCsr->aDoclist, &pCsr->nDoclist, 0);
    sqlite3Fts3SegmentsClose(p);
    if( rc!=SQLITE_OK ) return rc;
    pCsr->pNextId = pCsr->aDoclist;
    pCsr->iPrevId = 0;
    if( pCsr->nDoclist<0 ){
      assert( pCsr->aDoclist==0 );
      idxNum = FTS3_FULLSCAN_SEARCH;
    }
  }

  /* Compile a SELECT statement for this cursor. For a full-table-scan, the
  ** statement loops through all rows of the %_content table. For a
  ** full-text query or docid lookup, the statement retrieves a single
  ** row by docid.
  */
................................................................................
** message is written to context pContext and SQLITE_ERROR returned. The
** string passed via zFunc is used as part of the error message.
*/
static int fts3FunctionArg(
  sqlite3_context *pContext,      /* SQL function call context */
  const char *zFunc,              /* Function name */
  sqlite3_value *pVal,            /* argv[0] passed to function */
  Fts3Cursor **ppCsr         /* OUT: Store cursor handle here */
){
  Fts3Cursor *pRet;
  if( sqlite3_value_type(pVal)!=SQLITE_BLOB 
   || sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
  ){
    char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
    sqlite3_result_error(pContext, zErr, -1);
................................................................................
*/
static void fts3MatchinfoFunc(
  sqlite3_context *pContext,      /* SQLite function call context */
  int nVal,                       /* Size of argument array */
  sqlite3_value **apVal           /* Array of arguments */
){
  Fts3Cursor *pCsr;               /* Cursor handle passed through apVal[0] */

  if( nVal!=1 ){
    sqlite3_result_error(pContext,
        "wrong number of arguments to function matchinfo()", -1);
    return;
  }

  if( SQLITE_OK==fts3FunctionArg(pContext, "matchinfo", apVal[0], &pCsr) ){
    sqlite3Fts3Matchinfo(pContext, pCsr);
  }
}

/*
** This routine implements the xFindFunction method for the FTS3
................................................................................
    return rc;
  }

  fts3DbExec(&rc, db,
    "ALTER TABLE %Q.'%q_content'  RENAME TO '%q_content';",
    p->zDb, p->zName, zName
  );
  if( rc==SQLITE_ERROR ) rc = SQLITE_OK;
  if( p->bHasDocsize ){
    fts3DbExec(&rc, db,
      "ALTER TABLE %Q.'%q_docsize'  RENAME TO '%q_docsize';",
      p->zDb, p->zName, zName
    );
    fts3DbExec(&rc, db,
      "ALTER TABLE %Q.'%q_stat'  RENAME TO '%q_stat';",
................................................................................
  ** the two scalar functions. If this is successful, register the
  ** module with sqlite.
  */
  if( SQLITE_OK==rc 
   && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", -1))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1))
  ){
    rc = sqlite3_create_module_v2(
        db, "fts3", &fts3Module, (void *)pHash, hashDestroy
    );
    if( rc==SQLITE_OK ){
      rc = sqlite3_create_module_v2(







|







 







<
|







 







|
<
<
<







 







>







 







<
|
<







 







|
<







 







<
<
<
<







 







|







 







<
|
<
<
<
<
<







 







<







 







|







2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
....
2406
2407
2408
2409
2410
2411
2412

2413
2414
2415
2416
2417
2418
2419
2420
....
2556
2557
2558
2559
2560
2561
2562
2563



2564
2565
2566
2567
2568
2569
2570
....
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
....
2607
2608
2609
2610
2611
2612
2613

2614

2615
2616
2617
2618
2619
2620
2621
....
2642
2643
2644
2645
2646
2647
2648
2649

2650
2651
2652
2653
2654
2655
2656
....
2850
2851
2852
2853
2854
2855
2856




2857
2858
2859
2860
2861
2862
2863
....
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
....
3211
3212
3213
3214
3215
3216
3217

3218





3219
3220
3221
3222
3223
3224
3225
....
3274
3275
3276
3277
3278
3279
3280

3281
3282
3283
3284
3285
3286
3287
....
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
    }
    assert( nOut==0 || pOut!=0 );

    iPrevTok = iTok;
  }

  if( rc==SQLITE_OK ){
    if( ii!=pPhrase->nToken ){
      assert( pCsr->eEvalmode==FTS3_EVAL_FILTER && isReqPos==0 );
      fts3DoclistStripPositions(pOut, &nOut);
    }
    *paOut = pOut;
    *pnOut = nOut;
  }else{
    sqlite3_free(pOut);
................................................................................
static int fts3ExprAllocateSegReaders(
  Fts3Cursor *pCsr,               /* FTS3 table */
  Fts3Expr *pExpr,                /* Expression to create seg-readers for */
  int *pnExpr                     /* OUT: Number of AND'd expressions */
){
  int rc = SQLITE_OK;             /* Return code */


  assert( pCsr->eEvalmode==FTS3_EVAL_FILTER );
  if( pnExpr && pExpr->eType!=FTSQUERY_AND ){
    (*pnExpr)++;
    pnExpr = 0;
  }

  if( pExpr->eType==FTSQUERY_PHRASE ){
    Fts3Phrase *pPhrase = pExpr->pPhrase;
................................................................................
  *pnOut = 0;

  if( pExpr ){
    assert( pExpr->eType==FTSQUERY_NEAR   || pExpr->eType==FTSQUERY_OR     
         || pExpr->eType==FTSQUERY_AND    || pExpr->eType==FTSQUERY_NOT
         || pExpr->eType==FTSQUERY_PHRASE
    );
    assert( pExpr->eType==FTSQUERY_PHRASE || isReqPos==0 );




    if( pExpr->eType==FTSQUERY_PHRASE ){
      rc = fts3PhraseSelect(p, pExpr->pPhrase,
          isReqPos || (pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR),
          paOut, pnOut
      );
      fts3ExprFreeSegReaders(pExpr);
................................................................................
      int nRet = 0;               /* Length of aRet[] in bytes */
      int nDoc = 0x7FFFFFFF;

      assert( !isReqPos );

      rc = fts3ExprAllocateSegReaders(p, pExpr, &nExpr);
      if( rc==SQLITE_OK ){
        assert( nExpr>1 );
        aExpr = sqlite3_malloc(sizeof(ExprAndCost) * nExpr);
        if( !aExpr ) rc = SQLITE_NOMEM;
      }
      if( rc==SQLITE_OK ){
        int ii;                   /* Used to iterate through expressions */

        fts3ExprAssignCosts(pExpr, &aExpr);
................................................................................
          }else{
            rc = fts3EvalExpr(p, pBest->pExpr, &aNew, &nNew, 0);
            if( rc!=SQLITE_OK ) break;
            pBest->pExpr = 0;
            if( ii==0 ){
              aRet = aNew;
              nRet = nNew;

              nDoc = fts3DoclistCountDocids(0, aRet, nRet);

            }else{
              fts3DoclistMerge(
                  MERGE_AND, 0, 0, aRet, &nRet, aRet, nRet, aNew, nNew, &nDoc
              );
              sqlite3_free(aNew);
            }
          }
................................................................................
      if( 0==(rc = fts3EvalExpr(p, pExpr->pRight, &aRight, &nRight, isReqPos))
       && 0==(rc = fts3EvalExpr(p, pExpr->pLeft, &aLeft, &nLeft, isReqPos))
      ){
        switch( pExpr->eType ){
          case FTSQUERY_NEAR: {
            Fts3Expr *pLeft;
            Fts3Expr *pRight;
            int mergetype = MERGE_NEAR;

            if( pExpr->pParent && pExpr->pParent->eType==FTSQUERY_NEAR ){
              mergetype = MERGE_POS_NEAR;
            }
            pLeft = pExpr->pLeft;
            while( pLeft->eType==FTSQUERY_NEAR ){ 
              pLeft=pLeft->pRight;
            }
................................................................................
    if( rc!=SQLITE_OK ) return rc;

    rc = fts3EvalExpr(pCsr, pCsr->pExpr, &pCsr->aDoclist, &pCsr->nDoclist, 0);
    sqlite3Fts3SegmentsClose(p);
    if( rc!=SQLITE_OK ) return rc;
    pCsr->pNextId = pCsr->aDoclist;
    pCsr->iPrevId = 0;




  }

  /* Compile a SELECT statement for this cursor. For a full-table-scan, the
  ** statement loops through all rows of the %_content table. For a
  ** full-text query or docid lookup, the statement retrieves a single
  ** row by docid.
  */
................................................................................
** message is written to context pContext and SQLITE_ERROR returned. The
** string passed via zFunc is used as part of the error message.
*/
static int fts3FunctionArg(
  sqlite3_context *pContext,      /* SQL function call context */
  const char *zFunc,              /* Function name */
  sqlite3_value *pVal,            /* argv[0] passed to function */
  Fts3Cursor **ppCsr              /* OUT: Store cursor handle here */
){
  Fts3Cursor *pRet;
  if( sqlite3_value_type(pVal)!=SQLITE_BLOB 
   || sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
  ){
    char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
    sqlite3_result_error(pContext, zErr, -1);
................................................................................
*/
static void fts3MatchinfoFunc(
  sqlite3_context *pContext,      /* SQLite function call context */
  int nVal,                       /* Size of argument array */
  sqlite3_value **apVal           /* Array of arguments */
){
  Fts3Cursor *pCsr;               /* Cursor handle passed through apVal[0] */

  assert( nVal==1 );





  if( SQLITE_OK==fts3FunctionArg(pContext, "matchinfo", apVal[0], &pCsr) ){
    sqlite3Fts3Matchinfo(pContext, pCsr);
  }
}

/*
** This routine implements the xFindFunction method for the FTS3
................................................................................
    return rc;
  }

  fts3DbExec(&rc, db,
    "ALTER TABLE %Q.'%q_content'  RENAME TO '%q_content';",
    p->zDb, p->zName, zName
  );

  if( p->bHasDocsize ){
    fts3DbExec(&rc, db,
      "ALTER TABLE %Q.'%q_docsize'  RENAME TO '%q_docsize';",
      p->zDb, p->zName, zName
    );
    fts3DbExec(&rc, db,
      "ALTER TABLE %Q.'%q_stat'  RENAME TO '%q_stat';",
................................................................................
  ** the two scalar functions. If this is successful, register the
  ** module with sqlite.
  */
  if( SQLITE_OK==rc 
   && SQLITE_OK==(rc = sqlite3Fts3InitHashTable(db, pHash, "fts3_tokenizer"))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "snippet", -1))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "offsets", 1))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "matchinfo", 1))
   && SQLITE_OK==(rc = sqlite3_overload_function(db, "optimize", 1))
  ){
    rc = sqlite3_create_module_v2(
        db, "fts3", &fts3Module, (void *)pHash, hashDestroy
    );
    if( rc==SQLITE_OK ){
      rc = sqlite3_create_module_v2(

Changes to test/fts3ao.test.

18
19
20
21
22
23
24


25
26
27
28
29
30
31
...
194
195
196
197
198
199
200















201
202
203
source $testdir/tester.tcl

# If SQLITE_ENABLE_FTS3 is not defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}



#---------------------------------------------------------------------
# These tests, fts3ao-1.*, test that ticket #2429 is fixed.
#
db eval {
  CREATE VIRTUAL TABLE t1 USING fts3(a, b, c);
  INSERT INTO t1(a, b, c) VALUES('one three four', 'one four', 'one four two');
................................................................................
      INSERT INTO t5 VALUES('Down came a jumbuck to drink at that billabong');
      ALTER TABLE t5 RENAME TO t6;
      INSERT INTO t6 VALUES('Down came the troopers, one, two, three');
    ROLLBACK;
    SELECT * FROM t5;
  }
} {{the quick brown fox} {jumped over the} {lazy dog}}
















finish_test








>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
source $testdir/tester.tcl

# If SQLITE_ENABLE_FTS3 is not defined, omit this file.
ifcapable !fts3 {
  finish_test
  return
}

set ::testprefix fts3ao

#---------------------------------------------------------------------
# These tests, fts3ao-1.*, test that ticket #2429 is fixed.
#
db eval {
  CREATE VIRTUAL TABLE t1 USING fts3(a, b, c);
  INSERT INTO t1(a, b, c) VALUES('one three four', 'one four', 'one four two');
................................................................................
      INSERT INTO t5 VALUES('Down came a jumbuck to drink at that billabong');
      ALTER TABLE t5 RENAME TO t6;
      INSERT INTO t6 VALUES('Down came the troopers, one, two, three');
    ROLLBACK;
    SELECT * FROM t5;
  }
} {{the quick brown fox} {jumped over the} {lazy dog}}

# Test that it is possible to rename an FTS4 table. Renaming an FTS4 table
# involves renaming the extra %_docsize and %_stat tables.
#
do_execsql_test 5.1 {
  CREATE VIRTUAL TABLE t7 USING FTS4;
  INSERT INTO t7 VALUES('coined by a German clinician');
  SELECT count(*) FROM sqlite_master WHERE name LIKE 't7%';
  SELECT count(*) FROM sqlite_master WHERE name LIKE 't8%';
} {6 0}
do_execsql_test 5.2 {
  ALTER TABLE t7 RENAME TO t8;
  SELECT count(*) FROM sqlite_master WHERE name LIKE 't7%';
  SELECT count(*) FROM sqlite_master WHERE name LIKE 't8%';
} {0 6}

finish_test

Changes to test/fts3defer.test.

327
328
329
330
331
332
333





334
335
336
337
338
339
340
...
372
373
374
375
376
377
378
379







380
381
382
383
  } {
    {0 2 3 8 0 1 36 2 0 0 58 9} 
    {0 0 0 9 0 1 13 2 0 1 16 2 0 2 19 8 0 1 53 2} 
    {0 1 4 2 0 0 20 9 0 1 30 2 0 1 33 2 0 2 48 8} 
    {0 1 17 2 0 1 20 2 0 1 26 2 0 0 29 9 0 2 39 8}
  }






  # The following block of tests runs normally with FTS3 or FTS4 without the
  # long doclists zeroed. And with OOM-injection for FTS4 with long doclists
  # zeroed. Change this by messing with the [set dmt_modes] commands above.
  #
  foreach DO_MALLOC_TEST $dmt_modes {
    
    # Phrase search.
................................................................................
    
    # snippet() function with multiple tokens.
    do_select_test 5.$DO_MALLOC_TEST.6 {
      SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'zm zhbrzadb'
    } {
      {0 0 0 2 0 0 6 2 0 0 9 2 0 1 12 8}
    }
  }







}


finish_test







>
>
>
>
>







 







|
>
>
>
>
>
>
>




327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
...
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
  } {
    {0 2 3 8 0 1 36 2 0 0 58 9} 
    {0 0 0 9 0 1 13 2 0 1 16 2 0 2 19 8 0 1 53 2} 
    {0 1 4 2 0 0 20 9 0 1 30 2 0 1 33 2 0 2 48 8} 
    {0 1 17 2 0 1 20 2 0 1 26 2 0 0 29 9 0 2 39 8}
  }

  do_select_test 4.3 {
    SELECT offsets(t1) FROM t1 
    WHERE t1 MATCH 'vgsld (hrlipdm OR (aapmve NEAR duszemmzl))'
  } {{0 0 0 5 0 1 15 7 0 0 36 5}}

  # The following block of tests runs normally with FTS3 or FTS4 without the
  # long doclists zeroed. And with OOM-injection for FTS4 with long doclists
  # zeroed. Change this by messing with the [set dmt_modes] commands above.
  #
  foreach DO_MALLOC_TEST $dmt_modes {
    
    # Phrase search.
................................................................................
    
    # snippet() function with multiple tokens.
    do_select_test 5.$DO_MALLOC_TEST.6 {
      SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'zm zhbrzadb'
    } {
      {0 0 0 2 0 0 6 2 0 0 9 2 0 1 12 8}
    }

    set DO_MALLOC_TEST 0
  }

  do_select_test 6.1 {
    SELECT rowid FROM t1 
    WHERE t1 MATCH 'vgsld (hrlipdm OR (aayxpmve duszemmzl))'
  } {10}
}


finish_test

Changes to test/fts3malloc.test.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53


proc normal_list {l} {
  set ret [list]
  foreach elem $l {lappend ret $elem}
  set ret
}


do_write_test fts3_malloc-1.1 sqlite_master {
  CREATE VIRTUAL TABLE ft1 USING fts3(a, b)
}
do_write_test fts3_malloc-1.2 sqlite_master {
  CREATE VIRTUAL TABLE ft2 USING fts3([a], [b]);
}







<







39
40
41
42
43
44
45

46
47
48
49
50
51
52


proc normal_list {l} {
  set ret [list]
  foreach elem $l {lappend ret $elem}
  set ret
}


do_write_test fts3_malloc-1.1 sqlite_master {
  CREATE VIRTUAL TABLE ft1 USING fts3(a, b)
}
do_write_test fts3_malloc-1.2 sqlite_master {
  CREATE VIRTUAL TABLE ft2 USING fts3([a], [b]);
}

Changes to test/fts3query.test.

20
21
22
23
24
25
26


27
28
29
30
31
32
33
...
125
126
127
128
129
130
131
132

































































133
134
# If this build does not include FTS3, skip the tests in this file.
#
ifcapable !fts3 { finish_test ; return }
source $testdir/malloc_common.tcl
source $testdir/fts3_common.tcl
set DO_MALLOC_TEST 0



do_test fts3query-1.1 {
  execsql {
    CREATE VIRTUAL TABLE t1 USING fts3(x);
    BEGIN;
      INSERT INTO t1 VALUES('The source code for SQLite is in the public');
  }
} {}
................................................................................
do_test fts3query-4.4 {
  eqp "SELECT t1.number FROM t1, bt WHERE t1.number=bt.rowid ORDER BY t1.date"
} {0 0 {TABLE t1 WITH INDEX i1 ORDER BY} 1 1 {TABLE bt USING PRIMARY KEY}}
do_test fts3query-4.5 {
  eqp "SELECT t1.number FROM bt, t1 WHERE t1.number=bt.rowid ORDER BY t1.date"
} {0 1 {TABLE t1 WITH INDEX i1 ORDER BY} 1 0 {TABLE bt USING PRIMARY KEY}}



































































finish_test








>
>







 








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# If this build does not include FTS3, skip the tests in this file.
#
ifcapable !fts3 { finish_test ; return }
source $testdir/malloc_common.tcl
source $testdir/fts3_common.tcl
set DO_MALLOC_TEST 0

set testprefix fts3query

do_test fts3query-1.1 {
  execsql {
    CREATE VIRTUAL TABLE t1 USING fts3(x);
    BEGIN;
      INSERT INTO t1 VALUES('The source code for SQLite is in the public');
  }
} {}
................................................................................
do_test fts3query-4.4 {
  eqp "SELECT t1.number FROM t1, bt WHERE t1.number=bt.rowid ORDER BY t1.date"
} {0 0 {TABLE t1 WITH INDEX i1 ORDER BY} 1 1 {TABLE bt USING PRIMARY KEY}}
do_test fts3query-4.5 {
  eqp "SELECT t1.number FROM bt, t1 WHERE t1.number=bt.rowid ORDER BY t1.date"
} {0 1 {TABLE t1 WITH INDEX i1 ORDER BY} 1 0 {TABLE bt USING PRIMARY KEY}}


# Test that calling matchinfo() with the wrong number of arguments, or with
# an invalid argument returns an error.
#
do_execsql_test 5.1 {
  CREATE VIRTUAL TABLE t2 USING FTS4;
  INSERT INTO t2 VALUES('it was the first time in history');
}
do_select_tests 5.2 -errorformat {
  wrong number of arguments to function %s()
} {
  1 "SELECT matchinfo() FROM t2 WHERE t2 MATCH 'history'"       matchinfo
  2 "SELECT matchinfo(t2, t2) FROM t2 WHERE t2 MATCH 'history'" matchinfo

  3 "SELECT snippet(t2, 1, 2, 3, 4, 5, 6) FROM t2 WHERE t2 MATCH 'history'" 
    snippet
}
do_select_tests 5.3 -errorformat {
  illegal first argument to %s
} {
  1 "SELECT matchinfo(content) FROM t2 WHERE t2 MATCH 'history'" matchinfo
  2 "SELECT offsets(content) FROM t2 WHERE t2 MATCH 'history'"   offsets
  3 "SELECT snippet(content) FROM t2 WHERE t2 MATCH 'history'"   snippet
  4 "SELECT optimize(content) FROM t2 WHERE t2 MATCH 'history'"  optimize
}
do_execsql_test 5.4.0 { UPDATE t2_content SET c0content = X'1234' }
do_select_tests 5.4 -errorformat {
  illegal first argument to %s
} {
  1 "SELECT matchinfo(content) FROM t2 WHERE t2 MATCH 'history'" matchinfo
  2 "SELECT offsets(content) FROM t2 WHERE t2 MATCH 'history'"   offsets
  3 "SELECT snippet(content) FROM t2 WHERE t2 MATCH 'history'"   snippet
  4 "SELECT optimize(content) FROM t2 WHERE t2 MATCH 'history'"  optimize
}
do_execsql_test 5.5 { DROP TABLE t2 }

# Test the snippet() function with 1 to 6 arguments.
# 
do_execsql_test 6.1 {
  CREATE VIRTUAL TABLE t3 USING FTS4(a, b);
  INSERT INTO t3 VALUES('no gestures', 'another intriguing discovery by observing the hand gestures (called beats) people make while speaking. Research has shown that such gestures do more than add visual emphasis to our words (many people gesture while they''re on the telephone, for example); it seems they actually help our brains find words');
}

do_select_tests 6.2 {
  1 "SELECT snippet(t3) FROM t3 WHERE t3 MATCH 'gestures'"
  {{<b>...</b>hand <b>gestures</b> (called beats) people make while speaking. Research has shown that such <b>gestures</b> do<b>...</b>}}

  2 "SELECT snippet(t3, 'XXX') FROM t3 WHERE t3 MATCH 'gestures'" 
  {{<b>...</b>hand XXXgestures</b> (called beats) people make while speaking. Research has shown that such XXXgestures</b> do<b>...</b>}}

  3 "SELECT snippet(t3, 'XXX', 'YYY') FROM t3 WHERE t3 MATCH 'gestures'" 
  {{<b>...</b>hand XXXgesturesYYY (called beats) people make while speaking. Research has shown that such XXXgesturesYYY do<b>...</b>}}

  4 "SELECT snippet(t3, 'XXX', 'YYY', 'ZZZ') FROM t3 WHERE t3 MATCH 'gestures'" 
  {{ZZZhand XXXgesturesYYY (called beats) people make while speaking. Research has shown that such XXXgesturesYYY doZZZ}}

  5 "SELECT snippet(t3, 'XXX', 'YYY', 'ZZZ', 1) FROM t3 WHERE t3 MATCH 'gestures'" 
  {{ZZZhand XXXgesturesYYY (called beats) people make while speaking. Research has shown that such XXXgesturesYYY doZZZ}}

  6 "SELECT snippet(t3, 'XXX', 'YYY', 'ZZZ', 0) FROM t3 WHERE t3 MATCH 'gestures'" 
  {{no XXXgesturesYYY}}

  7 "SELECT snippet(t3, 'XXX', 'YYY', 'ZZZ', 1, 5) FROM t3 WHERE t3 MATCH 'gestures'" 
  {{ZZZthe hand XXXgesturesYYY (called beatsZZZ}}
}

finish_test

Changes to test/fts3snippet.test.

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
...
455
456
457
458
459
460
461
462
463
464
465

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If SQLITE_ENABLE_FTS3 is not defined, omit this file.
ifcapable !fts3 { finish_test ; return }
source $testdir/fts3_common.tcl
source $testdir/malloc_common.tcl

set sqlite_fts3_enable_parentheses 1
set DO_MALLOC_TEST 0

# Transform the list $L to its "normal" form. So that it can be compared to
# another list with the same set of elements using [string compare].
#
................................................................................
  do_select_test $T.10.5 {
    SELECT length(matchinfo(ft)), typeof(matchinfo(ft)) FROM ft;
  } {0 blob 0 blob 0 blob}
  do_select_test $T.10.6 {
    SELECT length(matchinfo(ft)), typeof(matchinfo(ft)) FROM ft WHERE rowid = $r
  } {0 blob}
}


set sqlite_fts3_enable_parentheses 0
finish_test







<







 







<



16
17
18
19
20
21
22

23
24
25
26
27
28
29
...
454
455
456
457
458
459
460

461
462
463

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# If SQLITE_ENABLE_FTS3 is not defined, omit this file.
ifcapable !fts3 { finish_test ; return }
source $testdir/fts3_common.tcl


set sqlite_fts3_enable_parentheses 1
set DO_MALLOC_TEST 0

# Transform the list $L to its "normal" form. So that it can be compared to
# another list with the same set of elements using [string compare].
#
................................................................................
  do_select_test $T.10.5 {
    SELECT length(matchinfo(ft)), typeof(matchinfo(ft)) FROM ft;
  } {0 blob 0 blob 0 blob}
  do_select_test $T.10.6 {
    SELECT length(matchinfo(ft)), typeof(matchinfo(ft)) FROM ft WHERE rowid = $r
  } {0 blob}
}


set sqlite_fts3_enable_parentheses 0
finish_test

Changes to test/malloc_common.tcl.

109
110
111
112
113
114
115


116
117
118
119
120
121
122
proc do_faultsim_test {name args} {
  global FAULTSIM
  
  set DEFAULT(-faults)        [array names FAULTSIM]
  set DEFAULT(-prep)          ""
  set DEFAULT(-body)          ""
  set DEFAULT(-test)          ""



  array set O [array get DEFAULT]
  array set O $args
  foreach o [array names O] {
    if {[info exists DEFAULT($o)]==0} { error "unknown option: $o" }
  }








>
>







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
proc do_faultsim_test {name args} {
  global FAULTSIM
  
  set DEFAULT(-faults)        [array names FAULTSIM]
  set DEFAULT(-prep)          ""
  set DEFAULT(-body)          ""
  set DEFAULT(-test)          ""

  fix_testname name

  array set O [array get DEFAULT]
  array set O $args
  foreach o [array names O] {
    if {[info exists DEFAULT($o)]==0} { error "unknown option: $o" }
  }

Changes to test/permutations.test.

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169


170
171
172
173
174
175
176
  All multi-threaded tests.
} -files {
  notify2.test   thread001.test thread002.test thread003.test 
  thread004.test thread005.test walthread.test
}

test_suite "fts3" -prefix "" -description {
  All FTS3 tests except fts3malloc.test and fts3rnd.test.
} -files {
  fts3aa.test fts3ab.test fts3ac.test fts3ad.test fts3ae.test
  fts3af.test fts3ag.test fts3ah.test fts3ai.test fts3aj.test
  fts3ak.test fts3al.test fts3am.test fts3an.test fts3ao.test
  fts3atoken.test fts3b.test fts3c.test fts3cov.test fts3d.test
  fts3e.test fts3expr.test fts3expr2.test fts3near.test 
  fts3query.test fts3snippet.test fts3defer.test fts3defer2.test


}


lappend ::testsuitelist xxx
#-------------------------------------------------------------------------
# Define the coverage related test suites:
#







|





|
|
>
>







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
  All multi-threaded tests.
} -files {
  notify2.test   thread001.test thread002.test thread003.test 
  thread004.test thread005.test walthread.test
}

test_suite "fts3" -prefix "" -description {
  All FTS3 tests except fts3rnd.test.
} -files {
  fts3aa.test fts3ab.test fts3ac.test fts3ad.test fts3ae.test
  fts3af.test fts3ag.test fts3ah.test fts3ai.test fts3aj.test
  fts3ak.test fts3al.test fts3am.test fts3an.test fts3ao.test
  fts3atoken.test fts3b.test fts3c.test fts3cov.test fts3d.test
  fts3defer.test fts3defer2.test fts3e.test fts3expr.test fts3expr2.test 
  fts3near.test fts3query.test fts3shared.test fts3snippet.test 

  fts3fault.test fts3malloc.test
}


lappend ::testsuitelist xxx
#-------------------------------------------------------------------------
# Define the coverage related test suites:
#

Changes to test/tester.tcl.

1371
1372
1373
1374
1375
1376
1377

}

# If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set
# to non-zero, then set the global variable $AUTOVACUUM to 1.
set AUTOVACUUM $sqlite_options(default_autovacuum)

source $testdir/thread_common.tcl








>
1371
1372
1373
1374
1375
1376
1377
1378
}

# If the library is compiled with the SQLITE_DEFAULT_AUTOVACUUM macro set
# to non-zero, then set the global variable $AUTOVACUUM to 1.
set AUTOVACUUM $sqlite_options(default_autovacuum)

source $testdir/thread_common.tcl
source $testdir/malloc_common.tcl