/ Check-in [f4de6d45]
Login

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

Overview
Comment:Tests and minor fixes to improve coverage of FTS5 code.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f4de6d450e143cb1dd5447800d4b178e3db114c8
User & Date: dan 2015-10-14 21:08:48
Context
2015-10-14
22:46
In the MSVC makefile, make sure LDFLAGS is used for the tool executables as well. check-in: 0a17ee49 user: mistachkin tags: trunk
21:08
Tests and minor fixes to improve coverage of FTS5 code. check-in: f4de6d45 user: dan tags: trunk
20:34
Fix harmless compiler warnings. check-in: 1c46c194 user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/fts5/fts5_index.c.

1762
1763
1764
1765
1766
1767
1768

1769
1770
1771
1772
1773
1774
1775
....
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
....
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
....
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
        }
        pIter->iLeafOffset = iOff;

      }else if( pIter->pSeg==0 ){
        const u8 *pList = 0;
        const char *zTerm = 0;
        int nList = 0;

        if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){
          sqlite3Fts5HashScanNext(p->pHash);
          sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList);
        }
        if( pList==0 ){
          fts5DataRelease(pIter->pLeaf);
          pIter->pLeaf = 0;
................................................................................
          pIter->pLeaf->p = (u8*)pList;
          pIter->pLeaf->nn = nList;
          pIter->pLeaf->szLeaf = nList;
          pIter->iEndofDoclist = nList+1;
          sqlite3Fts5BufferSet(&p->rc, &pIter->term, (int)strlen(zTerm),
              (u8*)zTerm);
          pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
          if( pbNewTerm ) *pbNewTerm = 1;
        }
      }else{
        iOff = 0;
        /* Next entry is not on the current page */
        while( iOff==0 ){
          fts5SegIterNextPage(p, pIter);
          pLeaf = pIter->pLeaf;
................................................................................
  if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){
    if( pColset==0 ){
      fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
    }else{
      PoslistCallbackCtx sCtx;
      sCtx.pBuf = pBuf;
      sCtx.pColset = pColset;
      sCtx.eState = pColset ? fts5IndexColsetTest(pColset, 0) : 1;
      assert( sCtx.eState==0 || sCtx.eState==1 );
      fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback);
    }
  }
}

/*
................................................................................
        if( res<0 ) p->rc = FTS5_CORRUPT;
      }

      fts5IntegrityCheckPgidx(p, pLeaf);
    }
    fts5DataRelease(pLeaf);
    if( p->rc ) break;


    /* Now check that the iter.nEmpty leaves following the current leaf
    ** (a) exist and (b) contain no terms. */
    fts5IndexIntegrityCheckEmpty(
        p, pSeg, iIdxPrevLeaf+1, iDlidxPrevLeaf+1, iIdxLeaf-1
    );
    if( p->rc ) break;







>







 







|







 







|







 







<







1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
....
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
....
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
....
5193
5194
5195
5196
5197
5198
5199

