2016-03-07 23:14:27 +03:00
|
|
|
# 2016 March 8
|
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
#
|
|
|
|
#*************************************************************************
|
|
|
|
#
|
|
|
|
|
|
|
|
set testdir [file dirname $argv0]
|
|
|
|
source $testdir/tester.tcl
|
|
|
|
source $testdir/fts3_common.tcl
|
|
|
|
set ::testprefix fts4opt
|
|
|
|
|
|
|
|
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
|
|
|
ifcapable !fts3 {
|
|
|
|
finish_test
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
# Create the fts_kjv_genesis procedure which fills and FTS3/4 table
|
|
|
|
# with the complete text of the Book of Genesis.
|
|
|
|
#
|
|
|
|
source $testdir/genesis.tcl
|
|
|
|
|
|
|
|
do_execsql_test 1.0 { CREATE TABLE t1(docid, words) }
|
|
|
|
fts_kjv_genesis
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
# Argument $db is an open database handle. $tbl is the name of an FTS3/4
|
|
|
|
# table with the database. This command rearranges the contents of the
|
|
|
|
# %_segdir table so that all segments within each index are on the same
|
|
|
|
# level. This means that the 'merge' command can then be used for an
|
|
|
|
# incremental optimize routine.
|
|
|
|
#
|
|
|
|
proc prepare_for_optimize {db tbl} {
|
|
|
|
$db eval [string map [list % $tbl] {
|
|
|
|
BEGIN;
|
|
|
|
CREATE TEMP TABLE tmp_segdir(
|
|
|
|
level, idx, start_block, leaves_end_block, end_block, root
|
|
|
|
);
|
|
|
|
|
|
|
|
INSERT INTO temp.tmp_segdir
|
|
|
|
SELECT
|
|
|
|
1024*(o.level / 1024) + 32, -- level
|
|
|
|
sum(o.level<i.level OR (o.level=i.level AND o.idx>i.idx)), -- idx
|
|
|
|
o.start_block, o.leaves_end_block, o.end_block, o.root -- other
|
|
|
|
FROM %_segdir o, %_segdir i
|
|
|
|
WHERE (o.level / 1024) = (i.level / 1024)
|
|
|
|
GROUP BY o.level, o.idx;
|
|
|
|
|
|
|
|
DELETE FROM %_segdir;
|
|
|
|
INSERT INTO %_segdir SELECT * FROM temp.tmp_segdir;
|
|
|
|
DROP TABLE temp.tmp_segdir;
|
|
|
|
|
|
|
|
COMMIT;
|
|
|
|
}]
|
|
|
|
}
|
|
|
|
|
|
|
|
do_test 1.1 {
|
|
|
|
execsql { CREATE VIRTUAL TABLE t2 USING fts4(words, prefix="1,2,3") }
|
|
|
|
foreach {docid words} [db eval { SELECT * FROM t1 }] {
|
|
|
|
execsql { INSERT INTO t2(docid, words) VALUES($docid, $words) }
|
|
|
|
}
|
|
|
|
} {}
|
|
|
|
|
|
|
|
do_execsql_test 1.2 {
|
|
|
|
SELECT level, count(*) FROM t2_segdir GROUP BY level
|
|
|
|
} {
|
|
|
|
0 13 1 15 2 5
|
|
|
|
1024 13 1025 15 1026 5
|
|
|
|
2048 13 2049 15 2050 5
|
|
|
|
3072 13 3073 15 3074 5
|
|
|
|
}
|
|
|
|
|
|
|
|
do_execsql_test 1.3 { INSERT INTO t2(t2) VALUES('integrity-check') }
|
|
|
|
prepare_for_optimize db t2
|
|
|
|
do_execsql_test 1.4 { INSERT INTO t2(t2) VALUES('integrity-check') }
|
|
|
|
|
|
|
|
do_execsql_test 1.5 {
|
|
|
|
SELECT level, count(*) FROM t2_segdir GROUP BY level
|
|
|
|
} {
|
|
|
|
32 33
|
|
|
|
1056 33
|
|
|
|
2080 33
|
|
|
|
3104 33
|
|
|
|
}
|
|
|
|
|
|
|
|
do_test 1.6 {
|
|
|
|
while 1 {
|
|
|
|
set tc1 [db total_changes]
|
2016-03-08 18:37:48 +03:00
|
|
|
execsql { INSERT INTO t2(t2) VALUES('merge=5,2') }
|
2016-03-07 23:14:27 +03:00
|
|
|
set tc2 [db total_changes]
|
|
|
|
if {($tc2 - $tc1) < 2} break
|
|
|
|
}
|
|
|
|
execsql { SELECT level, count(*) FROM t2_segdir GROUP BY level }
|
|
|
|
} {33 1 1057 1 2081 1 3105 1}
|
|
|
|
do_execsql_test 1.7 { INSERT INTO t2(t2) VALUES('integrity-check') }
|
|
|
|
|
|
|
|
do_execsql_test 1.8 {
|
|
|
|
INSERT INTO t2(words) SELECT words FROM t1;
|
|
|
|
SELECT level, count(*) FROM t2_segdir GROUP BY level;
|
|
|
|
} {0 2 1024 2 2048 2 3072 2}
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
|
|
|
|
do_execsql_test 2.0 {
|
|
|
|
DELETE FROM t2;
|
|
|
|
}
|
|
|
|
do_test 2.1 {
|
|
|
|
foreach {docid words} [db eval { SELECT * FROM t1 }] {
|
|
|
|
execsql { INSERT INTO t2(docid, words) VALUES($docid, $words) }
|
|
|
|
}
|
|
|
|
|
|
|
|
set i 0
|
|
|
|
foreach {docid words} [db eval { SELECT * FROM t1 }] {
|
|
|
|
if {[incr i] % 2} { execsql { DELETE FROM t2 WHERE docid = $docid } }
|
|
|
|
}
|
|
|
|
|
|
|
|
set i 0
|
|
|
|
foreach {docid words} [db eval { SELECT * FROM t1 }] {
|
|
|
|
if {[incr i] % 3} {
|
|
|
|
execsql { INSERT OR REPLACE INTO t2(docid, words) VALUES($docid, $words) }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} {}
|
|
|
|
|
|
|
|
do_execsql_test 2.2 {
|
|
|
|
SELECT level, count(*) FROM t2_segdir GROUP BY level
|
|
|
|
} {
|
|
|
|
0 10 1 15 2 12
|
|
|
|
1024 10 1025 15 1026 12
|
|
|
|
2048 10 2049 15 2050 12
|
|
|
|
3072 10 3073 15 3074 12
|
|
|
|
}
|
|
|
|
|
|
|
|
do_execsql_test 2.3 { INSERT INTO t2(t2) VALUES('integrity-check') }
|
|
|
|
prepare_for_optimize db t2
|
|
|
|
do_execsql_test 2.4 { INSERT INTO t2(t2) VALUES('integrity-check') }
|
|
|
|
|
|
|
|
do_execsql_test 2.5 {
|
|
|
|
SELECT level, count(*) FROM t2_segdir GROUP BY level
|
|
|
|
} {
|
|
|
|
32 37
|
|
|
|
1056 37
|
|
|
|
2080 37
|
|
|
|
3104 37
|
|
|
|
}
|
|
|
|
|
|
|
|
do_test 2.6 {
|
|
|
|
while 1 {
|
|
|
|
set tc1 [db total_changes]
|
2016-03-08 18:37:48 +03:00
|
|
|
execsql { INSERT INTO t2(t2) VALUES('merge=5,2') }
|
2016-03-07 23:14:27 +03:00
|
|
|
set tc2 [db total_changes]
|
|
|
|
if {($tc2 - $tc1) < 2} break
|
|
|
|
}
|
|
|
|
execsql { SELECT level, count(*) FROM t2_segdir GROUP BY level }
|
|
|
|
} {33 1 1057 1 2081 1 3105 1}
|
|
|
|
do_execsql_test 2.7 { INSERT INTO t2(t2) VALUES('integrity-check') }
|
|
|
|
|
|
|
|
do_execsql_test 2.8 {
|
|
|
|
INSERT INTO t2(words) SELECT words FROM t1;
|
|
|
|
SELECT level, count(*) FROM t2_segdir GROUP BY level;
|
|
|
|
} {0 2 1024 2 2048 2 3072 2}
|
|
|
|
|
2016-03-09 21:17:42 +03:00
|
|
|
#-------------------------------------------------------------------------
|
|
|
|
# Check that 'optimize' works when there is data in the in-memory hash
|
|
|
|
# table, but no segments at all on disk.
|
|
|
|
#
|
|
|
|
do_execsql_test 3.1 {
|
|
|
|
CREATE VIRTUAL TABLE fts USING fts4 (t);
|
|
|
|
INSERT INTO fts (fts) VALUES ('optimize');
|
|
|
|
}
|
|
|
|
do_execsql_test 3.2 {
|
|
|
|
INSERT INTO fts(fts) VALUES('integrity-check');
|
|
|
|
SELECT count(*) FROM fts_segdir;
|
|
|
|
} {0}
|
|
|
|
do_execsql_test 3.3 {
|
|
|
|
BEGIN;
|
|
|
|
INSERT INTO fts (rowid, t) VALUES (2, 'test');
|
|
|
|
INSERT INTO fts (fts) VALUES ('optimize');
|
|
|
|
COMMIT;
|
|
|
|
SELECT level, idx FROM fts_segdir;
|
|
|
|
} {0 0}
|
|
|
|
do_execsql_test 3.4 {
|
|
|
|
INSERT INTO fts(fts) VALUES('integrity-check');
|
|
|
|
SELECT rowid FROM fts WHERE fts MATCH 'test';
|
|
|
|
} {2}
|
|
|
|
do_execsql_test 3.5 {
|
|
|
|
INSERT INTO fts (fts) VALUES ('optimize');
|
|
|
|
INSERT INTO fts(fts) VALUES('integrity-check');
|
|
|
|
}
|
|
|
|
do_test 3.6 {
|
|
|
|
set c1 [db total_changes]
|
|
|
|
execsql { INSERT INTO fts (fts) VALUES ('optimize') }
|
|
|
|
expr {[db total_changes] - $c1}
|
|
|
|
} {1}
|
|
|
|
do_test 3.7 {
|
|
|
|
execsql { INSERT INTO fts (rowid, t) VALUES (3, 'xyz') }
|
|
|
|
set c1 [db total_changes]
|
|
|
|
execsql { INSERT INTO fts (fts) VALUES ('optimize') }
|
|
|
|
expr {([db total_changes] - $c1) > 1}
|
|
|
|
} {1}
|
|
|
|
do_test 3.8 {
|
|
|
|
set c1 [db total_changes]
|
|
|
|
execsql { INSERT INTO fts (fts) VALUES ('optimize') }
|
|
|
|
expr {[db total_changes] - $c1}
|
|
|
|
} {1}
|
|
|
|
|
2016-03-07 23:14:27 +03:00
|
|
|
finish_test
|