SQLite

Check-in [95e09b20e9]
Login

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

Overview
Comment:Fix a performance problem in queries that use "ORDER BY rowid DESC" and one or more FTS auxiliary functions.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | vtab-conflict
Files: files | file ages | folders
SHA1: 95e09b20e9aad28f829c8950f3632debe473070a
User & Date: dan 2011-05-04 15:41:18.367
Context
2011-05-04
16:30
Fix a couple of compiler warnings in the FTS code. (Closed-Leaf check-in: 1a11335970 user: dan tags: vtab-conflict)
15:41
Fix a performance problem in queries that use "ORDER BY rowid DESC" and one or more FTS auxiliary functions. (check-in: 95e09b20e9 user: dan tags: vtab-conflict)
12:52
Optimize "ORDER BY rowid/docid DESC/ASC" clauses on FTS tables. (check-in: 13395121e3 user: dan tags: vtab-conflict)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/fts3/fts3.c.
3316
3317
3318
3319
3320
3321
3322



















3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340

3341
3342








3343

3344
3345
3346
3347
3348


3349
3350
3351
3352
3353




3354
3355
3356
3357
3358
3359
3360
  assert( pCsr->eEvalmode==FTS3_EVAL_NEXT );
  assert( pExpr->eType==FTSQUERY_PHRASE && pExpr->pPhrase );
  pCsr->eEvalmode = FTS3_EVAL_MATCHINFO;
  rc = fts3EvalExpr(pCsr, pExpr, paDoclist, pnDoclist, 1);
  pCsr->eEvalmode = FTS3_EVAL_NEXT;
  return rc;
}




