5200
5201
5202
5203
5204
5205
5206
        }
        pIter->iLeafOffset = iOff;

      }else if( pIter->pSeg==0 ){
        const u8 *pList = 0;
        const char *zTerm = 0;
        int nList = 0;
        assert( (pIter->flags & FTS5_SEGITER_ONETERM) || pbNewTerm );
        if( 0==(pIter->flags & FTS5_SEGITER_ONETERM) ){
          sqlite3Fts5HashScanNext(p->pHash);
          sqlite3Fts5HashScanEntry(p->pHash, &zTerm, &pList, &nList);
        }
        if( pList==0 ){
          fts5DataRelease(pIter->pLeaf);
          pIter->pLeaf = 0;
................................................................................
          pIter->pLeaf->p = (u8*)pList;
          pIter->pLeaf->nn = nList;
          pIter->pLeaf->szLeaf = nList;
          pIter->iEndofDoclist = nList+1;
          sqlite3Fts5BufferSet(&p->rc, &pIter->term, (int)strlen(zTerm),
              (u8*)zTerm);
          pIter->iLeafOffset = fts5GetVarint(pList, (u64*)&pIter->iRowid);
          *pbNewTerm = 1;
        }
      }else{
        iOff = 0;
        /* Next entry is not on the current page */
        while( iOff==0 ){
          fts5SegIterNextPage(p, pIter);
          pLeaf = pIter->pLeaf;
................................................................................
  if( 0==fts5BufferGrow(&p->rc, pBuf, pSeg->nPos) ){
    if( pColset==0 ){
      fts5ChunkIterate(p, pSeg, (void*)pBuf, fts5PoslistCallback);
    }else{
      PoslistCallbackCtx sCtx;
      sCtx.pBuf = pBuf;
      sCtx.pColset = pColset;
      sCtx.eState = fts5IndexColsetTest(pColset, 0);
      assert( sCtx.eState==0 || sCtx.eState==1 );
      fts5ChunkIterate(p, pSeg, (void*)&sCtx, fts5PoslistFilterCallback);
    }
  }
}

/*
................................................................................
        if( res<0 ) p->rc = FTS5_CORRUPT;
      }

      fts5IntegrityCheckPgidx(p, pLeaf);
    }
    fts5DataRelease(pLeaf);
    if( p->rc ) break;


    /* Now check that the iter.nEmpty leaves following the current leaf
    ** (a) exist and (b) contain no terms. */
    fts5IndexIntegrityCheckEmpty(
        p, pSeg, iIdxPrevLeaf+1, iDlidxPrevLeaf+1, iIdxLeaf-1
    );
    if( p->rc ) break;

Changes to ext/fts5/fts5_main.c.

443
444
445
446
447
448
449

450


451
452
453
454
455
456
457
/*
** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this
** extension is currently being used by a version of SQLite too old to
** support index-info flags. In that case this function is a no-op.
*/
static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
#if SQLITE_VERSION_NUMBER>=3008012

  if( sqlite3_libversion_number()>=3008012 ){


    pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
  }
#endif
}

/*
** Implementation of the xBestIndex method for FTS5 tables. Within the 







>
|
>
>







443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
/*
** Set the SQLITE_INDEX_SCAN_UNIQUE flag in pIdxInfo->flags. Unless this
** extension is currently being used by a version of SQLite too old to
** support index-info flags. In that case this function is a no-op.
*/
static void fts5SetUniqueFlag(sqlite3_index_info *pIdxInfo){
#if SQLITE_VERSION_NUMBER>=3008012
#ifndef SQLITE_CORE
  if( sqlite3_libversion_number()>=3008012 )
#endif
  {
    pIdxInfo->idxFlags |= SQLITE_INDEX_SCAN_UNIQUE;
  }
#endif
}

/*
** Implementation of the xBestIndex method for FTS5 tables. Within the 

Changes to ext/fts5/fts5_storage.c.

721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
      *piRowid = sqlite3_value_int64(apVal[1]);
    }else{
      rc = fts5StorageNewRowid(p, piRowid);
    }
  }else{
    sqlite3_stmt *pInsert = 0;    /* Statement to write %_content table */
    int i;                        /* Counter variable */
#if 0
    if( eConflict==SQLITE_REPLACE ){
      eStmt = FTS5_STMT_REPLACE_CONTENT;
      rc = fts5StorageDeleteFromIndex(p, sqlite3_value_int64(apVal[1]));
    }else{
      eStmt = FTS5_STMT_INSERT_CONTENT;
    }
#endif
    if( rc==SQLITE_OK ){
      rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0);
    }
    for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
      rc = sqlite3_bind_value(pInsert, i, apVal[i]);
    }
    if( rc==SQLITE_OK ){
      sqlite3_step(pInsert);
      rc = sqlite3_reset(pInsert);
    }







<
<
<
<
<
<
<
<
<
|
<







