SQLite

Check-in [927d9a64e1]
Login

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

Overview
Comment:Further test coverage improvements for fts5.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | fts5
Files: files | file ages | folders
SHA1: 927d9a64e13c6b768f0a15475713192fcfaaf9e7
User & Date: dan 2015-05-16 20:04:43.177
Context
2015-05-18
17:50
Improve test coverage of fts5_config.c. (check-in: 47dbfadb99 user: dan tags: fts5)
2015-05-16
20:04
Further test coverage improvements for fts5. (check-in: 927d9a64e1 user: dan tags: fts5)
2015-05-15
18:13
Improve test coverage of fts5_index.c. (check-in: 7aea8c6d99 user: dan tags: fts5)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/fts5/fts5.c.
1643
1644
1645
1646
1647
1648
1649








1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
  sqlite3_value **argv
){
  assert( pCsr->pAux==0 );
  pCsr->pAux = pAux;
  pAux->xFunc(&sFts5Api, (Fts5Context*)pCsr, context, argc, argv);
  pCsr->pAux = 0;
}









static void fts5ApiCallback(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){

  Fts5Auxiliary *pAux;
  Fts5Cursor *pCsr;
  i64 iCsrId;

  assert( argc>=1 );
  pAux = (Fts5Auxiliary*)sqlite3_user_data(context);
  iCsrId = sqlite3_value_int64(argv[0]);

  for(pCsr=pAux->pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
    if( pCsr->iCsrId==iCsrId ) break;
  }
  if( pCsr==0 ){
    char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId);
    sqlite3_result_error(context, zErr, -1);
    sqlite3_free(zErr);
  }else{
    fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]);
  }







>
>
>
>
>
>
>
>















|
<
<







1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673


1674
1675
1676
1677
1678
1679
1680
  sqlite3_value **argv
){
  assert( pCsr->pAux==0 );
  pCsr->pAux = pAux;
  pAux->xFunc(&sFts5Api, (Fts5Context*)pCsr, context, argc, argv);
  pCsr->pAux = 0;
}

static Fts5Cursor *fts5CursorFromCsrid(Fts5Global *pGlobal, i64 iCsrId){
  Fts5Cursor *pCsr;
  for(pCsr=pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
    if( pCsr->iCsrId==iCsrId ) break;
  }
  return pCsr;
}

static void fts5ApiCallback(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){

  Fts5Auxiliary *pAux;
  Fts5Cursor *pCsr;
  i64 iCsrId;

  assert( argc>=1 );
  pAux = (Fts5Auxiliary*)sqlite3_user_data(context);
  iCsrId = sqlite3_value_int64(argv[0]);

  pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId);


  if( pCsr==0 ){
    char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId);
    sqlite3_result_error(context, zErr, -1);
    sqlite3_free(zErr);
  }else{
    fts5ApiInvoke(pAux, pCsr, context, argc-1, &argv[1]);
  }
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
*/
Fts5Index *sqlite3Fts5IndexFromCsrid(
  Fts5Global *pGlobal, 
  i64 iCsrId, 
  int *pnCol
){
  Fts5Cursor *pCsr;
  Fts5Index *pIndex = 0;

  for(pCsr=pGlobal->pCsr; pCsr; pCsr=pCsr->pNext){
    if( pCsr->iCsrId==iCsrId ) break;
  }
  if( pCsr ){
    Fts5Table *pTab = (Fts5Table*)pCsr->base.pVtab;
    pIndex = pTab->pIndex;
    *pnCol = pTab->pConfig->nCol;
  }

  return pIndex;
}

/*
** Return a "position-list blob" corresponding to the current position of
** cursor pCsr via sqlite3_result_blob(). A position-list blob contains
** the current position-list for each phrase in the query associated with
** cursor pCsr.







<
|
<
<
|
|
|
<
|
|
<
|







1690
1691
1692
1693
1694
1695
1696

1697


1698
1699
1700

1701
1702

1703
1704
1705
1706
1707
1708
1709
1710
*/
Fts5Index *sqlite3Fts5IndexFromCsrid(
  Fts5Global *pGlobal, 
  i64 iCsrId, 
  int *pnCol
){
  Fts5Cursor *pCsr;

  Fts5Table *pTab;



  pCsr = fts5CursorFromCsrid(pGlobal, iCsrId);
  pTab = (Fts5Table*)pCsr->base.pVtab;

  *pnCol = pTab->pConfig->nCol;


  return pTab->pIndex;
}

