/ Check-in [f4f7196b]
Login

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

Overview
Comment:Use integer handles for fts3 cursors for a small performance improvement.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | union-vtab | fts3-int-cursor
Files: files | file ages | folders
SHA3-256:f4f7196b877001098278f2a3ee4c6839c5f130c638c930decb559d24ab7a20c1
User & Date: dan 2017-07-17 09:30:15
Context
2017-07-17
09:30
Use integer handles for fts3 cursors for a small performance improvement. Closed-Leaf check-in: f4f7196b user: dan tags: union-vtab, fts3-int-cursor
2017-07-15
20:48
Add the "unionvtab" virtual table extension in ext/misc/unionvtab.c. check-in: 62a86aa6 user: dan tags: union-vtab
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3.c.

304
305
306
307
308
309
310








311
312
313
314
315
316
317
....
1667
1668
1669
1670
1671
1672
1673

1674
1675
1676
1677
1678
1679
1680
1681
1682

1683
1684
1685
1686






1687
1688
1689
1690
1691
1692
1693
....
1708
1709
1710
1711
1712
1713
1714

1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727

1728

1729
1730
1731


1732
1733
1734
1735
1736
1737
1738
....
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
....
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577



3578







3579
3580
3581
3582
3583
3584
3585
....
3731
3732
3733
3734
3735
3736
3737

3738
3739
3740
3741
3742
3743
3744

#include "fts3.h"
#ifndef SQLITE_CORE 
# include "sqlite3ext.h"
  SQLITE_EXTENSION_INIT1
#endif









static int fts3EvalNext(Fts3Cursor *pCsr);
static int fts3EvalStart(Fts3Cursor *pCsr);
static int fts3TermSegReaderCursor(
    Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);

#ifndef SQLITE_AMALGAMATION
# if defined(SQLITE_DEBUG)
................................................................................
  return SQLITE_OK;
}

/*
** Implementation of xOpen method.
*/
static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){

  sqlite3_vtab_cursor *pCsr;               /* Allocated cursor */

  UNUSED_PARAMETER(pVTab);

  /* Allocate a buffer large enough for an Fts3Cursor structure. If the
  ** allocation succeeds, zero it and return SQLITE_OK. Otherwise, 
  ** if the allocation fails, return SQLITE_NOMEM.
  */
  *ppCsr = pCsr = (sqlite3_vtab_cursor *)sqlite3_malloc(sizeof(Fts3Cursor));

  if( !pCsr ){
    return SQLITE_NOMEM;
  }
  memset(pCsr, 0, sizeof(Fts3Cursor));






  return SQLITE_OK;
}

/*
** Finalize the statement handle at pCsr->pStmt.
**
** Or, if that statement handle is one created by fts3CursorSeekStmt(),
................................................................................
}

/*
** Free all resources currently held by the cursor passed as the only
** argument.
*/
static void fts3ClearCursor(Fts3Cursor *pCsr){

  fts3CursorFinalizeStmt(pCsr);
  sqlite3Fts3FreeDeferredTokens(pCsr);
  sqlite3_free(pCsr->aDoclist);
  sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
  sqlite3Fts3ExprFree(pCsr->pExpr);
  memset(&(&pCsr->base)[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
}

/*
** Close the cursor.  For additional information see the documentation
** on the xClose method of the virtual table interface.
*/
static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){

  Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;

  assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
  fts3ClearCursor(pCsr);
  assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );


  sqlite3_free(pCsr);
  return SQLITE_OK;
}

/*
** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then
** compose and prepare an SQL statement of the form:
................................................................................

  /* The column value supplied by SQLite must be in range. */
  assert( iCol>=0 && iCol<=p->nColumn+2 );

  switch( iCol-p->nColumn ){
    case 0:
      /* The special 'table-name' column */
      sqlite3_result_pointer(pCtx, pCsr);
      break;

    case 1:
      /* The docid column */
      sqlite3_result_int64(pCtx, pCsr->iPrevId);
      break;

................................................................................
*/
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 */
){
  int rc;
  *ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal);
  if( (*ppCsr)!=0 ){
    rc = SQLITE_OK;



  }else{







    char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
    sqlite3_result_error(pContext, zErr, -1);
    sqlite3_free(zErr);
    rc = SQLITE_ERROR;
  }
  return rc;
}
................................................................................
  UNUSED_PARAMETER(pVtab);
  UNUSED_PARAMETER(nArg);
  UNUSED_PARAMETER(ppArg);

  for(i=0; i<SizeofArray(aOverload); i++){
    if( strcmp(zName, aOverload[i].zName)==0 ){
      *pxFunc = aOverload[i].xFunc;

      return 1;
    }
  }

  /* No function of the specified name was found. Return 0. */
  return 0;
}







