xref: /sqlite-3.40.0/ext/fts5/test/fts5dlidx.test (revision 885f4104)
1# 2015 April 21
2#
3# The author disclaims copyright to this source code.  In place of
4# a legal notice, here is a blessing:
5#
6#    May you do good and not evil.
7#    May you find forgiveness for yourself and forgive others.
8#    May you share freely, never taking more than you give.
9#
10#***********************************************************************
11#
12# This test is focused on uses of doclist-index records.
13#
14
15source [file join [file dirname [info script]] fts5_common.tcl]
16set testprefix fts5dlidx
17
18# If SQLITE_ENABLE_FTS5 is defined, omit this file.
19ifcapable !fts5 {
20  finish_test
21  return
22}
23
24if { $tcl_platform(wordSize)<8 } {
25  finish_test
26  return
27}
28
29foreach_detail_mode $testprefix {
30
31proc do_fb_test {tn sql res} {
32  set res2 [lsort -integer -decr $res]
33  uplevel [list do_execsql_test $tn.1 $sql $res]
34  uplevel [list do_execsql_test $tn.2 "$sql ORDER BY rowid DESC" $res2]
35}
36
37# This test populates the FTS5 table with $nEntry entries. Rows are
38# numbered from 0 to ($nEntry-1). The rowid for row $i is:
39#
40#   ($iFirst + $i*$nStep)
41#
42# Each document is of the form "a b c a b c a b c...". If the row number ($i)
43# is an integer multiple of $spc1, then an "x" token is appended to the
44# document. If it is *also* a multiple of $spc2, a "y" token is also appended.
45#
46proc do_dlidx_test1 {tn spc1 spc2 nEntry iFirst nStep} {
47
48  do_execsql_test $tn.0 { DELETE FROM t1 }
49
50  set xdoc [list]
51  set ydoc [list]
52
53  execsql BEGIN
54  for {set i 0} {$i < $nEntry} {incr i} {
55    set rowid [expr $i * $nStep]
56    set doc [string trim [string repeat "a b c " 100]]
57    if {($i % $spc1)==0} {
58      lappend xdoc $rowid
59      append doc " x"
60      if {($i % $spc2)==0} {
61        lappend ydoc $rowid
62        append doc " y"
63      }
64    }
65    execsql { INSERT INTO t1(rowid, x) VALUES($rowid, $doc) }
66  }
67  execsql COMMIT
68
69  do_test $tn.1 {
70    execsql { INSERT INTO t1(t1) VALUES('integrity-check') }
71  } {}
72
73  do_fb_test $tn.3.1 { SELECT rowid FROM t1 WHERE t1 MATCH 'a AND x' } $xdoc
74  do_fb_test $tn.3.2 { SELECT rowid FROM t1 WHERE t1 MATCH 'x AND a' } $xdoc
75
76  do_fb_test $tn.4.1 { SELECT rowid FROM t1 WHERE t1 MATCH 'a AND y' } $ydoc
77  do_fb_test $tn.4.2 { SELECT rowid FROM t1 WHERE t1 MATCH 'y AND a' } $ydoc
78
79  if {[detail_is_full]} {
80    do_fb_test $tn.5.1 {
81      SELECT rowid FROM t1 WHERE t1 MATCH 'a + b + c + x' } $xdoc
82    do_fb_test $tn.5.2 {
83      SELECT rowid FROM t1 WHERE t1 MATCH 'b + c + x + y' } $ydoc
84  }
85}
86
87
88foreach {tn pgsz} {
89  1 32
90  2 200
91} {
92  do_execsql_test $tn.0 {
93    DROP TABLE IF EXISTS t1;
94    CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%);
95    INSERT INTO t1(t1, rank) VALUES('pgsz', $pgsz);
96  }
97
98  do_dlidx_test1 1.$tn.1     10 100 10000 0 1000
99  do_dlidx_test1 1.$tn.2     10 10  10000 0 128
100  do_dlidx_test1 1.$tn.3     10 10  66    0 36028797018963970
101  do_dlidx_test1 1.$tn.4     10 10  50    0 150000000000000000
102  do_dlidx_test1 1.$tn.5     10 10  200   0 [expr 1<<55]
103  do_dlidx_test1 1.$tn.6      10 10  30    0 [expr 1<<58]
104}
105
106proc do_dlidx_test2 {tn nEntry iFirst nStep} {
107  set str [string repeat "a " 500]
108  execsql {
109    BEGIN;
110    DROP TABLE IF EXISTS t1;
111    CREATE VIRTUAL TABLE t1 USING fts5(x, detail=%DETAIL%);
112    INSERT INTO t1(t1, rank) VALUES('pgsz', 64);
113    INSERT INTO t1 VALUES('b a');
114
115    WITH iii(ii, i) AS (
116      SELECT 1,     $iFirst UNION ALL
117      SELECT ii+1, i+$nStep FROM iii WHERE ii<$nEntry
118    )
119    INSERT INTO t1(rowid,x) SELECT i, $str FROM iii;
120    COMMIT;
121  }
122
123  do_execsql_test $tn.1 {
124    SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a'
125  } {1}
126  do_execsql_test $tn.2 {
127    SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a' ORDER BY rowid DESC
128  } {1}
129}
130
131do_dlidx_test2 2.1 [expr 20] [expr 1<<57] [expr (1<<57) + 128]
132
133#--------------------------------------------------------------------
134#
135reset_db
136
137set ::vocab [list \
138  IteratorpItercurrentlypointstothefirstrowidofadoclist \
139  Thereisadoclistindexassociatedwiththefinaltermonthecurrent \
140  pageIfthecurrenttermisthelasttermonthepageloadthe \
141  doclistindexfromdiskandinitializeaniteratoratpIterpDlidx \
142  IteratorpItercurrentlypointstothefirstrowidofadoclist \
143  Thereisadoclistindexassociatedwiththefinaltermonthecurrent \
144  pageIfthecurrenttermisthelasttermonthepageloadthe \
145  doclistindexfromdiskandinitializeaniteratoratpIterpDlidx \
146]
147proc rnddoc {} {
148  global vocab
149  set nVocab [llength $vocab]
150  set ret [list]
151  for {set i 0} {$i < 64} {incr i} {
152    lappend ret [lindex $vocab [expr $i % $nVocab]]
153  }
154  set ret
155}
156db func rnddoc rnddoc
157
158do_execsql_test 3.1 {
159  CREATE VIRTUAL TABLE abc USING fts5(a, detail=%DETAIL%);
160  INSERT INTO abc(abc, rank) VALUES('pgsz', 32);
161
162  INSERT INTO abc VALUES ( rnddoc() );
163  INSERT INTO abc VALUES ( rnddoc() );
164  INSERT INTO abc VALUES ( rnddoc() );
165  INSERT INTO abc VALUES ( rnddoc() );
166
167  INSERT INTO abc SELECT rnddoc() FROM abc;
168  INSERT INTO abc SELECT rnddoc() FROM abc;
169}
170
171
172
173do_execsql_test 3.2 {
174  SELECT rowid FROM abc WHERE abc
175  MATCH 'IteratorpItercurrentlypointstothefirstrowidofadoclist'
176  ORDER BY rowid DESC;
177} {16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1}
178
179do_execsql_test 3.3 {
180  INSERT INTO abc(abc) VALUES('integrity-check');
181  INSERT INTO abc(abc) VALUES('optimize');
182  INSERT INTO abc(abc) VALUES('integrity-check');
183}
184
185set v [lindex $vocab 0]
186set i 0
187foreach v $vocab {
188  do_execsql_test 3.4.[incr i] {
189    SELECT rowid FROM abc WHERE abc MATCH $v
190  } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
191}
192
193} ;# foreach_detail_mode
194
195
196
197finish_test
198