Index: third_party/sqlite/sqlite-src-3170000/ext/fts5/test/fts5merge.test |
diff --git a/third_party/sqlite/sqlite-src-3170000/ext/fts5/test/fts5merge.test b/third_party/sqlite/sqlite-src-3170000/ext/fts5/test/fts5merge.test |
new file mode 100644 |
index 0000000000000000000000000000000000000000..73e006a7d2ce5d3c082b941f2cd1c2f77e23f720 |
--- /dev/null |
+++ b/third_party/sqlite/sqlite-src-3170000/ext/fts5/test/fts5merge.test |
@@ -0,0 +1,244 @@ |
+# 2014 Dec 20 |
+# |
+# The author disclaims copyright to this source code. In place of |
+# a legal notice, here is a blessing: |
+# |
+# May you do good and not evil. |
+# May you find forgiveness for yourself and forgive others. |
+# May you share freely, never taking more than you give. |
+# |
+#*********************************************************************** |
+# |
+# Test that focus on incremental merges of segments. |
+# |
+ |
+source [file join [file dirname [info script]] fts5_common.tcl] |
+set testprefix fts5merge |
+ |
+# If SQLITE_ENABLE_FTS5 is defined, omit this file. |
+ifcapable !fts5 { |
+ finish_test |
+ return |
+} |
+ |
+db func repeat [list string repeat] |
+ |
+#------------------------------------------------------------------------- |
+# Create an fts index so that: |
+# |
+# * the index consists of two top-level segments |
+# * each segment contains records related to $nRowPerSeg rows |
+# * all rows consist of tokens "x" and "y" only. |
+# |
+# Then run ('merge', 1) until everything is completely merged. |
+# |
+proc do_merge1_test {testname nRowPerSeg} { |
+ set ::nRowPerSeg [expr $nRowPerSeg] |
+ do_execsql_test $testname.0 { |
+ DROP TABLE IF EXISTS x8; |
+ CREATE VIRTUAL TABLE x8 USING fts5(i); |
+ INSERT INTO x8(x8, rank) VALUES('pgsz', 32); |
+ |
+ WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<$::nRowPerSeg) |
+ INSERT INTO x8 SELECT repeat('x y ', i % 16) FROM ii; |
+ |
+ WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<$::nRowPerSeg) |
+ INSERT INTO x8 SELECT repeat('x y ', i % 16) FROM ii; |
+ |
+ INSERT INTO x8(x8, rank) VALUES('usermerge', 2); |
+ } |
+ |
+ for {set tn 1} {[lindex [fts5_level_segs x8] 0]>0} {incr tn} { |
+ do_execsql_test $testname.$tn { |
+ INSERT INTO x8(x8, rank) VALUES('merge', 1); |
+ INSERT INTO x8(x8) VALUES('integrity-check'); |
+ } |
+ if {$tn>5} break |
+ } |
+ |
+ do_test $testname.x [list expr "$tn < 5"] 1 |
+} |
+ |
+do_merge1_test 1.1 1 |
+do_merge1_test 1.2 2 |
+do_merge1_test 1.3 3 |
+do_merge1_test 1.4 4 |
+do_merge1_test 1.5 10 |
+do_merge1_test 1.6 20 |
+do_merge1_test 1.7 100 |
+ |
+#------------------------------------------------------------------------- |
+# |
+proc do_merge2_test {testname nRow} { |
+ db func rnddoc fts5_rnddoc |
+ |
+ do_execsql_test $testname.0 { |
+ DROP TABLE IF EXISTS x8; |
+ CREATE VIRTUAL TABLE x8 USING fts5(i); |
+ INSERT INTO x8(x8, rank) VALUES('pgsz', 32); |
+ } |
+ |
+ set ::nRow $nRow |
+ do_test $testname.1 { |
+ for {set i 0} {$i < $::nRow} {incr i} { |
+ execsql { INSERT INTO x8 VALUES( rnddoc(($i%16) + 5) ) } |
+ while {[not_merged x8]} { |
+ execsql { |
+ INSERT INTO x8(x8, rank) VALUES('usermerge', 2); |
+ INSERT INTO x8(x8, rank) VALUES('merge', 1); |
+ INSERT INTO x8(x8, rank) VALUES('usermerge', 16); |
+ INSERT INTO x8(x8) VALUES('integrity-check'); |
+ } |
+ } |
+ } |
+ } {} |
+} |
+proc not_merged {tbl} { |
+ set segs [fts5_level_segs $tbl] |
+ foreach s $segs { if {$s>1} { return 1 } } |
+ return 0 |
+} |
+ |
+do_merge2_test 2.1 5 |
+do_merge2_test 2.2 10 |
+do_merge2_test 2.3 20 |
+ |
+#------------------------------------------------------------------------- |
+# Test that a merge will complete any merge that has already been |
+# started, even if the number of input segments is less than the current |
+# value of the 'usermerge' configuration parameter. |
+# |
+db func rnddoc fts5_rnddoc |
+ |
+do_execsql_test 3.1 { |
+ DROP TABLE IF EXISTS x8; |
+ CREATE VIRTUAL TABLE x8 USING fts5(i); |
+ INSERT INTO x8(x8, rank) VALUES('pgsz', 32); |
+ INSERT INTO x8 VALUES(rnddoc(100)); |
+ INSERT INTO x8 VALUES(rnddoc(100)); |
+} |
+do_test 3.2 { |
+ execsql { |
+ INSERT INTO x8(x8, rank) VALUES('usermerge', 4); |
+ INSERT INTO x8(x8, rank) VALUES('merge', 1); |
+ } |
+ fts5_level_segs x8 |
+} {2} |
+ |
+do_test 3.3 { |
+ execsql { |
+ INSERT INTO x8(x8, rank) VALUES('usermerge', 2); |
+ INSERT INTO x8(x8, rank) VALUES('merge', 1); |
+ } |
+ fts5_level_segs x8 |
+} {2 1} |
+ |
+do_test 3.4 { |
+ execsql { INSERT INTO x8(x8, rank) VALUES('usermerge', 4) } |
+ while {[not_merged x8]} { |
+ execsql { INSERT INTO x8(x8, rank) VALUES('merge', 1) } |
+ } |
+ fts5_level_segs x8 |
+} {0 1} |
+ |
+#------------------------------------------------------------------------- |
+# |
+proc mydoc {} { |
+ set x [lindex {a b c d e f g h i j} [expr int(rand()*10)]] |
+ return [string repeat "$x " 30] |
+} |
+db func mydoc mydoc |
+ |
+proc mycount {} { |
+ set res [list] |
+ foreach x {a b c d e f g h i j} { |
+ lappend res [db one {SELECT count(*) FROM x8 WHERE x8 MATCH $x}] |
+ } |
+ set res |
+} |
+ |
+ #1 32 |
+foreach {tn pgsz} { |
+ 2 1000 |
+} { |
+ do_execsql_test 4.$tn.1 { |
+ DROP TABLE IF EXISTS x8; |
+ CREATE VIRTUAL TABLE x8 USING fts5(i); |
+ INSERT INTO x8(x8, rank) VALUES('pgsz', $pgsz); |
+ } |
+ |
+ do_execsql_test 4.$tn.2 { |
+ INSERT INTO x8(x8, rank) VALUES('merge', 1); |
+ } |
+ |
+ do_execsql_test 4.$tn.3 { |
+ WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100) |
+ INSERT INTO x8 SELECT mydoc() FROM ii; |
+ WITH ii(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM ii WHERE i<100) |
+ INSERT INTO x8 SELECT mydoc() FROM ii; |
+ INSERT INTO x8(x8, rank) VALUES('usermerge', 2); |
+ } |
+ |
+ set expect [mycount] |
+ for {set i 0} {$i < 20} {incr i} { |
+ do_test 4.$tn.4.$i { |
+ execsql { INSERT INTO x8(x8, rank) VALUES('merge', 1); } |
+ mycount |
+ } $expect |
+ break |
+ } |
+# db eval {SELECT fts5_decode(rowid, block) AS r FROM x8_data} { puts $r } |
+} |
+ |
+#------------------------------------------------------------------------- |
+# Test that the 'merge' command does not modify the database if there is |
+# no work to do. |
+ |
+do_execsql_test 5.1 { |
+ CREATE VIRTUAL TABLE x9 USING fts5(one, two); |
+ INSERT INTO x9(x9, rank) VALUES('pgsz', 32); |
+ INSERT INTO x9(x9, rank) VALUES('automerge', 2); |
+ INSERT INTO x9(x9, rank) VALUES('usermerge', 2); |
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); |
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); |
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); |
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); |
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); |
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); |
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); |
+ INSERT INTO x9 VALUES(rnddoc(100), rnddoc(100)); |
+} |
+ |
+do_test 5.2 { |
+ while 1 { |
+ set nChange [db total_changes] |
+ execsql { INSERT INTO x9(x9, rank) VALUES('merge', 1); } |
+ set nChange [expr [db total_changes] - $nChange] |
+ #puts $nChange |
+ if {$nChange<2} break |
+ } |
+} {} |
+ |
+ |
+#-------------------------------------------------------------------------- |
+# Test that running 'merge' on an empty database does not cause a |
+# problem. |
+# |
+reset_db |
+do_execsql_test 6.0 { |
+ CREATE VIRTUAL TABLE g1 USING fts5(a, b); |
+} |
+do_execsql_test 6.1 { |
+ INSERT INTO g1(g1, rank) VALUES('merge', 10); |
+} |
+do_execsql_test 6.2 { |
+ INSERT INTO g1(g1, rank) VALUES('merge', -10); |
+} |
+do_execsql_test 6.3 { |
+ INSERT INTO g1(g1) VALUES('integrity-check'); |
+} |
+ |
+ |
+ |
+finish_test |
+ |