>
>
>
>
>
>
>
>







 







>
|
<
<





|
>




>
>
>
>
>
>







 







>





|







>
|
>
|

|
>
>







 







|







 







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







 







>







304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
....
1675
1676
1677
1678
1679
1680
1681
1682
1683


1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
....
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
....
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
....
3586
3587
3588
3589
3590
3591
3592



3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
....
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771

#include "fts3.h"
#ifndef SQLITE_CORE 
# include "sqlite3ext.h"
  SQLITE_EXTENSION_INIT1
#endif

/*
** GCC does not define the offsetof() macro so we'll have to do it
** ourselves. This definition was copied from sqlite3Int.h.
*/
#ifndef offsetof
#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD))
#endif

static int fts3EvalNext(Fts3Cursor *pCsr);
static int fts3EvalStart(Fts3Cursor *pCsr);
static int fts3TermSegReaderCursor(
    Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);

#ifndef SQLITE_AMALGAMATION
# if defined(SQLITE_DEBUG)
................................................................................
  return SQLITE_OK;
}

/*
** Implementation of xOpen method.
*/
static int fts3OpenMethod(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCsr){
  Fts3Table *p = (Fts3Table *)pVTab;
  Fts3Cursor *pCsr;               /* Allocated cursor */



  /* Allocate a buffer large enough for an Fts3Cursor structure. If the
  ** allocation succeeds, zero it and return SQLITE_OK. Otherwise, 
  ** if the allocation fails, return SQLITE_NOMEM.
  */
  pCsr = (Fts3Cursor*)sqlite3_malloc(sizeof(Fts3Cursor));
  *ppCsr = (sqlite3_vtab_cursor*)pCsr;
  if( !pCsr ){
    return SQLITE_NOMEM;
  }
  memset(pCsr, 0, sizeof(Fts3Cursor));

  /* Link the new cursor into the linked list at Fts3Table.pCsr. */
  pCsr->pNext = p->pAllCsr;
  p->pAllCsr = pCsr;
  pCsr->iId = ++p->iLastCsrId;

  return SQLITE_OK;
}

/*
** Finalize the statement handle at pCsr->pStmt.
**
** Or, if that statement handle is one created by fts3CursorSeekStmt(),
................................................................................
}

/*
** Free all resources currently held by the cursor passed as the only
** argument.
*/
static void fts3ClearCursor(Fts3Cursor *pCsr){
  const int nZero = sizeof(Fts3Cursor)-offsetof(Fts3Cursor,eSearch); 
  fts3CursorFinalizeStmt(pCsr);
  sqlite3Fts3FreeDeferredTokens(pCsr);
  sqlite3_free(pCsr->aDoclist);
  sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
  sqlite3Fts3ExprFree(pCsr->pExpr);
  memset((void*)&pCsr->eSearch, 0, nZero);
}

/*
** Close the cursor.  For additional information see the documentation
** on the xClose method of the virtual table interface.
*/
static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
  Fts3Table *p = (Fts3Table*)pCursor->pVtab;
  Fts3Cursor *pCsr = (Fts3Cursor*)pCursor;
  Fts3Cursor **pp;
  assert( p->pSegments==0 );
  fts3ClearCursor(pCsr);
  assert( p->pSegments==0 );
  for(pp=&p->pAllCsr; (*pp)!=pCsr; pp=&(*pp)->pNext);
  *pp = 0;
  sqlite3_free(pCsr);
  return SQLITE_OK;
}

