1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
|
# 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.
#
#***********************************************************************
#
# Tests of the scalar fts5_rowid() and fts5_decode() functions.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5rowid
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_catchsql_test 1.1 {
SELECT fts5_rowid()
} {1 {should be: fts5_rowid(subject, ....)}}
do_catchsql_test 1.2 {
SELECT fts5_rowid('segment')
} {1 {should be: fts5_rowid('segment', segid, pgno))}}
do_execsql_test 1.3 {
SELECT fts5_rowid('segment', 1, 1)
} {137438953473}
do_catchsql_test 1.4 {
SELECT fts5_rowid('nosucharg');
} {1 {first arg to fts5_rowid() must be 'segment'}}
#-------------------------------------------------------------------------
# Tests of the fts5_decode() function.
#
reset_db
do_execsql_test 2.1 {
CREATE VIRTUAL TABLE x1 USING fts5(a, b);
INSERT INTO x1(x1, rank) VALUES('pgsz', 32);
} {}
proc rnddoc {n} {
set map [list 0 a 1 b 2 c 3 d 4 e 5 f 6 g 7 h 8 i 9 j]
set doc [list]
for {set i 0} {$i < $n} {incr i} {
lappend doc [string map $map [format %.3d [expr int(rand()*100)]]]
}
set doc
}
db func rnddoc rnddoc
do_execsql_test 2.2 {
WITH r(a, b) AS (
SELECT rnddoc(6), rnddoc(6) UNION ALL
SELECT rnddoc(6), rnddoc(6) FROM r
)
INSERT INTO x1 SELECT * FROM r LIMIT 10000;
DELETE FROM x1 WHERE (rowid%2);
}
set res [db one {SELECT count(*) FROM x1_data}]
do_execsql_test 2.3 {
SELECT count(fts5_decode(rowid, block)) FROM x1_data;
} $res
sqlite3_db_config db DEFENSIVE 0
do_execsql_test 2.4 {
UPDATE x1_data SET block = X'';
SELECT count(fts5_decode(rowid, block)) FROM x1_data;
} $res
do_execsql_test 2.5 {
INSERT INTO x1(x1, rank) VALUES('pgsz', 1024);
INSERT INTO x1(x1) VALUES('rebuild');
}
set res [db one {SELECT count(*) FROM x1_data}]
do_execsql_test 2.6 {
SELECT count(fts5_decode(rowid, block)) FROM x1_data;
} $res
# This is really a corruption test...
#do_execsql_test 2.7 {
# UPDATE x1_data SET block = X'';
# SELECT count(fts5_decode(rowid, block)) FROM x1_data;
#} $res
do_execsql_test 2.8 {
SELECT fts5_decode(fts5_rowid('segment', 1000, 1), X'AB')
} {corrupt}
#-------------------------------------------------------------------------
# Tests with very large tokens.
#
set strlist [list \
"[string repeat x 400]" \
"[string repeat x 300][string repeat w 100]" \
"[string repeat x 300][string repeat y 100]" \
"[string repeat x 300][string repeat z 600]" \
]
do_test 3.0 {
execsql {
BEGIN;
CREATE VIRTUAL TABLE x2 USING fts5(a);
}
foreach str $strlist { execsql { INSERT INTO x2 VALUES($str) } }
execsql COMMIT
} {}
for {set tn 0} {$tn<[llength $strlist]} {incr tn} {
set str [lindex $strlist $tn]
do_execsql_test 3.1.$tn {
SELECT rowid FROM x2 WHERE x2 MATCH $str
} [expr $tn+1]
}
set res [db one {SELECT count(*) FROM x2_data}]
do_execsql_test 3.2 {
SELECT count(fts5_decode(rowid, block)) FROM x2_data;
} $res
#-------------------------------------------------------------------------
# Leaf pages with no terms or rowids at all.
#
set strlist [list \
"[string repeat {w } 400]" \
"[string repeat {x } 400]" \
"[string repeat {y } 400]" \
"[string repeat {z } 400]" \
]
do_test 4.0 {
execsql {
BEGIN;
CREATE VIRTUAL TABLE x3 USING fts5(a);
INSERT INTO x3(x3, rank) VALUES('pgsz', 32);
}
foreach str $strlist { execsql { INSERT INTO x3 VALUES($str) } }
execsql COMMIT
} {}
for {set tn 0} {$tn<[llength $strlist]} {incr tn} {
set str [lindex $strlist $tn]
do_execsql_test 4.1.$tn {
SELECT rowid FROM x3 WHERE x3 MATCH $str
} [expr $tn+1]
}
set res [db one {SELECT count(*) FROM x3_data}]
do_execsql_test 4.2 {
SELECT count(fts5_decode(rowid, block)) FROM x3_data;
} $res
#-------------------------------------------------------------------------
# Position lists with large values.
#
set strlist [list \
"[string repeat {w } 400]a" \
"[string repeat {x } 400]a" \
"[string repeat {y } 400]a" \
"[string repeat {z } 400]a" \
]
do_test 5.0 {
execsql {
BEGIN;
CREATE VIRTUAL TABLE x4 USING fts5(a);
INSERT INTO x4(x4, rank) VALUES('pgsz', 32);
}
foreach str $strlist { execsql { INSERT INTO x4 VALUES($str) } }
execsql COMMIT
} {}
do_execsql_test 5.1 {
SELECT rowid FROM x4 WHERE x4 MATCH 'a'
} {1 2 3 4}
set res [db one {SELECT count(*) FROM x4_data}]
do_execsql_test 5.2 {
SELECT count(fts5_decode(rowid, block)) FROM x4_data;
} $res
#-------------------------------------------------------------------------
#
do_execsql_test 6.0 {
CREATE VIRTUAL TABLE x5 USING fts5(x, detail=none);
INSERT INTO x5(x5, rank) VALUES('pgsz', 32);
INSERT INTO x5 VALUES('a b c d e f');
INSERT INTO x5 VALUES('a b c d e f');
INSERT INTO x5 VALUES('a b c d e f');
BEGIN;
WITH s(i) AS (
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100
) INSERT INTO x5 SELECT 'a b c d e f' FROM s;
COMMIT;
SELECT count(fts5_decode_none(rowid, block)) FROM x5_data;
} {32}
do_execsql_test 6.1 {
DELETE FROM x5 WHERE rowid <= 2;
SELECT count(fts5_decode_none(rowid, block)) FROM x5_data;
} {34}
do_execsql_test 6.2 {
UPDATE x5 SET x='a b c d e f' WHERE rowid=3;
SELECT count(fts5_decode_none(rowid, block)) FROM x5_data;
} {36}
#db eval {SELECT rowid, fts5_decode_none(rowid, block) aS r FROM x5_data} {puts $r}
finish_test
|