/*
** Return a "position-list blob" corresponding to the current position of
** cursor pCsr via sqlite3_result_blob(). A position-list blob contains
** the current position-list for each phrase in the query associated with
** cursor pCsr.
Changes to ext/fts5/fts5_expr.c.
1394
1395
1396
1397
1398
1399
1400

1401
1402
1403
1404
1405
1406
1407
  char *zRet = 0;
  if( pExpr->eType==FTS5_STRING ){
    Fts5ExprNearset *pNear = pExpr->pNear;
    int i; 
    int iTerm;

    zRet = fts5PrintfAppend(zRet, "[%s ", zNearsetCmd);

    if( pNear->iCol>=0 ){
      zRet = fts5PrintfAppend(zRet, "-col %d ", pNear->iCol);
      if( zRet==0 ) return 0;
    }

    if( pNear->nPhrase>1 ){
      zRet = fts5PrintfAppend(zRet, "-near %d ", pNear->nNear);







>







1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
  char *zRet = 0;
  if( pExpr->eType==FTS5_STRING ){
    Fts5ExprNearset *pNear = pExpr->pNear;
    int i; 
    int iTerm;

    zRet = fts5PrintfAppend(zRet, "[%s ", zNearsetCmd);
    if( zRet==0 ) return 0;
    if( pNear->iCol>=0 ){
      zRet = fts5PrintfAppend(zRet, "-col %d ", pNear->iCol);
      if( zRet==0 ) return 0;
    }

    if( pNear->nPhrase>1 ){
      zRet = fts5PrintfAppend(zRet, "-near %d ", pNear->nNear);
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438



1439
1440
1441
1442
1443
1444
1445
        zRet = fts5PrintfAppend(zRet, "%s%s", iTerm==0?"":" ", zTerm);
      }

      if( zRet ) zRet = fts5PrintfAppend(zRet, "}");
      if( zRet==0 ) return 0;
    }

    if( zRet ) zRet = fts5PrintfAppend(zRet, "]");
    if( zRet==0 ) return 0;

  }else{
    char *zOp = 0;
    char *z1 = 0;
    char *z2 = 0;
    switch( pExpr->eType ){
      case FTS5_AND: zOp = "&&"; break;
      case FTS5_NOT: zOp = "&& !"; break;
      case FTS5_OR:  zOp = "||"; break;
      default: assert( 0 );



    }

    z1 = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pLeft);
    z2 = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pRight);
    if( z1 && z2 ){
      int b1 = pExpr->pLeft->eType!=FTS5_STRING;
      int b2 = pExpr->pRight->eType!=FTS5_STRING;







|









<
|
>
>
>







1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437

1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
        zRet = fts5PrintfAppend(zRet, "%s%s", iTerm==0?"":" ", zTerm);
      }

      if( zRet ) zRet = fts5PrintfAppend(zRet, "}");
      if( zRet==0 ) return 0;
    }

    zRet = fts5PrintfAppend(zRet, "]");
    if( zRet==0 ) return 0;

  }else{
    char *zOp = 0;
    char *z1 = 0;
    char *z2 = 0;
    switch( pExpr->eType ){
      case FTS5_AND: zOp = "&&"; break;
      case FTS5_NOT: zOp = "&& !"; break;

      default: 
        assert( pExpr->eType==FTS5_OR );
        zOp = "||"; 
        break;
    }

    z1 = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pLeft);
    z2 = fts5ExprPrintTcl(pConfig, zNearsetCmd, pExpr->pRight);
    if( z1 && z2 ){
      int b1 = pExpr->pLeft->eType!=FTS5_STRING;
      int b2 = pExpr->pRight->eType!=FTS5_STRING;
1500
1501
1502
1503
1504
1505
1506
1507
1508



1509
1510
1511
1512
1513
1514
1515
  }else{
    char *zOp = 0;
    char *z1 = 0;
    char *z2 = 0;
    switch( pExpr->eType ){
      case FTS5_AND: zOp = "AND"; break;
      case FTS5_NOT: zOp = "NOT"; break;
      case FTS5_OR:  zOp = "OR"; break;
      default: assert( 0 );



    }

    z1 = fts5ExprPrint(pConfig, pExpr->pLeft);
    z2 = fts5ExprPrint(pConfig, pExpr->pRight);
    if( z1 && z2 ){
      int b1 = pExpr->pLeft->eType!=FTS5_STRING;
      int b2 = pExpr->pRight->eType!=FTS5_STRING;







<
|
>
>
>







1503
1504
1505
1506
1507
1508
1509

1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
  }else{
    char *zOp = 0;
    char *z1 = 0;
    char *z2 = 0;
    switch( pExpr->eType ){
      case FTS5_AND: zOp = "AND"; break;
      case FTS5_NOT: zOp = "NOT"; break;

      default:  
        assert( pExpr->eType==FTS5_OR );
        zOp = "OR"; 
        break;
    }

    z1 = fts5ExprPrint(pConfig, pExpr->pLeft);
    z2 = fts5ExprPrint(pConfig, pExpr->pRight);
    if( z1 && z2 ){
      int b1 = pExpr->pLeft->eType!=FTS5_STRING;
      int b2 = pExpr->pRight->eType!=FTS5_STRING;
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674


1675
1676
1677
1678
}

/*
** This function is used to access the current position list for phrase
** iPhrase.
*/
int sqlite3Fts5ExprPoslist(Fts5Expr *pExpr, int iPhrase, const u8 **pa){
  if( iPhrase>=0 && iPhrase<pExpr->nPhrase ){
    Fts5ExprPhrase *pPhrase = pExpr->apExprPhrase[iPhrase];
    Fts5ExprNode *pNode = pPhrase->pNode;
    if( pNode->bEof==0 && pNode->iRowid==pExpr->pRoot->iRowid ){
      *pa = pPhrase->poslist.p;
      return pPhrase->poslist.n;
    }
  }
  *pa = 0;


  return 0;
}

