/ Check-in [b9b0c1e5]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Avoid freeing the array of instance matches each time the fts5 xNext() method is called.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b9b0c1e50d77f5d6e02f43fbb100c722cb692cc5
User & Date: dan 2015-07-03 17:14:18
Context
2015-07-03
17:54
Enable use of the __builtin_bswap32() only with GCC 4.3 and higher. check-in: 030f60a7 user: mistachkin tags: trunk
17:14
Avoid freeing the array of instance matches each time the fts5 xNext() method is called. check-in: b9b0c1e5 user: dan tags: trunk
14:34
New command-line options for speedtest1: --multithread, --nomemstat, --serialized, and --singlethread check-in: 2b756722 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to ext/fts5/fts5_main.c.

215
216
217
218
219
220
221

222
223
224
225
226
227
228
229
230
231
...
607
608
609
610
611
612
613

614
615
616
617

618
619
620
621
622
623
624
...
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
....
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
....
1560
1561
1562
1563
1564
1565
1566

1567
1568
1569

1570
1571
1572
1573
1574
1575
1576
#define FTS5_BI_ORDER_DESC   0x0080

/*
** Values for Fts5Cursor.csrflags
*/
#define FTS5CSR_REQUIRE_CONTENT   0x01
#define FTS5CSR_REQUIRE_DOCSIZE   0x02

#define FTS5CSR_EOF               0x04
#define FTS5CSR_FREE_ZRANK        0x08
#define FTS5CSR_REQUIRE_RESEEK    0x10

#define BitFlagAllTest(x,y) (((x) & (y))==(y))
#define BitFlagTest(x,y)    (((x) & (y))!=0)

/*
** Constants for the largest and smallest possible 64-bit signed integers.
** These are copied from sqliteInt.h.
................................................................................

/*
** This function is called after the cursor passed as the only argument
** is moved to point at a different row. It clears all cached data 
** specific to the previous row stored by the cursor object.
*/
static void fts5CsrNewrow(Fts5Cursor *pCsr){

  CsrFlagSet(pCsr, FTS5CSR_REQUIRE_CONTENT | FTS5CSR_REQUIRE_DOCSIZE );
  sqlite3_free(pCsr->aInst);
  pCsr->aInst = 0;
  pCsr->nInstCount = 0;

}

/*
** Close the cursor.  For additional information see the documentation
** on the xClose method of the virtual table interface.
*/
static int fts5CloseMethod(sqlite3_vtab_cursor *pCursor){
................................................................................
  if( pCursor ){
    Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
    Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
    Fts5Cursor **pp;
    Fts5Auxdata *pData;
    Fts5Auxdata *pNext;

    fts5CsrNewrow(pCsr);
    if( pCsr->pStmt ){
      int eStmt = fts5StmtType(pCsr);
      sqlite3Fts5StorageStmtRelease(pTab->pStorage, eStmt, pCsr->pStmt);
    }
    if( pCsr->pSorter ){
      Fts5Sorter *pSorter = pCsr->pSorter;
      sqlite3_finalize(pSorter->pStmt);
................................................................................
/*
** Ensure that the Fts5Cursor.nInstCount and aInst[] variables are populated
** correctly for the current view. Return SQLITE_OK if successful, or an
** SQLite error code otherwise.
*/
static int fts5CacheInstArray(Fts5Cursor *pCsr){
  int rc = SQLITE_OK;
  if( pCsr->aInst==0 ){
    Fts5PoslistReader *aIter;     /* One iterator for each phrase */
    int nIter;                    /* Number of iterators/phrases */
    int nByte;
    
    nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
    nByte = sizeof(Fts5PoslistReader) * nIter;
    aIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte);
................................................................................
        aInst = &((int*)buf.p)[3 * (nInst-1)];
        aInst[0] = iBest;
        aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
        aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
        sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
      }


      pCsr->aInst = (int*)buf.p;
      pCsr->nInstCount = nInst;
      sqlite3_free(aIter);

    }
  }
  return rc;
}