/*
** If pCsr->pStmt has not been prepared (i.e. if pCsr->pStmt==0), then
** compose and prepare an SQL statement of the form:
................................................................................

  /* The column value supplied by SQLite must be in range. */
  assert( iCol>=0 && iCol<=p->nColumn+2 );

  switch( iCol-p->nColumn ){
    case 0:
      /* The special 'table-name' column */
      sqlite3_result_int(pCtx, pCsr->iId);
      break;

    case 1:
      /* The docid column */
      sqlite3_result_int64(pCtx, pCsr->iPrevId);
      break;

................................................................................
*/
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 */
){



  int rc = SQLITE_OK;
  int iId;
  Fts3Table *p = (Fts3Table*)sqlite3_user_data(pContext);
  iId = sqlite3_value_int(pVal);
  Fts3Cursor *pRet;

  for(pRet=p->pAllCsr; pRet; pRet=pRet->pNext){
    if( pRet->iId==iId ) break;
  }
  *ppCsr = pRet;

  if( pRet==0 ){
    char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
    sqlite3_result_error(pContext, zErr, -1);
    sqlite3_free(zErr);
    rc = SQLITE_ERROR;
  }
  return rc;
}
................................................................................
  UNUSED_PARAMETER(pVtab);
  UNUSED_PARAMETER(nArg);
  UNUSED_PARAMETER(ppArg);

  for(i=0; i<SizeofArray(aOverload); i++){
    if( strcmp(zName, aOverload[i].zName)==0 ){
      *pxFunc = aOverload[i].xFunc;
      *ppArg = (void*)pVtab;
      return 1;
    }
  }

  /* No function of the specified name was found. Return 0. */
  return 0;
}

Changes to ext/fts3/fts3Int.h.

284
285
286
287
288
289
290



291
292
293
294
295
296
297
298
299





300
301
302
303
304
305
306
#endif

#ifdef SQLITE_TEST
  /* True to disable the incremental doclist optimization. This is controled
  ** by special insert command 'test-no-incr-doclist'.  */
  int bNoIncrDoclist;
#endif



};

/*
** When the core wants to read from the virtual table, it creates a
** virtual table cursor (an instance of the following structure) using
** the xOpen method. Cursors are destroyed using the xClose method.
*/
struct Fts3Cursor {
  sqlite3_vtab_cursor base;       /* Base class used by SQLite core */





  i16 eSearch;                    /* Search strategy (see below) */
  u8 isEof;                       /* True if at End Of Results */
  u8 isRequireSeek;               /* True if must seek pStmt to %_content row */
  u8 bSeekStmt;                   /* True if pStmt is a seek */
  sqlite3_stmt *pStmt;            /* Prepared statement in use by the cursor */
  Fts3Expr *pExpr;                /* Parsed MATCH query string */
  int iLangid;                    /* Language being queried for */







>
>
>









>
>
>
>
>







284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
#endif

#ifdef SQLITE_TEST
  /* True to disable the incremental doclist optimization. This is controled
  ** by special insert command 'test-no-incr-doclist'.  */
  int bNoIncrDoclist;
#endif

  Fts3Cursor *pAllCsr;            /* List of all open cursors */
  int iLastCsrId;                 /* Last cursor id assigned (or 0) */
};

/*
** When the core wants to read from the virtual table, it creates a
** virtual table cursor (an instance of the following structure) using
** the xOpen method. Cursors are destroyed using the xClose method.
*/
struct Fts3Cursor {
  sqlite3_vtab_cursor base;       /* Base class used by SQLite core */
  int iId;                        /* Numeric id of this cursor */
  Fts3Cursor *pNext;              /* Next in list of all cursors */

  /* Variables below this point are zeroed by fts3ClearCursor() */

  i16 eSearch;                    /* Search strategy (see below) */
  u8 isEof;                       /* True if at End Of Results */
  u8 isRequireSeek;               /* True if must seek pStmt to %_content row */
  u8 bSeekStmt;                   /* True if pStmt is a seek */
  sqlite3_stmt *pStmt;            /* Prepared statement in use by the cursor */
  Fts3Expr *pExpr;                /* Parsed MATCH query string */
  int iLangid;                    /* Language being queried for */