721
722
723
724
725
726
727









728

729
730
731
732
733
734
735
      *piRowid = sqlite3_value_int64(apVal[1]);
    }else{
      rc = fts5StorageNewRowid(p, piRowid);
    }
  }else{
    sqlite3_stmt *pInsert = 0;    /* Statement to write %_content table */
    int i;                        /* Counter variable */









    rc = fts5StorageGetStmt(p, FTS5_STMT_INSERT_CONTENT, &pInsert, 0);

    for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
      rc = sqlite3_bind_value(pInsert, i, apVal[i]);
    }
    if( rc==SQLITE_OK ){
      sqlite3_step(pInsert);
      rc = sqlite3_reset(pInsert);
    }

Changes to ext/fts5/test/fts5aa.test.

155
156
157
158
159
160
161




162
163







164
165
166
167
168
169
170
}

do_execsql_test 6.3 {
  REPLACE INTO t1(rowid, x, y) VALUES('22', 'l l l', 'l l l');
}

do_execsql_test 6.4 {




  INSERT INTO t1(t1) VALUES('integrity-check') 
}








#-------------------------------------------------------------------------
#
reset_db
expr srand(0)
do_execsql_test 7.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(x,y,z);







>
>
>
>


>
>
>
>
>
>
>







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
}

do_execsql_test 6.3 {
  REPLACE INTO t1(rowid, x, y) VALUES('22', 'l l l', 'l l l');
}

do_execsql_test 6.4 {
  REPLACE INTO t1(x, y) VALUES('x y z', 'x y z');
}

do_execsql_test 6.5 {
  INSERT INTO t1(t1) VALUES('integrity-check') 
}

do_execsql_test 6.6 {
  SELECT rowid, * FROM t1;
} {
  22 {l l l} {l l l}
  23 {x y z} {x y z}
}

#-------------------------------------------------------------------------
#
reset_db
expr srand(0)
do_execsql_test 7.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(x,y,z);

Changes to ext/fts5/test/fts5corrupt3.test.

246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
...
331
332
333
334
335
336
337






































338
339
340
      }
      set {} {}
    } {}
    catch { db eval ROLLBACK }
  }
}

}

#------------------------------------------------------------------------
#
reset_db
do_execsql_test 6.1.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(a);
  INSERT INTO t1 VALUES('bbbbb ccccc');
  SELECT quote(block) FROM t1_data WHERE rowid>100;
................................................................................
      ----------^^-----------------------------------------------------
    WHERE id>100;
}
do_catchsql_test 6.3.5 {
  INSERT INTO t1(t1) VALUES('integrity-check');
} {1 {database disk image is malformed}}







































sqlite3_fts5_may_be_corrupt 0
finish_test








<
<







 







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



246
247
248
249
250
251
252


253
254
255
256
257
258
259
...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
      }
      set {} {}
    } {}
    catch { db eval ROLLBACK }
  }
}



#------------------------------------------------------------------------
#
reset_db
do_execsql_test 6.1.0 {
  CREATE VIRTUAL TABLE t1 USING fts5(a);
  INSERT INTO t1 VALUES('bbbbb ccccc');
  SELECT quote(block) FROM t1_data WHERE rowid>100;
................................................................................
      ----------^^-----------------------------------------------------
    WHERE id>100;
}
do_catchsql_test 6.3.5 {
  INSERT INTO t1(t1) VALUES('integrity-check');
} {1 {database disk image is malformed}}


}

#------------------------------------------------------------------------
#
reset_db
reset_db
proc rnddoc {n} {
  set map [list a b c d]
  set doc [list]
  for {set i 0} {$i < $n} {incr i} {
    lappend doc "x[lindex $map [expr int(rand()*4)]]"
  }
  set doc
}