static int fts5ApiInstCount(Fts5Context *pCtx, int *pnInst){
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;







>
|
|
|







 







>
|
<
|
|
>







 







|







 







|







 







>



>







215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
...
608
609
610
611
612
613
614
615
616

617
618
619
620
621
622
623
624
625
626
...
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
....
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
....
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
#define FTS5_BI_ORDER_DESC   0x0080

/*
** Values for Fts5Cursor.csrflags
*/
#define FTS5CSR_REQUIRE_CONTENT   0x01
#define FTS5CSR_REQUIRE_DOCSIZE   0x02
#define FTS5CSR_REQUIRE_INST      0x04
#define FTS5CSR_EOF               0x08
#define FTS5CSR_FREE_ZRANK        0x10
#define FTS5CSR_REQUIRE_RESEEK    0x20

#define BitFlagAllTest(x,y) (((x) & (y))==(y))
#define BitFlagTest(x,y)    (((x) & (y))!=0)

/*
** Constants for the largest and smallest possible 64-bit signed integers.
** These are copied from sqliteInt.h.
................................................................................

/*
** This function is called after the cursor passed as the only argument
** is moved to point at a different row. It clears all cached data 
** specific to the previous row stored by the cursor object.
*/
static void fts5CsrNewrow(Fts5Cursor *pCsr){
  CsrFlagSet(pCsr, 
      FTS5CSR_REQUIRE_CONTENT 

    | FTS5CSR_REQUIRE_DOCSIZE 
    | FTS5CSR_REQUIRE_INST 
  );
}

/*
** Close the cursor.  For additional information see the documentation
** on the xClose method of the virtual table interface.
*/
static int fts5CloseMethod(sqlite3_vtab_cursor *pCursor){
................................................................................
  if( pCursor ){
    Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
    Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
    Fts5Cursor **pp;
    Fts5Auxdata *pData;
    Fts5Auxdata *pNext;

    sqlite3_free(pCsr->aInst);
    if( pCsr->pStmt ){
      int eStmt = fts5StmtType(pCsr);
      sqlite3Fts5StorageStmtRelease(pTab->pStorage, eStmt, pCsr->pStmt);
    }
    if( pCsr->pSorter ){
      Fts5Sorter *pSorter = pCsr->pSorter;
      sqlite3_finalize(pSorter->pStmt);
................................................................................
/*
** Ensure that the Fts5Cursor.nInstCount and aInst[] variables are populated
** correctly for the current view. Return SQLITE_OK if successful, or an
** SQLite error code otherwise.
*/
static int fts5CacheInstArray(Fts5Cursor *pCsr){
  int rc = SQLITE_OK;
  if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_INST) ){
    Fts5PoslistReader *aIter;     /* One iterator for each phrase */
    int nIter;                    /* Number of iterators/phrases */
    int nByte;
    
    nIter = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
    nByte = sizeof(Fts5PoslistReader) * nIter;
    aIter = (Fts5PoslistReader*)sqlite3Fts5MallocZero(&rc, nByte);
................................................................................
        aInst = &((int*)buf.p)[3 * (nInst-1)];
        aInst[0] = iBest;
        aInst[1] = FTS5_POS2COLUMN(aIter[iBest].iPos);
        aInst[2] = FTS5_POS2OFFSET(aIter[iBest].iPos);
        sqlite3Fts5PoslistReaderNext(&aIter[iBest]);
      }

      sqlite3_free(pCsr->aInst);
      pCsr->aInst = (int*)buf.p;
      pCsr->nInstCount = nInst;
      sqlite3_free(aIter);
      CsrFlagClear(pCsr, FTS5CSR_REQUIRE_INST);
    }
  }
  return rc;
}

static int fts5ApiInstCount(Fts5Context *pCtx, int *pnInst){
  Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;

Changes to ext/fts5/tool/loadfts5.tcl.

98
99
100
101
102
103
104

105
106
107
108
109
110
111
    }
  }
}

set dbfile [lindex $argv end-1]
if {$O(delete)} { file delete -force $dbfile }
sqlite3 db $dbfile

db func loadfile loadfile

db transaction {
  set pref ""
  if {$O(prefix)!=""} { set pref ", prefix='$O(prefix)'" }
  catch {
    db eval "CREATE VIRTUAL TABLE t1 USING $O(vtab) (path, content$O(tok)$pref)"







>







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
    }
  }
}

set dbfile [lindex $argv end-1]
if {$O(delete)} { file delete -force $dbfile }
sqlite3 db $dbfile
catch { load_static_extension db fts5 }
db func loadfile loadfile

db transaction {
  set pref ""
  if {$O(prefix)!=""} { set pref ", prefix='$O(prefix)'" }
  catch {
    db eval "CREATE VIRTUAL TABLE t1 USING $O(vtab) (path, content$O(tok)$pref)"

Changes to ext/fts5/tool/mkfts5c.tcl.

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  puts -nonewline $G(fd) $G(hdr)
}

proc fts5c_printfile {zIn} {
  global G
  set data [readfile $zIn]
  set zTail [file tail $zIn]
  puts $G(fd) "#line 1 \"$zTail\""

  set sub_map [list --FTS5-SOURCE-ID-- [fts5_source_id $::srcdir]]
  if {$zTail=="fts5parse.c"} {
    lappend sub_map yy fts5yy YY fts5YY TOKEN FTS5TOKEN
  }

  foreach line [split $data "\n"] {







|







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  puts -nonewline $G(fd) $G(hdr)
}

proc fts5c_printfile {zIn} {
  global G
  set data [readfile $zIn]
  set zTail [file tail $zIn]
  puts $G(fd) "#line 2 \"$zTail\""

  set sub_map [list --FTS5-SOURCE-ID-- [fts5_source_id $::srcdir]]
  if {$zTail=="fts5parse.c"} {
    lappend sub_map yy fts5yy YY fts5YY TOKEN FTS5TOKEN
  }

  foreach line [split $data "\n"] {

Changes to ext/fts5/tool/showfts5.tcl.

14
15
16
17
18
19
20

21
22
23
24
25
26
27
28
29
30
31

if {[llength $argv]!=2} usage

set database [lindex $argv 0]
set tbl [lindex $argv 1]

sqlite3 db $database


db eval "SELECT fts5_decode(rowid, block) AS d FROM ${tbl}_data WHERE id=10" {
  foreach lvl [lrange $d 1 end] {
    puts $lvl
  }
}












>











14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

if {[llength $argv]!=2} usage

set database [lindex $argv 0]
set tbl [lindex $argv 1]

sqlite3 db $database
catch { load_static_extension db fts5 }

db eval "SELECT fts5_decode(rowid, block) AS d FROM ${tbl}_data WHERE id=10" {
  foreach lvl [lrange $d 1 end] {
    puts $lvl
  }
}