/ Check-in [e0d61442]
Login
Overview
Comment:Fix an fts5 issue with loading doclist-indexes for a term that is the last thing on its leaf page.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | fts5
Files: files | file ages | folders
SHA1:e0d614425f7f5ffe266fdc03642931b1ec19ad25
User & Date: dan 2015-01-21 18:23:25
Context
2015-01-21
20:30
Further tests and fixes for fts5. check-in: c020a291 user: dan tags: fts5
18:23
Fix an fts5 issue with loading doclist-indexes for a term that is the last thing on its leaf page. check-in: e0d61442 user: dan tags: fts5
17:20
Merge trunk changes with this branch. check-in: f8699a1a user: dan tags: fts5
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/fts5/fts5_index.c.

1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838

1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849

1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
** Iterator pIter currently points to the first rowid of a doclist within
** index iIdx. There is a doclist-index associated with the final term on
** the current page. If the current term is the last term on the page, 
** load the doclist-index from disk and initialize an iterator at 
** (pIter->pDlidx).
*/
static void fts5SegIterLoadDlidx(Fts5Index *p, int iIdx, Fts5SegIter *pIter){
  int iSegid = pIter->pSeg->iSegid;
  int bRev = (pIter->flags & FTS5_SEGITER_REVERSE);
  Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */
  int iOff = pIter->iLeafOffset;  /* Byte offset within current leaf */

  assert( pIter->flags & FTS5_SEGITER_ONETERM );
  assert( pIter->pDlidx==0 );

  /* Check if the current doclist ends on this page. If it does, return
  ** early without loading the doclist-index (as it belongs to a different
  ** term. */

  while( iOff<pLeaf->n ){
    i64 iDelta;
    int nPoslist;

    /* iOff is currently the offset of the size field of a position list. */
    iOff += getVarint32(&pLeaf->p[iOff], nPoslist);
    iOff += nPoslist;

    if( iOff<pLeaf->n ){
      iOff += getVarint(&pLeaf->p[iOff], (u64*)&iDelta);
      if( iDelta==0 ) return;

    }
  }

  fts5DlidxIterInit(p, bRev, iIdx, iSegid, pIter->iLeafPgno, &pIter->pDlidx);
}

/*
** Initialize the object pIter to point to term pTerm/nTerm within segment
** pSeg, index iIdx. If there is no such term in the index, the iterator
** is set to EOF.
**







|










>
|
|
|

|
|
|

|
|
|
>



|







1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
** Iterator pIter currently points to the first rowid of a doclist within
** index iIdx. There is a doclist-index associated with the final term on
** the current page. If the current term is the last term on the page, 
** load the doclist-index from disk and initialize an iterator at 
** (pIter->pDlidx).
*/
static void fts5SegIterLoadDlidx(Fts5Index *p, int iIdx, Fts5SegIter *pIter){
  int iSeg = pIter->pSeg->iSegid;
  int bRev = (pIter->flags & FTS5_SEGITER_REVERSE);
  Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */
  int iOff = pIter->iLeafOffset;  /* Byte offset within current leaf */

  assert( pIter->flags & FTS5_SEGITER_ONETERM );
  assert( pIter->pDlidx==0 );

  /* Check if the current doclist ends on this page. If it does, return
  ** early without loading the doclist-index (as it belongs to a different
  ** term. */
  if( pIter->iTermLeafPgno==pIter->iLeafPgno ){
    while( iOff<pLeaf->n ){
      i64 iDelta;
      int nPoslist;

      /* iOff is currently the offset of the size field of a position list. */
      iOff += getVarint32(&pLeaf->p[iOff], nPoslist);
      iOff += nPoslist;

      if( iOff<pLeaf->n ){
        iOff += getVarint(&pLeaf->p[iOff], (u64*)&iDelta);
        if( iDelta==0 ) return;
      }
    }
  }

  fts5DlidxIterInit(p, bRev, iIdx, iSeg, pIter->iTermLeafPgno, &pIter->pDlidx);
}

/*
** Initialize the object pIter to point to term pTerm/nTerm within segment
** pSeg, index iIdx. If there is no such term in the index, the iterator
** is set to EOF.
**

Changes to ext/fts5/test/fts5rowid.test.

115
116
117
118
119
120
121
122































123
124
  } [expr $tn+1]
}

set res [db one {SELECT count(*) FROM x2_data}]
do_execsql_test 3.2 {
  SELECT count(fts5_decode(rowid, block)) FROM x2_data;
} $res
































finish_test









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


115
116
117
118
119
120
121
122
123
124
125
126
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
  } [expr $tn+1]
}

set res [db one {SELECT count(*) FROM x2_data}]
do_execsql_test 3.2 {
  SELECT count(fts5_decode(rowid, block)) FROM x2_data;
} $res

#-------------------------------------------------------------------------
# Leaf pages with no terms or rowids at all.
#
set strlist [list \
  "[string repeat {w } 400]"  \
  "[string repeat {x } 400]"  \
  "[string repeat {y } 400]"  \
  "[string repeat {z } 400]"  \
]
do_test 4.0 {
  execsql {
    BEGIN;
    CREATE VIRTUAL TABLE x3 USING fts5(a);
    INSERT INTO x3(x3, rank) VALUES('pgsz', 32);
  }
  foreach str $strlist { execsql { INSERT INTO x3 VALUES($str) } }
  execsql COMMIT
} {}

for {set tn 0} {$tn<[llength $strlist]} {incr tn} {
  set str [lindex $strlist $tn]
  do_execsql_test 4.1.$tn {
    SELECT rowid FROM x3 WHERE x3 MATCH $str
  } [expr $tn+1]
}

set res [db one {SELECT count(*) FROM x3_data}]
do_execsql_test 4.2 {
  SELECT count(fts5_decode(rowid, block)) FROM x3_data;
} $res

finish_test