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