1108b7953Sdan# 2016 March 8 2108b7953Sdan# 3108b7953Sdan# The author disclaims copyright to this source code. In place of 4108b7953Sdan# a legal notice, here is a blessing: 5108b7953Sdan# 6108b7953Sdan# May you do good and not evil. 7108b7953Sdan# May you find forgiveness for yourself and forgive others. 8108b7953Sdan# May you share freely, never taking more than you give. 9108b7953Sdan# 10108b7953Sdan#************************************************************************* 11108b7953Sdan# 12108b7953Sdan 13108b7953Sdanset testdir [file dirname $argv0] 14108b7953Sdansource $testdir/tester.tcl 15108b7953Sdansource $testdir/fts3_common.tcl 16108b7953Sdanset ::testprefix fts4opt 17108b7953Sdan 18108b7953Sdan# If SQLITE_ENABLE_FTS3 is defined, omit this file. 19108b7953Sdanifcapable !fts3 { 20108b7953Sdan finish_test 21108b7953Sdan return 22108b7953Sdan} 23108b7953Sdan 24108b7953Sdan# Create the fts_kjv_genesis procedure which fills and FTS3/4 table 25108b7953Sdan# with the complete text of the Book of Genesis. 26108b7953Sdan# 27108b7953Sdansource $testdir/genesis.tcl 28108b7953Sdan 29108b7953Sdando_execsql_test 1.0 { CREATE TABLE t1(docid, words) } 30108b7953Sdanfts_kjv_genesis 31108b7953Sdan 32108b7953Sdan#------------------------------------------------------------------------- 33108b7953Sdan# Argument $db is an open database handle. $tbl is the name of an FTS3/4 34108b7953Sdan# table with the database. This command rearranges the contents of the 35108b7953Sdan# %_segdir table so that all segments within each index are on the same 36108b7953Sdan# level. This means that the 'merge' command can then be used for an 37108b7953Sdan# incremental optimize routine. 38108b7953Sdan# 39108b7953Sdanproc prepare_for_optimize {db tbl} { 40*0f0d3ddfSdrh sqlite3_db_config $db DEFENSIVE 0 41108b7953Sdan $db eval [string map [list % $tbl] { 42108b7953Sdan BEGIN; 43108b7953Sdan CREATE TEMP TABLE tmp_segdir( 44108b7953Sdan level, idx, start_block, leaves_end_block, end_block, root 45108b7953Sdan ); 46108b7953Sdan 47108b7953Sdan INSERT INTO temp.tmp_segdir 48108b7953Sdan SELECT 49108b7953Sdan 1024*(o.level / 1024) + 32, -- level 50108b7953Sdan sum(o.level<i.level OR (o.level=i.level AND o.idx>i.idx)), -- idx 51108b7953Sdan o.start_block, o.leaves_end_block, o.end_block, o.root -- other 52108b7953Sdan FROM %_segdir o, %_segdir i 53108b7953Sdan WHERE (o.level / 1024) = (i.level / 1024) 54108b7953Sdan GROUP BY o.level, o.idx; 55108b7953Sdan 56108b7953Sdan DELETE FROM %_segdir; 57108b7953Sdan INSERT INTO %_segdir SELECT * FROM temp.tmp_segdir; 58108b7953Sdan DROP TABLE temp.tmp_segdir; 59108b7953Sdan 60108b7953Sdan COMMIT; 61108b7953Sdan }] 62108b7953Sdan} 63108b7953Sdan 64108b7953Sdando_test 1.1 { 65108b7953Sdan execsql { CREATE VIRTUAL TABLE t2 USING fts4(words, prefix="1,2,3") } 66108b7953Sdan foreach {docid words} [db eval { SELECT * FROM t1 }] { 67108b7953Sdan execsql { INSERT INTO t2(docid, words) VALUES($docid, $words) } 68108b7953Sdan } 69108b7953Sdan} {} 70108b7953Sdan 71108b7953Sdando_execsql_test 1.2 { 72108b7953Sdan SELECT level, count(*) FROM t2_segdir GROUP BY level 73108b7953Sdan} { 74108b7953Sdan 0 13 1 15 2 5 75108b7953Sdan 1024 13 1025 15 1026 5 76108b7953Sdan 2048 13 2049 15 2050 5 77108b7953Sdan 3072 13 3073 15 3074 5 78108b7953Sdan} 79108b7953Sdan 80108b7953Sdando_execsql_test 1.3 { INSERT INTO t2(t2) VALUES('integrity-check') } 81108b7953Sdanprepare_for_optimize db t2 82108b7953Sdando_execsql_test 1.4 { INSERT INTO t2(t2) VALUES('integrity-check') } 83108b7953Sdan 84108b7953Sdando_execsql_test 1.5 { 85108b7953Sdan SELECT level, count(*) FROM t2_segdir GROUP BY level 86108b7953Sdan} { 87108b7953Sdan 32 33 88108b7953Sdan 1056 33 89108b7953Sdan 2080 33 90108b7953Sdan 3104 33 91108b7953Sdan} 92108b7953Sdan 93108b7953Sdando_test 1.6 { 94108b7953Sdan while 1 { 95108b7953Sdan set tc1 [db total_changes] 96c7dbce0fSdan execsql { INSERT INTO t2(t2) VALUES('merge=5,2') } 97108b7953Sdan set tc2 [db total_changes] 98108b7953Sdan if {($tc2 - $tc1) < 2} break 99108b7953Sdan } 100108b7953Sdan execsql { SELECT level, count(*) FROM t2_segdir GROUP BY level } 101108b7953Sdan} {33 1 1057 1 2081 1 3105 1} 102108b7953Sdando_execsql_test 1.7 { INSERT INTO t2(t2) VALUES('integrity-check') } 103108b7953Sdan 104108b7953Sdando_execsql_test 1.8 { 105108b7953Sdan INSERT INTO t2(words) SELECT words FROM t1; 106108b7953Sdan SELECT level, count(*) FROM t2_segdir GROUP BY level; 107108b7953Sdan} {0 2 1024 2 2048 2 3072 2} 108108b7953Sdan 109108b7953Sdan#------------------------------------------------------------------------- 110108b7953Sdan 111108b7953Sdando_execsql_test 2.0 { 112108b7953Sdan DELETE FROM t2; 113108b7953Sdan} 114108b7953Sdando_test 2.1 { 115108b7953Sdan foreach {docid words} [db eval { SELECT * FROM t1 }] { 116108b7953Sdan execsql { INSERT INTO t2(docid, words) VALUES($docid, $words) } 117108b7953Sdan } 118108b7953Sdan 119108b7953Sdan set i 0 120108b7953Sdan foreach {docid words} [db eval { SELECT * FROM t1 }] { 121108b7953Sdan if {[incr i] % 2} { execsql { DELETE FROM t2 WHERE docid = $docid } } 122108b7953Sdan } 123108b7953Sdan 124108b7953Sdan set i 0 125108b7953Sdan foreach {docid words} [db eval { SELECT * FROM t1 }] { 126108b7953Sdan if {[incr i] % 3} { 127108b7953Sdan execsql { INSERT OR REPLACE INTO t2(docid, words) VALUES($docid, $words) } 128108b7953Sdan } 129108b7953Sdan } 130108b7953Sdan} {} 131108b7953Sdan 132108b7953Sdando_execsql_test 2.2 { 133108b7953Sdan SELECT level, count(*) FROM t2_segdir GROUP BY level 134108b7953Sdan} { 135108b7953Sdan 0 10 1 15 2 12 136108b7953Sdan 1024 10 1025 15 1026 12 137108b7953Sdan 2048 10 2049 15 2050 12 138108b7953Sdan 3072 10 3073 15 3074 12 139108b7953Sdan} 140108b7953Sdan 141108b7953Sdando_execsql_test 2.3 { INSERT INTO t2(t2) VALUES('integrity-check') } 142108b7953Sdanprepare_for_optimize db t2 143108b7953Sdando_execsql_test 2.4 { INSERT INTO t2(t2) VALUES('integrity-check') } 144108b7953Sdan 145108b7953Sdando_execsql_test 2.5 { 146108b7953Sdan SELECT level, count(*) FROM t2_segdir GROUP BY level 147108b7953Sdan} { 148108b7953Sdan 32 37 149108b7953Sdan 1056 37 150108b7953Sdan 2080 37 151108b7953Sdan 3104 37 152108b7953Sdan} 153108b7953Sdan 154108b7953Sdando_test 2.6 { 155108b7953Sdan while 1 { 156108b7953Sdan set tc1 [db total_changes] 157c7dbce0fSdan execsql { INSERT INTO t2(t2) VALUES('merge=5,2') } 158108b7953Sdan set tc2 [db total_changes] 159108b7953Sdan if {($tc2 - $tc1) < 2} break 160108b7953Sdan } 161108b7953Sdan execsql { SELECT level, count(*) FROM t2_segdir GROUP BY level } 162108b7953Sdan} {33 1 1057 1 2081 1 3105 1} 163108b7953Sdando_execsql_test 2.7 { INSERT INTO t2(t2) VALUES('integrity-check') } 164108b7953Sdan 165108b7953Sdando_execsql_test 2.8 { 166108b7953Sdan INSERT INTO t2(words) SELECT words FROM t1; 167108b7953Sdan SELECT level, count(*) FROM t2_segdir GROUP BY level; 168108b7953Sdan} {0 2 1024 2 2048 2 3072 2} 169108b7953Sdan 17057ebc84aSdan#------------------------------------------------------------------------- 17157ebc84aSdan# Check that 'optimize' works when there is data in the in-memory hash 17257ebc84aSdan# table, but no segments at all on disk. 17357ebc84aSdan# 17457ebc84aSdando_execsql_test 3.1 { 17557ebc84aSdan CREATE VIRTUAL TABLE fts USING fts4 (t); 17657ebc84aSdan INSERT INTO fts (fts) VALUES ('optimize'); 17757ebc84aSdan} 17857ebc84aSdando_execsql_test 3.2 { 17957ebc84aSdan INSERT INTO fts(fts) VALUES('integrity-check'); 18057ebc84aSdan SELECT count(*) FROM fts_segdir; 18157ebc84aSdan} {0} 18257ebc84aSdando_execsql_test 3.3 { 18357ebc84aSdan BEGIN; 18457ebc84aSdan INSERT INTO fts (rowid, t) VALUES (2, 'test'); 18557ebc84aSdan INSERT INTO fts (fts) VALUES ('optimize'); 18657ebc84aSdan COMMIT; 18757ebc84aSdan SELECT level, idx FROM fts_segdir; 18857ebc84aSdan} {0 0} 18957ebc84aSdando_execsql_test 3.4 { 19057ebc84aSdan INSERT INTO fts(fts) VALUES('integrity-check'); 19157ebc84aSdan SELECT rowid FROM fts WHERE fts MATCH 'test'; 19257ebc84aSdan} {2} 19357ebc84aSdando_execsql_test 3.5 { 19457ebc84aSdan INSERT INTO fts (fts) VALUES ('optimize'); 19557ebc84aSdan INSERT INTO fts(fts) VALUES('integrity-check'); 19657ebc84aSdan} 19757ebc84aSdando_test 3.6 { 19857ebc84aSdan set c1 [db total_changes] 19957ebc84aSdan execsql { INSERT INTO fts (fts) VALUES ('optimize') } 20057ebc84aSdan expr {[db total_changes] - $c1} 20157ebc84aSdan} {1} 20257ebc84aSdando_test 3.7 { 20357ebc84aSdan execsql { INSERT INTO fts (rowid, t) VALUES (3, 'xyz') } 20457ebc84aSdan set c1 [db total_changes] 20557ebc84aSdan execsql { INSERT INTO fts (fts) VALUES ('optimize') } 20657ebc84aSdan expr {([db total_changes] - $c1) > 1} 20757ebc84aSdan} {1} 20857ebc84aSdando_test 3.8 { 20957ebc84aSdan set c1 [db total_changes] 21057ebc84aSdan execsql { INSERT INTO fts (fts) VALUES ('optimize') } 21157ebc84aSdan expr {[db total_changes] - $c1} 21257ebc84aSdan} {1} 21357ebc84aSdan 214108b7953Sdanfinish_test 215