#endif /* SQLITE_ENABLE_FTS5 */







|
|
|
|
|
|
|
<
|
>
>
|



1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677

1678
1679
1680
1681
1682
1683
1684
}

/*
** This function is used to access the current position list for phrase
** iPhrase.
*/
int sqlite3Fts5ExprPoslist(Fts5Expr *pExpr, int iPhrase, const u8 **pa){
  int nRet;
  Fts5ExprPhrase *pPhrase = pExpr->apExprPhrase[iPhrase];
  Fts5ExprNode *pNode = pPhrase->pNode;
  if( pNode->bEof==0 && pNode->iRowid==pExpr->pRoot->iRowid ){
    *pa = pPhrase->poslist.p;
    nRet = pPhrase->poslist.n;
  }else{

    *pa = 0;
    nRet = 0;
  }
  return nRet;
}

#endif /* SQLITE_ENABLE_FTS5 */
Changes to ext/fts5/test/fts5ac.test.
439
440
441
442
443
444
445




446
447
    } {
      set res [matchdata 0 $expr $bAsc]
      do_execsql_test $tn2.6.$bAsc.$tn.[llength $res] $sql $res
    }
  }
}





finish_test








>
>
>
>


439
440
441
442
443
444
445
446
447
448
449
450
451
    } {
      set res [matchdata 0 $expr $bAsc]
      do_execsql_test $tn2.6.$bAsc.$tn.[llength $res] $sql $res
    }
  }
}

do_execsql_test 3.1 {
  SELECT fts5_expr_tcl('a AND b');
} {{[nearset -- {a}] && [nearset -- {b}]}}

finish_test

Changes to ext/fts5/test/fts5aux.test.
176
177
178
179
180
181
182



















183
184
185
  SELECT my_rowid(z) FROM e11 WHERE e11 MATCH 'b'
} {1 {no such cursor: 45}}

do_catchsql_test 6.2 {
  SELECT my_rowid(y) FROM e11 WHERE e11 MATCH 'b'
} {1 {no such cursor: 0}}





















finish_test








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



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
202
203
204
  SELECT my_rowid(z) FROM e11 WHERE e11 MATCH 'b'
} {1 {no such cursor: 45}}

do_catchsql_test 6.2 {
  SELECT my_rowid(y) FROM e11 WHERE e11 MATCH 'b'
} {1 {no such cursor: 0}}

#-------------------------------------------------------------------------
# Test passing an out-of-range phrase number to xPhraseSize (should 
# return 0).
#
proc my_phrasesize {cmd iPhrase} { $cmd xPhraseSize $iPhrase }
sqlite3_fts5_create_function db my_phrasesize my_phrasesize

do_execsql_test 7.1 {
  CREATE VIRTUAL TABLE t1 USING fts5(a);
  INSERT INTO t1 VALUES('a b c');
}
do_execsql_test 7.2 {
  SELECT 
    my_phrasesize(t1, -1),
    my_phrasesize(t1, 0),
    my_phrasesize(t1, 1),
    my_phrasesize(t1, 2)
  FROM t1 WHERE t1 MATCH 'a OR b+c'
} {0 1 2 0}

finish_test

Changes to ext/fts5/test/fts5fault4.test.
297
298
299
300
301
302
303


304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333

334





335
336
337
338
}

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}
}



#-------------------------------------------------------------------------
# OOM in fts5_expr() SQL function.
#
reset_db
do_execsql_test 10.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 10.1 -faults oom-t* -body {
  db one { SELECT fts5_expr('a AND b NEAR(a b)') }
} -test {
  faultsim_test_result {0 {"a" AND ("b" AND NEAR("a" "b", 10))}} 
}

}