/*
** After ExprLoadDoclist() (see above) has been called, this function is
** used to iterate/search through the position lists that make up the doclist
** stored in pExpr->aDoclist.
*/
char *sqlite3Fts3FindPositions(
  Fts3Cursor *pCursor,            /* Associate FTS3 cursor */
  Fts3Expr *pExpr,                /* Access this expressions doclist */
  sqlite3_int64 iDocid,           /* Docid associated with requested pos-list */
  int iCol                        /* Column of requested pos-list */
){
  assert( pExpr->isLoaded );
  if( pExpr->aDoclist ){
    char *pEnd = &pExpr->aDoclist[pExpr->nDoclist];
    char *pCsr;

    if( pExpr->pCurrent==0 || pCursor->desc ){

      pExpr->pCurrent = pExpr->aDoclist;
      pExpr->iCurrent = 0;








      pExpr->pCurrent += sqlite3Fts3GetVarint(pExpr->pCurrent,&pExpr->iCurrent);

    }
    pCsr = pExpr->pCurrent;
    assert( pCsr );

    while( pCsr<pEnd ){


      if( pExpr->iCurrent<iDocid ){
        fts3PoslistCopy(0, &pCsr);
        if( pCsr<pEnd ){
          fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
        }




        pExpr->pCurrent = pCsr;
      }else{
        if( pExpr->iCurrent==iDocid ){
          int iThis = 0;
          if( iCol<0 ){
            /* If iCol is negative, return a pointer to the start of the
            ** position-list (instead of a pointer to the start of a list







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

















|
>
|
|
>
>
>
>
>
>
>
>
|
>




|
>
>
|




>
>
>
>







3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
  assert( pCsr->eEvalmode==FTS3_EVAL_NEXT );
  assert( pExpr->eType==FTSQUERY_PHRASE && pExpr->pPhrase );
  pCsr->eEvalmode = FTS3_EVAL_MATCHINFO;
  rc = fts3EvalExpr(pCsr, pExpr, paDoclist, pnDoclist, 1);
  pCsr->eEvalmode = FTS3_EVAL_NEXT;
  return rc;
}


/*
** When called, *ppPoslist must point to the byte immediately following the
** end of a position-list. i.e. ( (*ppPoslist)[-1]==POS_END ). This function
** moves *ppPoslist so that it instead points to the first byte of the
** position list.
*/
static void fts3ReversePoslist(char *pStart, char **ppPoslist){
  char *p = &(*ppPoslist)[-3];
  char c = p[1];
  while( p>=pStart && (*p & 0x80) | c ){ 
    c = *p--; 
  }
  if( p>pStart ){ p = &p[2]; }
  while( *p++&0x80 );
  *ppPoslist = p;
}


/*
** After ExprLoadDoclist() (see above) has been called, this function is
** used to iterate/search through the position lists that make up the doclist
** stored in pExpr->aDoclist.
*/
char *sqlite3Fts3FindPositions(
  Fts3Cursor *pCursor,            /* Associate FTS3 cursor */
  Fts3Expr *pExpr,                /* Access this expressions doclist */
  sqlite3_int64 iDocid,           /* Docid associated with requested pos-list */
  int iCol                        /* Column of requested pos-list */
){
  assert( pExpr->isLoaded );
  if( pExpr->aDoclist ){
    char *pEnd = &pExpr->aDoclist[pExpr->nDoclist];
    char *pCsr;

    if( pExpr->pCurrent==0 ){
      if( pCursor->desc==0 ){
        pExpr->pCurrent = pExpr->aDoclist;
        pExpr->iCurrent = 0;
        fts3GetDeltaVarint(&pExpr->pCurrent, &pExpr->iCurrent);
      }else{
        pCsr = pExpr->aDoclist;
        while( pCsr<pEnd ){
          fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
          fts3PoslistCopy(0, &pCsr);
        }
        fts3ReversePoslist(pExpr->aDoclist, &pCsr);
        pExpr->pCurrent = pCsr;
      }
    }
    pCsr = pExpr->pCurrent;
    assert( pCsr );

    while( (pCursor->desc==0 && pCsr<pEnd) 
        || (pCursor->desc && pCsr>pExpr->aDoclist) 
    ){
      if( pCursor->desc==0 && pExpr->iCurrent<iDocid ){
        fts3PoslistCopy(0, &pCsr);
        if( pCsr<pEnd ){
          fts3GetDeltaVarint(&pCsr, &pExpr->iCurrent);
        }
        pExpr->pCurrent = pCsr;
      }else if( pCursor->desc && pExpr->iCurrent>iDocid ){
        fts3GetReverseDeltaVarint(&pCsr, pExpr->aDoclist, &pExpr->iCurrent);
        fts3ReversePoslist(pExpr->aDoclist, &pCsr);
        pExpr->pCurrent = pCsr;
      }else{
        if( pExpr->iCurrent==iDocid ){
          int iThis = 0;
          if( iCol<0 ){
            /* If iCol is negative, return a pointer to the start of the
            ** position-list (instead of a pointer to the start of a list
Changes to test/fts3sort.test.
54
55
56
57
58
59
60

61
62
63
64
65
66
67
  3   "SELECT docid, * FROM t1 WHERE t1 MATCH 'a*'"
  4   "SELECT docid, quote(matchinfo(t1)) FROM t1 WHERE t1 MATCH 'a*'"
  5   "SELECT docid, quote(matchinfo(t1,'pcnxals')) FROM t1 WHERE t1 MATCH 'b*'"
  6   "SELECT docid, * FROM t1 WHERE t1 MATCH 'a* b* c*'"
  7   "SELECT docid, * FROM t1 WHERE t1 MATCH 'aa OR da'"
  8   "SELECT docid, * FROM t1 WHERE t1 MATCH 'nosuchtoken'"
  9   "SELECT docid, snippet(t1) FROM t1 WHERE t1 MATCH 'aa OR da'"

} {

  unset -nocomplain A B C D
  set A_list [list]
  set B_list [list]
  set C_list [list]
  set D_list [list]







>







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  3   "SELECT docid, * FROM t1 WHERE t1 MATCH 'a*'"
  4   "SELECT docid, quote(matchinfo(t1)) FROM t1 WHERE t1 MATCH 'a*'"
  5   "SELECT docid, quote(matchinfo(t1,'pcnxals')) FROM t1 WHERE t1 MATCH 'b*'"
  6   "SELECT docid, * FROM t1 WHERE t1 MATCH 'a* b* c*'"
  7   "SELECT docid, * FROM t1 WHERE t1 MATCH 'aa OR da'"
  8   "SELECT docid, * FROM t1 WHERE t1 MATCH 'nosuchtoken'"
  9   "SELECT docid, snippet(t1) FROM t1 WHERE t1 MATCH 'aa OR da'"
  10  "SELECT docid, snippet(t1) FROM t1 WHERE t1 MATCH 'aa OR nosuchtoken'"
} {

  unset -nocomplain A B C D
  set A_list [list]
  set B_list [list]
  set C_list [list]
  set D_list [list]