db func rnddoc rnddoc
do_test 7.0 {
  execsql {
    CREATE VIRTUAL TABLE t5 USING fts5(x);
    INSERT INTO t5 VALUES( rnddoc(10000) );
    INSERT INTO t5 VALUES( rnddoc(10000) );
    INSERT INTO t5 VALUES( rnddoc(10000) );
    INSERT INTO t5 VALUES( rnddoc(10000) );
    INSERT INTO t5(t5) VALUES('optimize');
  }
} {}

do_test 7.1 {
  foreach i [db eval { SELECT rowid FROM t5_data WHERE rowid>100 }] {
    db eval BEGIN  
    db eval {DELETE FROM t5_data WHERE rowid = $i}
    set r [catchsql { INSERT INTO t5(t5) VALUES('integrity-check')} ]
    if {$r != "1 {database disk image is malformed}"} { error $r }
    db eval ROLLBACK  
  }
} {}

sqlite3_fts5_may_be_corrupt 0
finish_test

Changes to ext/fts5/test/fts5fault7.test.

82
83
84
85
86
87
88





















89
90
91
    INSERT INTO t2 VALUES('e a d a e d');
  }
} -body {
  db eval COMMIT
} -test {
  faultsim_test_result {0 {}}
}






















finish_test








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



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
    INSERT INTO t2 VALUES('e a d a e d');
  }
} -body {
  db eval COMMIT
} -test {
  faultsim_test_result {0 {}}
}

#-------------------------------------------------------------------------
# Test fault-injection when a segment is promoted.
#
reset_db
do_execsql_test 2.0 {
  CREATE VIRTUAL TABLE xy USING fts5(x);
  INSERT INTO xy(rowid, x) VALUES(1, '1 2 3');
  INSERT INTO xy(rowid, x) VALUES(2, '2 3 4');
  INSERT INTO xy(rowid, x) VALUES(3, '3 4 5');
}
faultsim_save_and_close

do_faultsim_test 2 -faults oom-* -prep {
  faultsim_restore_and_reopen
} -body {
  db eval { UPDATE OR REPLACE xy SET rowid=3 WHERE rowid = 2 }
} -test {
  faultsim_test_result {0 {}}
}


finish_test

Changes to ext/fts5/test/fts5hash.test.

80
81
82
83
84
85
86
87
88
89
90
91


92
93
94
95
96
97
98
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"
    }
  }







|
|
|
|
|
>
>







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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;
}
do_test 1.2 {
  for {set i 1} {$i <= 100} {incr i} {
    execsql { INSERT INTO eee VALUES( r($vocab, 5), r($vocab, 7) ) }
  }
} {}
  
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"
    }
  }

Changes to ext/fts5/test/fts5prefix.test.

191
192
193
194
195
196
197

198





































































































199
200
201
      } $res
    }
  }
  execsql { INSERT INTO t3(t3) VALUES('optimize') }
  execsql { INSERT INTO t3(t3) VALUES('integrity-check') }
}








































































































finish_test









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



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
      } $res
    }
  }
  execsql { INSERT INTO t3(t3) VALUES('optimize') }
  execsql { INSERT INTO t3(t3) VALUES('integrity-check') }
}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 4.0 {
  CREATE VIRTUAL TABLE t2 USING fts5(c1, c2);
  INSERT INTO t2 VALUES('xa xb', 'xb xa');

  INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 2
  INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 4
  INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 8
  INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 16
  INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 32
  INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 64
  INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 128
  INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 256
  INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 512
  INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 1024
  INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 2048
  INSERT INTO t2 SELECT c1||' '||c1, c2||' '||c2 FROM t2; -- 4096

  SELECT count(*) FROM t2('x*');
} {4096}

do_execsql_test 4.1 {
  UPDATE t2 SET c2 = 'ya yb';
  SELECT count(*) FROM t2('c1:x*');
  SELECT count(*) FROM t2('c2:x*');
} {4096 0}

do_execsql_test 4.2 {
  UPDATE t2 SET c2 = 'xa';
  SELECT count(*) FROM t2('c1:x*');
  SELECT count(*) FROM t2('c2:x*');
} {4096 4096}