#do_faultsim_test 10.2 -faults oom-t* -body {
#  db one { SELECT fts5_expr_tcl('x:"a b c" AND b NEAR(a b)', 'ns', 'x') }
#} -test {
#  set res {[ns -col 0 -- {a b c}] && ([ns -- {b}] && [ns -near 10 -- {a} {b}]}
#  faultsim_test_result [list 0 $res]

#}







finish_test








>
>




<
<
<
<
<
<
<
<
<
<
<
<






<
<
<
|
|
|
|
|
>
|
>
>
>
>
>




297
298
299
300
301
302
303
304
305
306
307
308
309












310
311
312
313
314
315



316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
}

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}
}

}

#-------------------------------------------------------------------------
# OOM in fts5_expr() SQL function.
#












do_faultsim_test 10.1 -faults oom-t* -body {
  db one { SELECT fts5_expr('a AND b NEAR(a b)') }
} -test {
  faultsim_test_result {0 {"a" AND ("b" AND NEAR("a" "b", 10))}} 
}




do_faultsim_test 10.2 -faults oom-t* -body {
  db one { SELECT fts5_expr_tcl('x:"a b c" AND b NEAR(a b)', 'ns', 'x') }
} -test {
  set res {[ns -col 0 -- {a b c}] && ([ns -- {b}] && [ns -near 10 -- {a} {b}])}
  faultsim_test_result [list 0 $res]
}

do_faultsim_test 10.3 -faults oom-t* -body {
  db one { SELECT fts5_expr('x:a', 'x') }
} -test {
  faultsim_test_result {0 {x : "a"}}
}


finish_test

Changes to ext/fts5/test/fts5hash.test.
72
73
74
75
76
77
78

79
80
81
82













83
84
85
86
87
88
89
}

set hash [sqlite3_fts5_token_hash 1024 xyz]
set vocab [build_vocab1 -prefix xyz -hash $hash]
lappend vocab xyz

do_execsql_test 1.1 {

  BEGIN;
    WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100)
    INSERT INTO eee SELECT r($vocab, 5), r($vocab, 7) FROM ii;
    INSERT INTO eee(eee) VALUES('integrity-check');













  COMMIT;
  INSERT INTO eee(eee) VALUES('integrity-check');
}


finish_test








>




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



<



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

100
101
102
}

set hash [sqlite3_fts5_token_hash 1024 xyz]
set vocab [build_vocab1 -prefix xyz -hash $hash]
lappend vocab xyz

do_execsql_test 1.1 {
  CREATE VIRTUAL TABLE vocab USING fts5vocab(eee, 'row'); 
  BEGIN;
    WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100)
    INSERT INTO eee SELECT r($vocab, 5), r($vocab, 7) FROM ii;
    INSERT INTO eee(eee) VALUES('integrity-check');
}

do_test 1.2 {
  db eval { SELECT term, doc FROM vocab } {
    set nRow [db one {SELECT count(*) FROM eee WHERE eee MATCH $term}]
    if {$nRow != $doc} {
      error "term=$term fts5vocab=$doc cnt=$nRow"
    }
  }
  set {} {}
} {}

do_execsql_test 1.3 {
  COMMIT;
  INSERT INTO eee(eee) VALUES('integrity-check');
}


finish_test

Changes to test/malloc_common.tcl.
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
# [faultsim_test_result] command created by [do_faultsim_test] and used
# by -test scripts.
#
proc faultsim_test_result_int {args} {
  upvar testrc testrc testresult testresult testnfail testnfail
  set t [list $testrc $testresult]
  set r $args
  if { ($testnfail==0 && $t != [lindex $r 0]) || [lsearch $r $t]<0 } {
    error "nfail=$testnfail rc=$testrc result=$testresult list=$r"
  }
}

#--------------------------------------------------------------------------
# Usage do_one_faultsim_test NAME ?OPTIONS...? 
#







|







288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
# [faultsim_test_result] command created by [do_faultsim_test] and used
# by -test scripts.
#
proc faultsim_test_result_int {args} {
  upvar testrc testrc testresult testresult testnfail testnfail
  set t [list $testrc $testresult]
  set r $args
  if { ($testnfail==0 && $t != [lindex $r 0]) || [lsearch -exact $r $t]<0 } {
    error "nfail=$testnfail rc=$testrc result=$testresult list=$r"
  }
}

#--------------------------------------------------------------------------
# Usage do_one_faultsim_test NAME ?OPTIONS...? 
#