xref: /sqlite-3.40.0/test/fts4opt.test (revision 6ab91a7a)
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