#-------------------------------------------------------------------------
#
reset_db
proc rnddoc {n} {
  set map [list a b c d]
  set doc [list]
  for {set i 0} {$i < $n} {incr i} {
    lappend doc "x[lindex $map [expr int(rand()*4)]]"
  }
  set doc
}
set cols [list]
for {set i 1} {$i<250} {incr i} { 
  lappend cols "c$i" 
  lappend vals "'[rnddoc 10]'"
}

do_test 5.0 {
  execsql "CREATE VIRTUAL TABLE t4 USING fts5([join $cols ,])"
  execsql {INSERT INTO t4(t4, rank) VALUES('pgsz', 32)}
  execsql "INSERT INTO t4 VALUES([join $vals ,])"
  execsql "INSERT INTO t4 VALUES([join $vals ,])"
  execsql "INSERT INTO t4 VALUES([join $vals ,])"
  execsql "INSERT INTO t4 VALUES([join $vals ,])"
} {}

proc gmatch {col pattern} {
  expr {[lsearch -glob $col $pattern]>=0}
}
db func gmatch gmatch
foreach {tn col pattern} {
  1 c100 {xa*}
  2 c200 {xb*}
} {
  set res [db eval "SELECT rowid FROM t4 WHERE gmatch($col, \$pattern)"]
  set query "$col : $pattern"
  do_execsql_test 5.$tn { SELECT rowid FROM t4($query) } $res
}

reset_db
db func fts5_rnddoc fts5_rnddoc
do_test 6.0 {
  execsql {
    CREATE VIRTUAL TABLE t5 USING fts5(x, y);
    INSERT INTO t5 VALUES( fts5_rnddoc(10000), fts5_rnddoc(10000) );
    INSERT INTO t5 VALUES( fts5_rnddoc(10000), fts5_rnddoc(10000) );
    INSERT INTO t5 VALUES( fts5_rnddoc(10000), fts5_rnddoc(10000) );
    INSERT INTO t5 VALUES( fts5_rnddoc(10000), fts5_rnddoc(10000) );
  }
} {}

proc gmatch {col pattern} {
  expr {[lsearch -glob $col $pattern]>=0}
}
db func gmatch gmatch
foreach {tn col pattern} {
  1 y {xa*}
  2 y {xb*}
  3 y {xc*}
  4 x {xa*}
  5 x {xb*}
  6 x {xc*}
} {
  set res [db eval "SELECT rowid FROM t5 WHERE gmatch($col, \$pattern)"]
  set query "$col : $pattern"
  do_execsql_test 6.$tn { SELECT rowid FROM t5($query) } $res
}

finish_test


Changes to ext/fts5/test/fts5simple.test.

295
296
297
298
299
300
301






















302
303
304
  }
} {}

do_execsql_test 12.2 {
  SELECT rowid FROM xx('x:a');
  COMMIT;
} {}























finish_test








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



295
296
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
  }
} {}

do_execsql_test 12.2 {
  SELECT rowid FROM xx('x:a');
  COMMIT;
} {}

#-------------------------------------------------------------------------
# Try an UPDATE OR REPLACE query.
#
do_execsql_test 13.1 {
  CREATE VIRTUAL TABLE xy USING fts5(x);
  INSERT INTO xy(rowid, x) VALUES(1, '1 2 3');
  INSERT INTO xy(rowid, x) VALUES(2, '2 3 4');
  INSERT INTO xy(rowid, x) VALUES(3, '3 4 5');
}

do_execsql_test 13.2 {
  UPDATE OR REPLACE xy SET rowid=3 WHERE rowid = 2;
  SELECT rowid, x FROM xy;
} {
  1 {1 2 3}
  3 {2 3 4}
}

do_execsql_test 13.3 {
  INSERT INTO xy(xy) VALUES('integrity-check');
}

finish_test