ifcapable fts3 {
sqlite3_fts3_may_be_corrupt 0
}
proc fts3_build_db_1 {args} {
set default(-module) fts4
set nArg [llength $args]
if {($nArg%2)==0} {
error "wrong # args: should be \"fts3_build_db_1 ?switches? n\""
}
set n [lindex $args [expr $nArg-1]]
array set opts [array get default]
array set opts [lrange $args 0 [expr $nArg-2]]
foreach k [array names opts] {
if {0==[info exists default($k)]} { error "unknown option: $k" }
}
if {$n > 10000} {error "n must be <= 10000"}
db eval "CREATE VIRTUAL TABLE t1 USING $opts(-module) (x, y)"
set xwords [list zero one two three four five six seven eight nine ten]
set ywords [list alpha beta gamma delta epsilon zeta eta theta iota kappa]
for {set i 0} {$i < $n} {incr i} {
set x ""
set y ""
set x [list]
lappend x [lindex $xwords [expr ($i / 1000) % 10]]
lappend x [lindex $xwords [expr ($i / 100) % 10]]
lappend x [lindex $xwords [expr ($i / 10) % 10]]
lappend x [lindex $xwords [expr ($i / 1) % 10]]
set y [list]
lappend y [lindex $ywords [expr ($i / 1000) % 10]]
lappend y [lindex $ywords [expr ($i / 100) % 10]]
lappend y [lindex $ywords [expr ($i / 10) % 10]]
lappend y [lindex $ywords [expr ($i / 1) % 10]]
db eval { INSERT INTO t1(docid, x, y) VALUES($i, $x, $y) }
}
}
proc fts3_build_db_2 {args} {
set default(-module) fts4
set default(-extra) ""
set nArg [llength $args]
if {($nArg%2)==0} {
error "wrong # args: should be \"fts3_build_db_1 ?switches? n\""
}
set n [lindex $args [expr $nArg-1]]
array set opts [array get default]
array set opts [lrange $args 0 [expr $nArg-2]]
foreach k [array names opts] {
if {0==[info exists default($k)]} { error "unknown option: $k" }
}
if {$n > 100000} {error "n must be <= 100000"}
set sql "CREATE VIRTUAL TABLE t2 USING $opts(-module) (content"
if {$opts(-extra) != ""} {
append sql ", " $opts(-extra)
}
append sql ")"
db eval $sql
set chars [list a b c d e f g h i j k l m n o p q r s t u v w x y z ""]
for {set i 0} {$i < $n} {incr i} {
set word ""
set nChar [llength $chars]
append word [lindex $chars [expr {($i / 1) % $nChar}]]
append word [lindex $chars [expr {($i / $nChar) % $nChar}]]
append word [lindex $chars [expr {($i / ($nChar*$nChar)) % $nChar}]]
db eval { INSERT INTO t2(docid, content) VALUES($i, $word) }
}
}
proc fts3_integrity_check {tbl} {
fts3_read2 $tbl 1 A
foreach zTerm [array names A] {
foreach doclist $A($zTerm) {
set docid 0
while {[string length $doclist]>0} {
set iCol 0
set iPos 0
set lPos [list]
set lCol [list]
incr docid [gobble_varint doclist]
if {[info exists D($zTerm,$docid)]} {
while {[set iDelta [gobble_varint doclist]] != 0} {}
continue
}
set D($zTerm,$docid) 1
while {[set iDelta [gobble_varint doclist]] > 0} {
if {$iDelta == 1} {
set iCol [gobble_varint doclist]
set iPos 0
} else {
incr iPos $iDelta
incr iPos -2
set C($docid,$iCol,$iPos) $zTerm
}
}
}
}
}
foreach key [array names C] {
}
db eval "SELECT * FROM ${tbl}_content" E {
set iCol 0
set iDoc $E(docid)
foreach col [lrange $E(*) 1 end] {
set c $E($col)
set sql {SELECT fts3_tokenizer_test('simple', $c)}
foreach {pos term dummy} [db one $sql] {
if {![info exists C($iDoc,$iCol,$pos)]} {
set es "Error at docid=$iDoc col=$iCol pos=$pos. Index is missing"
lappend errors $es
} else {
if {[string compare $C($iDoc,$iCol,$pos) $term]} {
set es "Error at docid=$iDoc col=$iCol pos=$pos. Index "
append es "has \"$C($iDoc,$iCol,$pos)\", document has \"$term\""
lappend errors $es
}
unset C($iDoc,$iCol,$pos)
}
}
incr iCol
}
}
foreach c [array names C] {
lappend errors "Bad index entry: $c -> $C($c)"
}
if {[info exists errors]} { return [join $errors "\n"] }
return "ok"
}
proc fts3_terms {tbl where} {
fts3_read $tbl $where a
return [lsort [array names a]]
}
proc fts3_doclist {tbl term where} {
fts3_read $tbl $where a
foreach doclist $a($term) {
set docid 0
while {[string length $doclist]>0} {
set iCol 0
set iPos 0
set lPos [list]
set lCol [list]
incr docid [gobble_varint doclist]
while {[set iDelta [gobble_varint doclist]] > 0} {
if {$iDelta == 1} {
lappend lCol [list $iCol $lPos]
set iPos 0
set lPos [list]
set iCol [gobble_varint doclist]
} else {
incr iPos $iDelta
incr iPos -2
lappend lPos $iPos
}
}
if {[llength $lPos]>0} {
lappend lCol [list $iCol $lPos]
}
if {$where != "1" || [llength $lCol]>0} {
set ret($docid) $lCol
} else {
unset -nocomplain ret($docid)
}
}
}
set lDoc [list]
foreach docid [lsort -integer [array names ret]] {
set lCol [list]
set cols ""
foreach col $ret($docid) {
foreach {iCol lPos} $col {}
append cols " $iCol\[[join $lPos { }]\]"
}
lappend lDoc "\[${docid}${cols}\]"
}
join $lDoc " "
}
proc gobble_varint {varname} {
upvar $varname blob
set n [read_fts3varint $blob ret]
set blob [string range $blob $n end]
return $ret
}
proc gobble_string {varname nLength} {
upvar $varname blob
set ret [string range $blob 0 [expr $nLength-1]]
set blob [string range $blob $nLength end]
return $ret
}
proc fts3_readleaf {blob} {
set zPrev ""
set terms [list]
while {[string length $blob] > 0} {
set nPrefix [gobble_varint blob]
set nSuffix [gobble_varint blob]
set zTerm [string range $zPrev 0 [expr $nPrefix-1]]
append zTerm [gobble_string blob $nSuffix]
set nDoclist [gobble_varint blob]
set doclist [gobble_string blob $nDoclist]
lappend terms $zTerm $doclist
set zPrev $zTerm
}
return $terms
}
proc fts3_read2 {tbl where varname} {
upvar $varname a
array unset a
db eval " SELECT start_block, leaves_end_block, root
FROM ${tbl}_segdir WHERE $where
ORDER BY level ASC, idx DESC
" {
set c 0
binary scan $root c c
if {$c==0} {
foreach {t d} [fts3_readleaf $root] { lappend a($t) $d }
} else {
db eval " SELECT block
FROM ${tbl}_segments
WHERE blockid>=$start_block AND blockid<=$leaves_end_block
ORDER BY blockid
" {
foreach {t d} [fts3_readleaf $block] { lappend a($t) $d }
}
}
}
}
proc fts3_read {tbl where varname} {
upvar $varname a
array unset a
db eval " SELECT start_block, leaves_end_block, root
FROM ${tbl}_segdir WHERE $where
ORDER BY level DESC, idx ASC
" {
if {$start_block == 0} {
foreach {t d} [fts3_readleaf $root] { lappend a($t) $d }
} else {
db eval " SELECT block
FROM ${tbl}_segments
WHERE blockid>=$start_block AND blockid<$leaves_end_block
ORDER BY blockid
" {
foreach {t d} [fts3_readleaf $block] { lappend a($t) $d }
}
}
}
}