/ Hex Artifact Content
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Artifact 51f7ef3af444b89c6f6ce3896a0ac349ff4e996d:


0000: 23 20 32 30 31 34 20 44 65 63 20 31 39 0a 23 0a  # 2014 Dec 19.#.
0010: 23 20 54 68 65 20 61 75 74 68 6f 72 20 64 69 73  # The author dis
0020: 63 6c 61 69 6d 73 20 63 6f 70 79 72 69 67 68 74  claims copyright
0030: 20 74 6f 20 74 68 69 73 20 73 6f 75 72 63 65 20   to this source 
0040: 63 6f 64 65 2e 20 20 49 6e 20 70 6c 61 63 65 20  code.  In place 
0050: 6f 66 0a 23 20 61 20 6c 65 67 61 6c 20 6e 6f 74  of.# a legal not
0060: 69 63 65 2c 20 68 65 72 65 20 69 73 20 61 20 62  ice, here is a b
0070: 6c 65 73 73 69 6e 67 3a 0a 23 0a 23 20 20 20 20  lessing:.#.#    
0080: 4d 61 79 20 79 6f 75 20 64 6f 20 67 6f 6f 64 20  May you do good 
0090: 61 6e 64 20 6e 6f 74 20 65 76 69 6c 2e 0a 23 20  and not evil..# 
00a0: 20 20 20 4d 61 79 20 79 6f 75 20 66 69 6e 64 20     May you find 
00b0: 66 6f 72 67 69 76 65 6e 65 73 73 20 66 6f 72 20  forgiveness for 
00c0: 79 6f 75 72 73 65 6c 66 20 61 6e 64 20 66 6f 72  yourself and for
00d0: 67 69 76 65 20 6f 74 68 65 72 73 2e 0a 23 20 20  give others..#  
00e0: 20 20 4d 61 79 20 79 6f 75 20 73 68 61 72 65 20    May you share 
00f0: 66 72 65 65 6c 79 2c 20 6e 65 76 65 72 20 74 61  freely, never ta
0100: 6b 69 6e 67 20 6d 6f 72 65 20 74 68 61 6e 20 79  king more than y
0110: 6f 75 20 67 69 76 65 2e 0a 23 0a 23 2a 2a 2a 2a  ou give..#.#****
0120: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0130: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0140: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0150: 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a  ****************
0160: 2a 2a 2a 0a 23 0a 0a 69 66 20 7b 21 5b 69 6e 66  ***.#..if {![inf
0170: 6f 20 65 78 69 73 74 73 20 74 65 73 74 64 69 72  o exists testdir
0180: 5d 7d 20 7b 0a 20 20 73 65 74 20 74 65 73 74 64  ]} {.  set testd
0190: 69 72 20 5b 66 69 6c 65 20 6a 6f 69 6e 20 5b 66  ir [file join [f
01a0: 69 6c 65 20 64 69 72 6e 61 6d 65 20 5b 69 6e 66  ile dirname [inf
01b0: 6f 20 73 63 72 69 70 74 5d 5d 20 2e 2e 20 2e 2e  o script]] .. ..
01c0: 20 2e 2e 20 74 65 73 74 5d 0a 7d 0a 73 6f 75 72   .. test].}.sour
01d0: 63 65 20 24 74 65 73 74 64 69 72 2f 74 65 73 74  ce $testdir/test
01e0: 65 72 2e 74 63 6c 0a 0a 63 61 74 63 68 20 7b 20  er.tcl..catch { 
01f0: 0a 20 20 73 71 6c 69 74 65 33 5f 66 74 73 35 5f  .  sqlite3_fts5_
0200: 6d 61 79 5f 62 65 5f 63 6f 72 72 75 70 74 20 30  may_be_corrupt 0
0210: 20 0a 20 20 72 65 73 65 74 5f 64 62 0a 7d 0a 0a   .  reset_db.}..
0220: 70 72 6f 63 20 66 74 73 35 5f 74 65 73 74 5f 70  proc fts5_test_p
0230: 6f 73 6c 69 73 74 20 7b 63 6d 64 7d 20 7b 0a 20  oslist {cmd} {. 
0240: 20 73 65 74 20 72 65 73 20 5b 6c 69 73 74 5d 0a   set res [list].
0250: 20 20 66 6f 72 20 7b 73 65 74 20 69 20 30 7d 20    for {set i 0} 
0260: 7b 24 69 20 3c 20 5b 24 63 6d 64 20 78 49 6e 73  {$i < [$cmd xIns
0270: 74 43 6f 75 6e 74 5d 7d 20 7b 69 6e 63 72 20 69  tCount]} {incr i
0280: 7d 20 7b 0a 20 20 20 20 6c 61 70 70 65 6e 64 20  } {.    lappend 
0290: 72 65 73 20 5b 73 74 72 69 6e 67 20 6d 61 70 20  res [string map 
02a0: 7b 7b 20 7d 20 2e 7d 20 5b 24 63 6d 64 20 78 49  {{ } .} [$cmd xI
02b0: 6e 73 74 20 24 69 5d 5d 0a 20 20 7d 0a 20 20 73  nst $i]].  }.  s
02c0: 65 74 20 72 65 73 0a 7d 0a 0a 70 72 6f 63 20 66  et res.}..proc f
02d0: 74 73 35 5f 74 65 73 74 5f 63 6f 6c 75 6d 6e 73  ts5_test_columns
02e0: 69 7a 65 20 7b 63 6d 64 7d 20 7b 0a 20 20 73 65  ize {cmd} {.  se
02f0: 74 20 72 65 73 20 5b 6c 69 73 74 5d 0a 20 20 66  t res [list].  f
0300: 6f 72 20 7b 73 65 74 20 69 20 30 7d 20 7b 24 69  or {set i 0} {$i
0310: 20 3c 20 5b 24 63 6d 64 20 78 43 6f 6c 75 6d 6e   < [$cmd xColumn
0320: 43 6f 75 6e 74 5d 7d 20 7b 69 6e 63 72 20 69 7d  Count]} {incr i}
0330: 20 7b 0a 20 20 20 20 6c 61 70 70 65 6e 64 20 72   {.    lappend r
0340: 65 73 20 5b 24 63 6d 64 20 78 43 6f 6c 75 6d 6e  es [$cmd xColumn
0350: 53 69 7a 65 20 24 69 5d 0a 20 20 7d 0a 20 20 73  Size $i].  }.  s
0360: 65 74 20 72 65 73 0a 7d 0a 0a 70 72 6f 63 20 66  et res.}..proc f
0370: 74 73 35 5f 74 65 73 74 5f 63 6f 6c 75 6d 6e 74  ts5_test_columnt
0380: 65 78 74 20 7b 63 6d 64 7d 20 7b 0a 20 20 73 65  ext {cmd} {.  se
0390: 74 20 72 65 73 20 5b 6c 69 73 74 5d 0a 20 20 66  t res [list].  f
03a0: 6f 72 20 7b 73 65 74 20 69 20 30 7d 20 7b 24 69  or {set i 0} {$i
03b0: 20 3c 20 5b 24 63 6d 64 20 78 43 6f 6c 75 6d 6e   < [$cmd xColumn
03c0: 43 6f 75 6e 74 5d 7d 20 7b 69 6e 63 72 20 69 7d  Count]} {incr i}
03d0: 20 7b 0a 20 20 20 20 6c 61 70 70 65 6e 64 20 72   {.    lappend r
03e0: 65 73 20 5b 24 63 6d 64 20 78 43 6f 6c 75 6d 6e  es [$cmd xColumn
03f0: 54 65 78 74 20 24 69 5d 0a 20 20 7d 0a 20 20 73  Text $i].  }.  s
0400: 65 74 20 72 65 73 0a 7d 0a 0a 70 72 6f 63 20 66  et res.}..proc f
0410: 74 73 35 5f 74 65 73 74 5f 63 6f 6c 75 6d 6e 74  ts5_test_columnt
0420: 6f 74 61 6c 73 69 7a 65 20 7b 63 6d 64 7d 20 7b  otalsize {cmd} {
0430: 0a 20 20 73 65 74 20 72 65 73 20 5b 6c 69 73 74  .  set res [list
0440: 5d 0a 20 20 66 6f 72 20 7b 73 65 74 20 69 20 30  ].  for {set i 0
0450: 7d 20 7b 24 69 20 3c 20 5b 24 63 6d 64 20 78 43  } {$i < [$cmd xC
0460: 6f 6c 75 6d 6e 43 6f 75 6e 74 5d 7d 20 7b 69 6e  olumnCount]} {in
0470: 63 72 20 69 7d 20 7b 0a 20 20 20 20 6c 61 70 70  cr i} {.    lapp
0480: 65 6e 64 20 72 65 73 20 5b 24 63 6d 64 20 78 43  end res [$cmd xC
0490: 6f 6c 75 6d 6e 54 6f 74 61 6c 53 69 7a 65 20 24  olumnTotalSize $
04a0: 69 5d 0a 20 20 7d 0a 20 20 73 65 74 20 72 65 73  i].  }.  set res
04b0: 0a 7d 0a 0a 70 72 6f 63 20 74 65 73 74 5f 61 70  .}..proc test_ap
04c0: 70 65 6e 64 5f 74 6f 6b 65 6e 20 7b 76 61 72 6e  pend_token {varn
04d0: 61 6d 65 20 74 6f 6b 65 6e 20 69 53 74 61 72 74  ame token iStart
04e0: 20 69 45 6e 64 7d 20 7b 0a 20 20 75 70 76 61 72   iEnd} {.  upvar
04f0: 20 24 76 61 72 6e 61 6d 65 20 76 61 72 0a 20 20   $varname var.  
0500: 6c 61 70 70 65 6e 64 20 76 61 72 20 24 74 6f 6b  lappend var $tok
0510: 65 6e 0a 20 20 72 65 74 75 72 6e 20 22 53 51 4c  en.  return "SQL
0520: 49 54 45 5f 4f 4b 22 0a 7d 0a 70 72 6f 63 20 66  ITE_OK".}.proc f
0530: 74 73 35 5f 74 65 73 74 5f 74 6f 6b 65 6e 69 7a  ts5_test_tokeniz
0540: 65 20 7b 63 6d 64 7d 20 7b 0a 20 20 73 65 74 20  e {cmd} {.  set 
0550: 72 65 73 20 5b 6c 69 73 74 5d 0a 20 20 66 6f 72  res [list].  for
0560: 20 7b 73 65 74 20 69 20 30 7d 20 7b 24 69 20 3c   {set i 0} {$i <
0570: 20 5b 24 63 6d 64 20 78 43 6f 6c 75 6d 6e 43 6f   [$cmd xColumnCo
0580: 75 6e 74 5d 7d 20 7b 69 6e 63 72 20 69 7d 20 7b  unt]} {incr i} {
0590: 0a 20 20 20 20 73 65 74 20 74 6f 6b 65 6e 73 20  .    set tokens 
05a0: 5b 6c 69 73 74 5d 0a 20 20 20 20 24 63 6d 64 20  [list].    $cmd 
05b0: 78 54 6f 6b 65 6e 69 7a 65 20 5b 24 63 6d 64 20  xTokenize [$cmd 
05c0: 78 43 6f 6c 75 6d 6e 54 65 78 74 20 24 69 5d 20  xColumnText $i] 
05d0: 5b 6c 69 73 74 20 74 65 73 74 5f 61 70 70 65 6e  [list test_appen
05e0: 64 5f 74 6f 6b 65 6e 20 74 6f 6b 65 6e 73 5d 0a  d_token tokens].
05f0: 20 20 20 20 6c 61 70 70 65 6e 64 20 72 65 73 20      lappend res 
0600: 24 74 6f 6b 65 6e 73 0a 20 20 7d 0a 20 20 73 65  $tokens.  }.  se
0610: 74 20 72 65 73 0a 7d 0a 0a 70 72 6f 63 20 66 74  t res.}..proc ft
0620: 73 35 5f 74 65 73 74 5f 72 6f 77 63 6f 75 6e 74  s5_test_rowcount
0630: 20 7b 63 6d 64 7d 20 7b 0a 20 20 24 63 6d 64 20   {cmd} {.  $cmd 
0640: 78 52 6f 77 43 6f 75 6e 74 0a 7d 0a 0a 70 72 6f  xRowCount.}..pro
0650: 63 20 74 65 73 74 5f 71 75 65 72 79 70 68 72 61  c test_queryphra
0660: 73 65 5f 63 62 20 7b 63 6e 74 20 63 6d 64 7d 20  se_cb {cnt cmd} 
0670: 7b 0a 20 20 75 70 76 61 72 20 24 63 6e 74 20 4c  {.  upvar $cnt L
0680: 20 0a 20 20 66 6f 72 20 7b 73 65 74 20 69 20 30   .  for {set i 0
0690: 7d 20 7b 24 69 20 3c 20 5b 24 63 6d 64 20 78 49  } {$i < [$cmd xI
06a0: 6e 73 74 43 6f 75 6e 74 5d 7d 20 7b 69 6e 63 72  nstCount]} {incr
06b0: 20 69 7d 20 7b 0a 20 20 20 20 66 6f 72 65 61 63   i} {.    foreac
06c0: 68 20 7b 69 70 20 69 63 20 69 6f 7d 20 5b 24 63  h {ip ic io} [$c
06d0: 6d 64 20 78 49 6e 73 74 20 24 69 5d 20 62 72 65  md xInst $i] bre
06e0: 61 6b 0a 20 20 20 20 73 65 74 20 41 28 24 69 63  ak.    set A($ic
06f0: 29 20 31 0a 20 20 7d 0a 20 20 66 6f 72 65 61 63  ) 1.  }.  foreac
0700: 68 20 69 63 20 5b 61 72 72 61 79 20 6e 61 6d 65  h ic [array name
0710: 73 20 41 5d 20 7b 0a 20 20 20 20 6c 73 65 74 20  s A] {.    lset 
0720: 4c 20 24 69 63 20 5b 65 78 70 72 20 7b 5b 6c 69  L $ic [expr {[li
0730: 6e 64 65 78 20 24 4c 20 24 69 63 5d 20 2b 20 31  ndex $L $ic] + 1
0740: 7d 5d 0a 20 20 7d 0a 7d 0a 70 72 6f 63 20 66 74  }].  }.}.proc ft
0750: 73 35 5f 74 65 73 74 5f 71 75 65 72 79 70 68 72  s5_test_queryphr
0760: 61 73 65 20 7b 63 6d 64 7d 20 7b 0a 20 20 73 65  ase {cmd} {.  se
0770: 74 20 72 65 73 20 5b 6c 69 73 74 5d 0a 20 20 66  t res [list].  f
0780: 6f 72 20 7b 73 65 74 20 69 20 30 7d 20 7b 24 69  or {set i 0} {$i
0790: 20 3c 20 5b 24 63 6d 64 20 78 50 68 72 61 73 65   < [$cmd xPhrase
07a0: 43 6f 75 6e 74 5d 7d 20 7b 69 6e 63 72 20 69 7d  Count]} {incr i}
07b0: 20 7b 0a 20 20 20 20 73 65 74 20 63 6e 74 20 5b   {.    set cnt [
07c0: 6c 69 73 74 5d 0a 20 20 20 20 66 6f 72 20 7b 73  list].    for {s
07d0: 65 74 20 6a 20 30 7d 20 7b 24 6a 20 3c 20 5b 24  et j 0} {$j < [$
07e0: 63 6d 64 20 78 43 6f 6c 75 6d 6e 43 6f 75 6e 74  cmd xColumnCount
07f0: 5d 7d 20 7b 69 6e 63 72 20 6a 7d 20 7b 20 6c 61  ]} {incr j} { la
0800: 70 70 65 6e 64 20 63 6e 74 20 30 20 7d 0a 20 20  ppend cnt 0 }.  
0810: 20 20 24 63 6d 64 20 78 51 75 65 72 79 50 68 72    $cmd xQueryPhr
0820: 61 73 65 20 24 69 20 5b 6c 69 73 74 20 74 65 73  ase $i [list tes
0830: 74 5f 71 75 65 72 79 70 68 72 61 73 65 5f 63 62  t_queryphrase_cb
0840: 20 63 6e 74 5d 0a 20 20 20 20 6c 61 70 70 65 6e   cnt].    lappen
0850: 64 20 72 65 73 20 24 63 6e 74 0a 20 20 7d 0a 20  d res $cnt.  }. 
0860: 20 73 65 74 20 72 65 73 0a 7d 0a 0a 70 72 6f 63   set res.}..proc
0870: 20 66 74 73 35 5f 74 65 73 74 5f 70 68 72 61 73   fts5_test_phras
0880: 65 63 6f 75 6e 74 20 7b 63 6d 64 7d 20 7b 0a 20  ecount {cmd} {. 
0890: 20 24 63 6d 64 20 78 50 68 72 61 73 65 43 6f 75   $cmd xPhraseCou
08a0: 6e 74 0a 7d 0a 0a 70 72 6f 63 20 66 74 73 35 5f  nt.}..proc fts5_
08b0: 74 65 73 74 5f 61 6c 6c 20 7b 63 6d 64 7d 20 7b  test_all {cmd} {
08c0: 0a 20 20 73 65 74 20 72 65 73 20 5b 6c 69 73 74  .  set res [list
08d0: 5d 0a 20 20 6c 61 70 70 65 6e 64 20 72 65 73 20  ].  lappend res 
08e0: 63 6f 6c 75 6d 6e 73 69 7a 65 20 20 20 20 20 20  columnsize      
08f0: 5b 66 74 73 35 5f 74 65 73 74 5f 63 6f 6c 75 6d  [fts5_test_colum
0900: 6e 73 69 7a 65 20 24 63 6d 64 5d 0a 20 20 6c 61  nsize $cmd].  la
0910: 70 70 65 6e 64 20 72 65 73 20 63 6f 6c 75 6d 6e  ppend res column
0920: 74 65 78 74 20 20 20 20 20 20 5b 66 74 73 35 5f  text      [fts5_
0930: 74 65 73 74 5f 63 6f 6c 75 6d 6e 74 65 78 74 20  test_columntext 
0940: 24 63 6d 64 5d 0a 20 20 6c 61 70 70 65 6e 64 20  $cmd].  lappend 
0950: 72 65 73 20 63 6f 6c 75 6d 6e 74 6f 74 61 6c 73  res columntotals
0960: 69 7a 65 20 5b 66 74 73 35 5f 74 65 73 74 5f 63  ize [fts5_test_c
0970: 6f 6c 75 6d 6e 74 6f 74 61 6c 73 69 7a 65 20 24  olumntotalsize $
0980: 63 6d 64 5d 0a 20 20 6c 61 70 70 65 6e 64 20 72  cmd].  lappend r
0990: 65 73 20 70 6f 73 6c 69 73 74 20 20 20 20 20 20  es poslist      
09a0: 20 20 20 5b 66 74 73 35 5f 74 65 73 74 5f 70 6f     [fts5_test_po
09b0: 73 6c 69 73 74 20 24 63 6d 64 5d 0a 20 20 6c 61  slist $cmd].  la
09c0: 70 70 65 6e 64 20 72 65 73 20 74 6f 6b 65 6e 69  ppend res tokeni
09d0: 7a 65 20 20 20 20 20 20 20 20 5b 66 74 73 35 5f  ze        [fts5_
09e0: 74 65 73 74 5f 74 6f 6b 65 6e 69 7a 65 20 24 63  test_tokenize $c
09f0: 6d 64 5d 0a 20 20 6c 61 70 70 65 6e 64 20 72 65  md].  lappend re
0a00: 73 20 72 6f 77 63 6f 75 6e 74 20 20 20 20 20 20  s rowcount      
0a10: 20 20 5b 66 74 73 35 5f 74 65 73 74 5f 72 6f 77    [fts5_test_row
0a20: 63 6f 75 6e 74 20 24 63 6d 64 5d 0a 20 20 73 65  count $cmd].  se
0a30: 74 20 72 65 73 0a 7d 0a 0a 70 72 6f 63 20 66 74  t res.}..proc ft
0a40: 73 35 5f 61 75 78 5f 74 65 73 74 5f 66 75 6e 63  s5_aux_test_func
0a50: 74 69 6f 6e 73 20 7b 64 62 7d 20 7b 0a 20 20 66  tions {db} {.  f
0a60: 6f 72 65 61 63 68 20 66 20 7b 0a 20 20 20 20 66  oreach f {.    f
0a70: 74 73 35 5f 74 65 73 74 5f 63 6f 6c 75 6d 6e 73  ts5_test_columns
0a80: 69 7a 65 0a 20 20 20 20 66 74 73 35 5f 74 65 73  ize.    fts5_tes
0a90: 74 5f 63 6f 6c 75 6d 6e 74 65 78 74 0a 20 20 20  t_columntext.   
0aa0: 20 66 74 73 35 5f 74 65 73 74 5f 63 6f 6c 75 6d   fts5_test_colum
0ab0: 6e 74 6f 74 61 6c 73 69 7a 65 0a 20 20 20 20 66  ntotalsize.    f
0ac0: 74 73 35 5f 74 65 73 74 5f 70 6f 73 6c 69 73 74  ts5_test_poslist
0ad0: 0a 20 20 20 20 66 74 73 35 5f 74 65 73 74 5f 74  .    fts5_test_t
0ae0: 6f 6b 65 6e 69 7a 65 0a 20 20 20 20 66 74 73 35  okenize.    fts5
0af0: 5f 74 65 73 74 5f 72 6f 77 63 6f 75 6e 74 0a 20  _test_rowcount. 
0b00: 20 20 20 66 74 73 35 5f 74 65 73 74 5f 61 6c 6c     fts5_test_all
0b10: 0a 0a 20 20 20 20 66 74 73 35 5f 74 65 73 74 5f  ..    fts5_test_
0b20: 71 75 65 72 79 70 68 72 61 73 65 0a 20 20 20 20  queryphrase.    
0b30: 66 74 73 35 5f 74 65 73 74 5f 70 68 72 61 73 65  fts5_test_phrase
0b40: 63 6f 75 6e 74 0a 20 20 7d 20 7b 0a 20 20 20 20  count.  } {.    
0b50: 73 71 6c 69 74 65 33 5f 66 74 73 35 5f 63 72 65  sqlite3_fts5_cre
0b60: 61 74 65 5f 66 75 6e 63 74 69 6f 6e 20 24 64 62  ate_function $db
0b70: 20 24 66 20 24 66 0a 20 20 7d 0a 7d 0a 0a 70 72   $f $f.  }.}..pr
0b80: 6f 63 20 66 74 73 35 5f 6c 65 76 65 6c 5f 73 65  oc fts5_level_se
0b90: 67 73 20 7b 74 62 6c 7d 20 7b 0a 20 20 73 65 74  gs {tbl} {.  set
0ba0: 20 73 71 6c 20 22 53 45 4c 45 43 54 20 66 74 73   sql "SELECT fts
0bb0: 35 5f 64 65 63 6f 64 65 28 72 6f 77 69 64 2c 62  5_decode(rowid,b
0bc0: 6c 6f 63 6b 29 20 61 53 20 72 20 46 52 4f 4d 20  lock) aS r FROM 
0bd0: 24 7b 74 62 6c 7d 5f 64 61 74 61 20 57 48 45 52  ${tbl}_data WHER
0be0: 45 20 72 6f 77 69 64 3d 31 30 22 0a 20 20 73 65  E rowid=10".  se
0bf0: 74 20 72 65 74 20 5b 6c 69 73 74 5d 0a 20 20 66  t ret [list].  f
0c00: 6f 72 65 61 63 68 20 4c 20 5b 6c 72 61 6e 67 65  oreach L [lrange
0c10: 20 5b 64 62 20 6f 6e 65 20 24 73 71 6c 5d 20 31   [db one $sql] 1
0c20: 20 65 6e 64 5d 20 7b 0a 20 20 20 20 6c 61 70 70   end] {.    lapp
0c30: 65 6e 64 20 72 65 74 20 5b 65 78 70 72 20 5b 6c  end ret [expr [l
0c40: 6c 65 6e 67 74 68 20 24 4c 5d 20 2d 20 33 5d 0a  length $L] - 3].
0c50: 20 20 7d 0a 20 20 73 65 74 20 72 65 74 0a 7d 20    }.  set ret.} 
0c60: 0a 0a 70 72 6f 63 20 66 74 73 35 5f 6c 65 76 65  ..proc fts5_leve
0c70: 6c 5f 73 65 67 69 64 73 20 7b 74 62 6c 7d 20 7b  l_segids {tbl} {
0c80: 0a 20 20 73 65 74 20 73 71 6c 20 22 53 45 4c 45  .  set sql "SELE
0c90: 43 54 20 66 74 73 35 5f 64 65 63 6f 64 65 28 72  CT fts5_decode(r
0ca0: 6f 77 69 64 2c 62 6c 6f 63 6b 29 20 61 53 20 72  owid,block) aS r
0cb0: 20 46 52 4f 4d 20 24 7b 74 62 6c 7d 5f 64 61 74   FROM ${tbl}_dat
0cc0: 61 20 57 48 45 52 45 20 72 6f 77 69 64 3d 31 30  a WHERE rowid=10
0cd0: 22 0a 20 20 73 65 74 20 72 65 74 20 5b 6c 69 73  ".  set ret [lis
0ce0: 74 5d 0a 20 20 66 6f 72 65 61 63 68 20 4c 20 5b  t].  foreach L [
0cf0: 6c 72 61 6e 67 65 20 5b 64 62 20 6f 6e 65 20 24  lrange [db one $
0d00: 73 71 6c 5d 20 31 20 65 6e 64 5d 20 7b 0a 20 20  sql] 1 end] {.  
0d10: 20 20 73 65 74 20 6c 76 6c 20 5b 6c 69 73 74 5d    set lvl [list]
0d20: 0a 20 20 20 20 66 6f 72 65 61 63 68 20 53 20 5b  .    foreach S [
0d30: 6c 72 61 6e 67 65 20 24 4c 20 33 20 65 6e 64 5d  lrange $L 3 end]
0d40: 20 7b 0a 20 20 20 20 20 20 72 65 67 65 78 70 20   {.      regexp 
0d50: 7b 69 64 3d 28 5b 31 32 33 34 35 36 37 38 39 30  {id=([1234567890
0d60: 5d 2a 29 7d 20 24 53 20 2d 3e 20 73 65 67 69 64  ]*)} $S -> segid
0d70: 0a 20 20 20 20 20 20 6c 61 70 70 65 6e 64 20 6c  .      lappend l
0d80: 76 6c 20 24 73 65 67 69 64 0a 20 20 20 20 7d 0a  vl $segid.    }.
0d90: 20 20 20 20 6c 61 70 70 65 6e 64 20 72 65 74 20      lappend ret 
0da0: 24 6c 76 6c 0a 20 20 7d 0a 20 20 73 65 74 20 72  $lvl.  }.  set r
0db0: 65 74 0a 7d 0a 0a 70 72 6f 63 20 66 74 73 35 5f  et.}..proc fts5_
0dc0: 72 6e 64 64 6f 63 20 7b 6e 7d 20 7b 0a 20 20 73  rnddoc {n} {.  s
0dd0: 65 74 20 6d 61 70 20 5b 6c 69 73 74 20 30 20 61  et map [list 0 a
0de0: 20 20 31 20 62 20 20 32 20 63 20 20 33 20 64 20    1 b  2 c  3 d 
0df0: 20 34 20 65 20 20 35 20 66 20 20 36 20 67 20 20   4 e  5 f  6 g  
0e00: 37 20 68 20 20 38 20 69 20 20 39 20 6a 5d 0a 20  7 h  8 i  9 j]. 
0e10: 20 73 65 74 20 64 6f 63 20 5b 6c 69 73 74 5d 0a   set doc [list].
0e20: 20 20 66 6f 72 20 7b 73 65 74 20 69 20 30 7d 20    for {set i 0} 
0e30: 7b 24 69 20 3c 20 24 6e 7d 20 7b 69 6e 63 72 20  {$i < $n} {incr 
0e40: 69 7d 20 7b 0a 20 20 20 20 6c 61 70 70 65 6e 64  i} {.    lappend
0e50: 20 64 6f 63 20 22 78 5b 73 74 72 69 6e 67 20 6d   doc "x[string m
0e60: 61 70 20 24 6d 61 70 20 5b 66 6f 72 6d 61 74 20  ap $map [format 
0e70: 25 2e 33 64 20 5b 65 78 70 72 20 69 6e 74 28 72  %.3d [expr int(r
0e80: 61 6e 64 28 29 2a 31 30 30 30 29 5d 5d 5d 22 0a  and()*1000)]]]".
0e90: 20 20 7d 0a 20 20 73 65 74 20 64 6f 63 0a 7d 0a    }.  set doc.}.
0ea0: 0a 23 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  .#--------------
0eb0: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
0ec0: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
0ed0: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
0ee0: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 0a 23 20 55 73  -----------.# Us
0ef0: 61 67 65 3a 0a 23 0a 23 20 20 20 6e 65 61 72 73  age:.#.#   nears
0f00: 65 74 20 61 43 6f 6c 20 3f 2d 70 63 20 56 41 52  et aCol ?-pc VAR
0f10: 4e 41 4d 45 3f 20 3f 2d 6e 65 61 72 20 4e 3f 20  NAME? ?-near N? 
0f20: 3f 2d 63 6f 6c 20 43 3f 20 2d 2d 20 70 68 72 61  ?-col C? -- phra
0f30: 73 65 31 20 70 68 72 61 73 65 32 2e 2e 2e 0a 23  se1 phrase2....#
0f40: 0a 23 20 54 68 69 73 20 63 6f 6d 6d 61 6e 64 20  .# This command 
0f50: 69 73 20 75 73 65 64 20 74 6f 20 74 65 73 74 20  is used to test 
0f60: 69 66 20 61 20 64 6f 63 75 6d 65 6e 74 20 28 73  if a document (s
0f70: 65 74 20 6f 66 20 63 6f 6c 75 6d 6e 20 76 61 6c  et of column val
0f80: 75 65 73 29 20 6d 61 74 63 68 65 73 0a 23 20 74  ues) matches.# t
0f90: 68 65 20 6c 6f 67 69 63 61 6c 20 65 71 75 69 76  he logical equiv
0fa0: 61 6c 65 6e 74 20 6f 66 20 61 20 73 69 6e 67 6c  alent of a singl
0fb0: 65 20 46 54 53 35 20 4e 45 41 52 28 29 20 63 6c  e FTS5 NEAR() cl
0fc0: 75 6d 70 20 61 6e 64 2c 20 69 66 20 73 6f 2c 20  ump and, if so, 
0fd0: 72 65 74 75 72 6e 0a 23 20 74 68 65 20 65 71 75  return.# the equ
0fe0: 69 76 61 6c 65 6e 74 20 6f 66 20 61 6e 20 46 54  ivalent of an FT
0ff0: 53 35 20 70 6f 73 69 74 69 6f 6e 20 6c 69 73 74  S5 position list
1000: 2e 0a 23 0a 23 20 50 61 72 61 6d 65 74 65 72 20  ..#.# Parameter 
1010: 24 61 43 6f 6c 20 69 73 20 70 61 73 73 65 64 20  $aCol is passed 
1020: 61 20 6c 69 73 74 20 6f 66 20 74 68 65 20 63 6f  a list of the co
1030: 6c 75 6d 6e 20 76 61 6c 75 65 73 20 66 6f 72 20  lumn values for 
1040: 74 68 65 20 64 6f 63 75 6d 65 6e 74 0a 23 20 74  the document.# t
1050: 6f 20 74 65 73 74 2e 20 50 61 72 61 6d 65 74 65  o test. Paramete
1060: 72 73 20 24 70 68 72 61 73 65 31 20 61 6e 64 20  rs $phrase1 and 
1070: 73 6f 20 6f 6e 20 61 72 65 20 74 68 65 20 70 68  so on are the ph
1080: 72 61 73 65 73 2e 0a 23 0a 23 20 54 68 65 20 72  rases..#.# The r
1090: 65 73 75 6c 74 20 69 73 20 61 20 6c 69 73 74 20  esult is a list 
10a0: 6f 66 20 70 68 72 61 73 65 20 68 69 74 73 2e 20  of phrase hits. 
10b0: 45 61 63 68 20 70 68 72 61 73 65 20 68 69 74 20  Each phrase hit 
10c0: 69 73 20 66 6f 72 6d 61 74 74 65 64 20 61 73 0a  is formatted as.
10d0: 23 20 74 68 72 65 65 20 69 6e 74 65 67 65 72 73  # three integers
10e0: 20 73 65 70 61 72 61 74 65 64 20 62 79 20 22 2e   separated by ".
10f0: 22 20 63 68 61 72 61 63 74 65 72 73 2c 20 69 6e  " characters, in
1100: 20 74 68 65 20 66 6f 6c 6c 6f 77 69 6e 67 20 66   the following f
1110: 6f 72 6d 61 74 3a 0a 23 0a 23 20 20 20 3c 70 68  ormat:.#.#   <ph
1120: 72 61 73 65 20 6e 75 6d 62 65 72 3e 20 2e 20 3c  rase number> . <
1130: 63 6f 6c 75 6d 6e 20 6e 75 6d 62 65 72 3e 20 2e  column number> .
1140: 20 3c 74 6f 6b 65 6e 20 6f 66 66 73 65 74 3e 0a   <token offset>.
1150: 23 0a 23 20 4f 70 74 69 6f 6e 73 3a 0a 23 0a 23  #.# Options:.#.#
1160: 20 20 20 2d 6e 65 61 72 20 4e 20 20 20 20 20 20     -near N      
1170: 20 20 28 4e 45 41 52 20 64 69 73 74 61 6e 63 65    (NEAR distance
1180: 2e 20 44 65 66 61 75 6c 74 20 31 30 29 0a 23 20  . Default 10).# 
1190: 20 20 2d 63 6f 6c 20 20 43 20 20 20 20 20 20 20    -col  C       
11a0: 20 28 4c 69 73 74 20 6f 66 20 63 6f 6c 75 6d 6e   (List of column
11b0: 20 69 6e 64 65 78 65 73 20 74 6f 20 6d 61 74 63   indexes to matc
11c0: 68 20 61 67 61 69 6e 73 74 29 0a 23 20 20 20 2d  h against).#   -
11d0: 70 63 20 20 20 56 41 52 4e 41 4d 45 20 20 28 76  pc   VARNAME  (v
11e0: 61 72 69 61 62 6c 65 20 69 6e 20 63 61 6c 6c 65  ariable in calle
11f0: 72 20 66 72 61 6d 65 20 74 6f 20 75 73 65 20 66  r frame to use f
1200: 6f 72 20 70 68 72 61 73 65 20 6e 75 6d 62 65 72  or phrase number
1210: 69 6e 67 29 0a 23 0a 70 72 6f 63 20 6e 65 61 72  ing).#.proc near
1220: 73 65 74 20 7b 61 43 6f 6c 20 61 72 67 73 7d 20  set {aCol args} 
1230: 7b 0a 20 20 73 65 74 20 4f 28 2d 6e 65 61 72 29  {.  set O(-near)
1240: 20 31 30 0a 20 20 73 65 74 20 4f 28 2d 63 6f 6c   10.  set O(-col
1250: 29 20 20 7b 7d 0a 20 20 73 65 74 20 4f 28 2d 70  )  {}.  set O(-p
1260: 63 29 20 20 20 22 22 0a 0a 20 20 73 65 74 20 6e  c)   ""..  set n
1270: 4f 70 74 20 5b 6c 73 65 61 72 63 68 20 2d 65 78  Opt [lsearch -ex
1280: 61 63 74 20 24 61 72 67 73 20 2d 2d 5d 0a 20 20  act $args --].  
1290: 69 66 20 7b 24 6e 4f 70 74 3c 30 7d 20 7b 20 65  if {$nOpt<0} { e
12a0: 72 72 6f 72 20 22 6e 6f 20 2d 2d 20 6f 70 74 69  rror "no -- opti
12b0: 6f 6e 22 20 7d 0a 0a 20 20 66 6f 72 65 61 63 68  on" }..  foreach
12c0: 20 7b 6b 20 76 7d 20 5b 6c 72 61 6e 67 65 20 24   {k v} [lrange $
12d0: 61 72 67 73 20 30 20 5b 65 78 70 72 20 24 6e 4f  args 0 [expr $nO
12e0: 70 74 2d 31 5d 5d 20 7b 0a 20 20 20 20 69 66 20  pt-1]] {.    if 
12f0: 7b 5b 69 6e 66 6f 20 65 78 69 73 74 73 20 4f 28  {[info exists O(
1300: 24 6b 29 5d 3d 3d 30 7d 20 7b 20 65 72 72 6f 72  $k)]==0} { error
1310: 20 22 75 6e 72 65 63 6f 67 6e 69 7a 65 64 20 6f   "unrecognized o
1320: 70 74 69 6f 6e 20 24 6b 22 20 7d 0a 20 20 20 20  ption $k" }.    
1330: 73 65 74 20 4f 28 24 6b 29 20 24 76 0a 20 20 7d  set O($k) $v.  }
1340: 0a 0a 20 20 69 66 20 7b 24 4f 28 2d 70 63 29 20  ..  if {$O(-pc) 
1350: 3d 3d 20 22 22 7d 20 7b 0a 20 20 20 20 73 65 74  == ""} {.    set
1360: 20 63 6f 75 6e 74 65 72 20 30 0a 20 20 7d 20 65   counter 0.  } e
1370: 6c 73 65 20 7b 0a 20 20 20 20 75 70 76 61 72 20  lse {.    upvar 
1380: 24 4f 28 2d 70 63 29 20 63 6f 75 6e 74 65 72 0a  $O(-pc) counter.
1390: 20 20 7d 0a 0a 20 20 23 20 53 65 74 20 24 70 68    }..  # Set $ph
13a0: 72 61 73 65 6c 69 73 74 20 74 6f 20 62 65 20 61  raselist to be a
13b0: 20 6c 69 73 74 20 6f 66 20 70 68 72 61 73 65 73   list of phrases
13c0: 2e 20 24 6e 50 68 72 61 73 65 20 69 74 73 20 6c  . $nPhrase its l
13d0: 65 6e 67 74 68 2e 0a 20 20 73 65 74 20 70 68 72  ength..  set phr
13e0: 61 73 65 6c 69 73 74 20 5b 6c 72 61 6e 67 65 20  aselist [lrange 
13f0: 24 61 72 67 73 20 5b 65 78 70 72 20 24 6e 4f 70  $args [expr $nOp
1400: 74 2b 31 5d 20 65 6e 64 5d 0a 20 20 73 65 74 20  t+1] end].  set 
1410: 6e 50 68 72 61 73 65 20 5b 6c 6c 65 6e 67 74 68  nPhrase [llength
1420: 20 24 70 68 72 61 73 65 6c 69 73 74 5d 0a 0a 20   $phraselist].. 
1430: 20 66 6f 72 20 7b 73 65 74 20 6a 20 30 7d 20 7b   for {set j 0} {
1440: 24 6a 20 3c 20 5b 6c 6c 65 6e 67 74 68 20 24 61  $j < [llength $a
1450: 43 6f 6c 5d 7d 20 7b 69 6e 63 72 20 6a 7d 20 7b  Col]} {incr j} {
1460: 0a 20 20 20 20 66 6f 72 20 7b 73 65 74 20 69 20  .    for {set i 
1470: 30 7d 20 7b 24 69 20 3c 20 24 6e 50 68 72 61 73  0} {$i < $nPhras
1480: 65 7d 20 7b 69 6e 63 72 20 69 7d 20 7b 20 0a 20  e} {incr i} { . 
1490: 20 20 20 20 20 73 65 74 20 41 28 24 6a 2c 24 69       set A($j,$i
14a0: 29 20 5b 6c 69 73 74 5d 0a 20 20 20 20 7d 0a 20  ) [list].    }. 
14b0: 20 7d 0a 0a 20 20 73 65 74 20 69 43 6f 6c 20 2d   }..  set iCol -
14c0: 31 0a 20 20 66 6f 72 65 61 63 68 20 63 6f 6c 20  1.  foreach col 
14d0: 24 61 43 6f 6c 20 7b 0a 20 20 20 20 69 6e 63 72  $aCol {.    incr
14e0: 20 69 43 6f 6c 0a 20 20 20 20 69 66 20 7b 24 4f   iCol.    if {$O
14f0: 28 2d 63 6f 6c 29 21 3d 22 22 20 26 26 20 5b 6c  (-col)!="" && [l
1500: 73 65 61 72 63 68 20 24 4f 28 2d 63 6f 6c 29 20  search $O(-col) 
1510: 24 69 43 6f 6c 5d 3c 30 7d 20 63 6f 6e 74 69 6e  $iCol]<0} contin
1520: 75 65 0a 20 20 20 20 73 65 74 20 6e 54 6f 6b 65  ue.    set nToke
1530: 6e 20 5b 6c 6c 65 6e 67 74 68 20 24 63 6f 6c 5d  n [llength $col]
1540: 0a 0a 20 20 20 20 73 65 74 20 69 46 4c 20 5b 65  ..    set iFL [e
1550: 78 70 72 20 24 4f 28 2d 6e 65 61 72 29 20 3e 3d  xpr $O(-near) >=
1560: 20 24 6e 54 6f 6b 65 6e 20 3f 20 24 6e 54 6f 6b   $nToken ? $nTok
1570: 65 6e 20 2d 20 31 20 3a 20 24 4f 28 2d 6e 65 61  en - 1 : $O(-nea
1580: 72 29 5d 0a 20 20 20 20 66 6f 72 20 7b 20 7d 20  r)].    for { } 
1590: 7b 24 69 46 4c 20 3c 20 24 6e 54 6f 6b 65 6e 7d  {$iFL < $nToken}
15a0: 20 7b 69 6e 63 72 20 69 46 4c 7d 20 7b 0a 20 20   {incr iFL} {.  
15b0: 20 20 20 20 66 6f 72 20 7b 73 65 74 20 69 50 68      for {set iPh
15c0: 72 61 73 65 20 30 7d 20 7b 24 69 50 68 72 61 73  rase 0} {$iPhras
15d0: 65 3c 24 6e 50 68 72 61 73 65 7d 20 7b 69 6e 63  e<$nPhrase} {inc
15e0: 72 20 69 50 68 72 61 73 65 7d 20 7b 0a 20 20 20  r iPhrase} {.   
15f0: 20 20 20 20 20 73 65 74 20 42 28 24 69 50 68 72       set B($iPhr
1600: 61 73 65 29 20 5b 6c 69 73 74 5d 0a 20 20 20 20  ase) [list].    
1610: 20 20 7d 0a 20 20 20 20 20 20 0a 20 20 20 20 20    }.      .     
1620: 20 66 6f 72 20 7b 73 65 74 20 69 50 68 72 61 73   for {set iPhras
1630: 65 20 30 7d 20 7b 24 69 50 68 72 61 73 65 3c 24  e 0} {$iPhrase<$
1640: 6e 50 68 72 61 73 65 7d 20 7b 69 6e 63 72 20 69  nPhrase} {incr i
1650: 50 68 72 61 73 65 7d 20 7b 0a 20 20 20 20 20 20  Phrase} {.      
1660: 20 20 73 65 74 20 70 20 5b 6c 69 6e 64 65 78 20    set p [lindex 
1670: 24 70 68 72 61 73 65 6c 69 73 74 20 24 69 50 68  $phraselist $iPh
1680: 72 61 73 65 5d 0a 20 20 20 20 20 20 20 20 73 65  rase].        se
1690: 74 20 6e 50 6d 31 20 5b 65 78 70 72 20 7b 5b 6c  t nPm1 [expr {[l
16a0: 6c 65 6e 67 74 68 20 24 70 5d 20 2d 20 31 7d 5d  length $p] - 1}]
16b0: 0a 20 20 20 20 20 20 20 20 73 65 74 20 69 46 69  .        set iFi
16c0: 72 73 74 20 5b 65 78 70 72 20 24 69 46 4c 20 2d  rst [expr $iFL -
16d0: 20 24 4f 28 2d 6e 65 61 72 29 20 2d 20 5b 6c 6c   $O(-near) - [ll
16e0: 65 6e 67 74 68 20 24 70 5d 5d 0a 0a 20 20 20 20  ength $p]]..    
16f0: 20 20 20 20 66 6f 72 20 7b 73 65 74 20 69 20 24      for {set i $
1700: 69 46 69 72 73 74 7d 20 7b 24 69 20 3c 3d 20 24  iFirst} {$i <= $
1710: 69 46 4c 7d 20 7b 69 6e 63 72 20 69 7d 20 7b 0a  iFL} {incr i} {.
1720: 20 20 20 20 20 20 20 20 20 20 69 66 20 7b 5b 6c            if {[l
1730: 72 61 6e 67 65 20 24 63 6f 6c 20 24 69 20 5b 65  range $col $i [e
1740: 78 70 72 20 24 69 2b 24 6e 50 6d 31 5d 5d 20 3d  xpr $i+$nPm1]] =
1750: 3d 20 24 70 7d 20 7b 20 6c 61 70 70 65 6e 64 20  = $p} { lappend 
1760: 42 28 24 69 50 68 72 61 73 65 29 20 24 69 20 7d  B($iPhrase) $i }
1770: 0a 20 20 20 20 20 20 20 20 7d 0a 20 20 20 20 20  .        }.     
1780: 20 20 20 69 66 20 7b 5b 6c 6c 65 6e 67 74 68 20     if {[llength 
1790: 24 42 28 24 69 50 68 72 61 73 65 29 5d 20 3d 3d  $B($iPhrase)] ==
17a0: 20 30 7d 20 62 72 65 61 6b 0a 20 20 20 20 20 20   0} break.      
17b0: 7d 0a 0a 20 20 20 20 20 20 69 66 20 7b 24 69 50  }..      if {$iP
17c0: 68 72 61 73 65 3d 3d 24 6e 50 68 72 61 73 65 7d  hrase==$nPhrase}
17d0: 20 7b 0a 20 20 20 20 20 20 20 20 66 6f 72 20 7b   {.        for {
17e0: 73 65 74 20 69 50 68 72 61 73 65 20 30 7d 20 7b  set iPhrase 0} {
17f0: 24 69 50 68 72 61 73 65 3c 24 6e 50 68 72 61 73  $iPhrase<$nPhras
1800: 65 7d 20 7b 69 6e 63 72 20 69 50 68 72 61 73 65  e} {incr iPhrase
1810: 7d 20 7b 0a 20 20 20 20 20 20 20 20 20 20 73 65  } {.          se
1820: 74 20 41 28 24 69 43 6f 6c 2c 24 69 50 68 72 61  t A($iCol,$iPhra
1830: 73 65 29 20 5b 63 6f 6e 63 61 74 20 24 41 28 24  se) [concat $A($
1840: 69 43 6f 6c 2c 24 69 50 68 72 61 73 65 29 20 24  iCol,$iPhrase) $
1850: 42 28 24 69 50 68 72 61 73 65 29 5d 0a 20 20 20  B($iPhrase)].   
1860: 20 20 20 20 20 20 20 73 65 74 20 41 28 24 69 43         set A($iC
1870: 6f 6c 2c 24 69 50 68 72 61 73 65 29 20 5b 6c 73  ol,$iPhrase) [ls
1880: 6f 72 74 20 2d 69 6e 74 65 67 65 72 20 2d 75 6e  ort -integer -un
1890: 69 71 20 24 41 28 24 69 43 6f 6c 2c 24 69 50 68  iq $A($iCol,$iPh
18a0: 72 61 73 65 29 5d 0a 20 20 20 20 20 20 20 20 7d  rase)].        }
18b0: 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d 0a 20  .      }.    }. 
18c0: 20 7d 0a 0a 20 20 73 65 74 20 72 65 73 20 5b 6c   }..  set res [l
18d0: 69 73 74 5d 0a 20 20 23 70 75 74 73 20 5b 61 72  ist].  #puts [ar
18e0: 72 61 79 20 6e 61 6d 65 73 20 41 5d 0a 0a 20 20  ray names A]..  
18f0: 66 6f 72 20 7b 73 65 74 20 69 50 68 72 61 73 65  for {set iPhrase
1900: 20 30 7d 20 7b 24 69 50 68 72 61 73 65 3c 24 6e   0} {$iPhrase<$n
1910: 50 68 72 61 73 65 7d 20 7b 69 6e 63 72 20 69 50  Phrase} {incr iP
1920: 68 72 61 73 65 7d 20 7b 0a 20 20 20 20 66 6f 72  hrase} {.    for
1930: 20 7b 73 65 74 20 69 43 6f 6c 20 30 7d 20 7b 24   {set iCol 0} {$
1940: 69 43 6f 6c 20 3c 20 5b 6c 6c 65 6e 67 74 68 20  iCol < [llength 
1950: 24 61 43 6f 6c 5d 7d 20 7b 69 6e 63 72 20 69 43  $aCol]} {incr iC
1960: 6f 6c 7d 20 7b 0a 20 20 20 20 20 20 66 6f 72 65  ol} {.      fore
1970: 61 63 68 20 61 20 24 41 28 24 69 43 6f 6c 2c 24  ach a $A($iCol,$
1980: 69 50 68 72 61 73 65 29 20 7b 0a 20 20 20 20 20  iPhrase) {.     
1990: 20 20 20 6c 61 70 70 65 6e 64 20 72 65 73 20 22     lappend res "
19a0: 24 63 6f 75 6e 74 65 72 2e 24 69 43 6f 6c 2e 24  $counter.$iCol.$
19b0: 61 22 0a 20 20 20 20 20 20 7d 0a 20 20 20 20 7d  a".      }.    }
19c0: 0a 20 20 20 20 69 6e 63 72 20 63 6f 75 6e 74 65  .    incr counte
19d0: 72 0a 20 20 7d 0a 0a 20 20 23 70 75 74 73 20 24  r.  }..  #puts $
19e0: 72 65 73 0a 20 20 73 6f 72 74 5f 70 6f 73 6c 69  res.  sort_posli
19f0: 73 74 20 24 72 65 73 0a 7d 0a 0a 23 2d 2d 2d 2d  st $res.}..#----
1a00: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
1a10: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
1a20: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
1a30: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
1a40: 2d 2d 2d 2d 2d 0a 23 20 55 73 61 67 65 3a 0a 23  -----.# Usage:.#
1a50: 0a 23 20 20 20 73 6f 72 74 5f 70 6f 73 6c 69 73  .#   sort_poslis
1a60: 74 20 4c 49 53 54 0a 23 0a 23 20 53 6f 72 74 20  t LIST.#.# Sort 
1a70: 61 20 70 6f 73 69 74 69 6f 6e 20 6c 69 73 74 20  a position list 
1a80: 6f 66 20 74 68 65 20 74 79 70 65 20 72 65 74 75  of the type retu
1a90: 72 6e 65 64 20 62 79 20 63 6f 6d 6d 61 6e 64 20  rned by command 
1aa0: 5b 6e 65 61 72 73 65 74 5d 0a 23 0a 70 72 6f 63  [nearset].#.proc
1ab0: 20 73 6f 72 74 5f 70 6f 73 6c 69 73 74 20 7b 4c   sort_poslist {L
1ac0: 7d 20 7b 0a 20 20 6c 73 6f 72 74 20 2d 63 6f 6d  } {.  lsort -com
1ad0: 6d 61 6e 64 20 69 6e 73 74 63 6f 6d 70 61 72 65  mand instcompare
1ae0: 20 24 4c 0a 7d 0a 70 72 6f 63 20 69 6e 73 74 63   $L.}.proc instc
1af0: 6f 6d 70 61 72 65 20 7b 6c 68 73 20 72 68 73 7d  ompare {lhs rhs}
1b00: 20 7b 0a 20 20 66 6f 72 65 61 63 68 20 7b 70 31   {.  foreach {p1
1b10: 20 63 31 20 6f 31 7d 20 5b 73 70 6c 69 74 20 24   c1 o1} [split $
1b20: 6c 68 73 20 2e 5d 20 7b 7d 0a 20 20 66 6f 72 65  lhs .] {}.  fore
1b30: 61 63 68 20 7b 70 32 20 63 32 20 6f 32 7d 20 5b  ach {p2 c2 o2} [
1b40: 73 70 6c 69 74 20 24 72 68 73 20 2e 5d 20 7b 7d  split $rhs .] {}
1b50: 0a 0a 20 20 73 65 74 20 72 65 73 20 5b 65 78 70  ..  set res [exp
1b60: 72 20 24 63 31 20 2d 20 24 63 32 5d 0a 20 20 69  r $c1 - $c2].  i
1b70: 66 20 7b 24 72 65 73 3d 3d 30 7d 20 7b 20 73 65  f {$res==0} { se
1b80: 74 20 72 65 73 20 5b 65 78 70 72 20 24 6f 31 20  t res [expr $o1 
1b90: 2d 20 24 6f 32 5d 20 7d 0a 20 20 69 66 20 7b 24  - $o2] }.  if {$
1ba0: 72 65 73 3d 3d 30 7d 20 7b 20 73 65 74 20 72 65  res==0} { set re
1bb0: 73 20 5b 65 78 70 72 20 24 70 31 20 2d 20 24 70  s [expr $p1 - $p
1bc0: 32 5d 20 7d 0a 0a 20 20 72 65 74 75 72 6e 20 24  2] }..  return $
1bd0: 72 65 73 0a 7d 0a 0a 23 2d 2d 2d 2d 2d 2d 2d 2d  res.}..#--------
1be0: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
1bf0: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
1c00: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
1c10: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
1c20: 2d 0a 23 20 4c 6f 67 69 63 61 6c 20 6f 70 65 72  -.# Logical oper
1c30: 61 74 6f 72 73 20 75 73 65 64 20 62 79 20 74 68  ators used by th
1c40: 65 20 63 6f 6d 6d 61 6e 64 73 20 72 65 74 75 72  e commands retur
1c50: 6e 65 64 20 62 79 20 66 74 73 35 5f 74 63 6c 5f  ned by fts5_tcl_
1c60: 65 78 70 72 28 29 2e 0a 23 0a 70 72 6f 63 20 41  expr()..#.proc A
1c70: 4e 44 20 7b 61 72 67 73 7d 20 7b 0a 20 20 66 6f  ND {args} {.  fo
1c80: 72 65 61 63 68 20 61 20 24 61 72 67 73 20 7b 0a  reach a $args {.
1c90: 20 20 20 20 69 66 20 7b 5b 6c 6c 65 6e 67 74 68      if {[llength
1ca0: 20 24 61 5d 3d 3d 30 7d 20 7b 20 72 65 74 75 72   $a]==0} { retur
1cb0: 6e 20 5b 6c 69 73 74 5d 20 7d 0a 20 20 7d 0a 20  n [list] }.  }. 
1cc0: 20 73 6f 72 74 5f 70 6f 73 6c 69 73 74 20 5b 63   sort_poslist [c
1cd0: 6f 6e 63 61 74 20 7b 2a 7d 24 61 72 67 73 5d 0a  oncat {*}$args].
1ce0: 7d 0a 70 72 6f 63 20 4f 52 20 7b 61 72 67 73 7d  }.proc OR {args}
1cf0: 20 7b 0a 20 20 73 6f 72 74 5f 70 6f 73 6c 69 73   {.  sort_poslis
1d00: 74 20 5b 63 6f 6e 63 61 74 20 7b 2a 7d 24 61 72  t [concat {*}$ar
1d10: 67 73 5d 0a 7d 0a 70 72 6f 63 20 4e 4f 54 20 7b  gs].}.proc NOT {
1d20: 61 20 62 7d 20 7b 0a 20 20 69 66 20 7b 5b 6c 6c  a b} {.  if {[ll
1d30: 65 6e 67 74 68 20 24 62 5d 3e 30 7d 20 7b 20 72  ength $b]>0} { r
1d40: 65 74 75 72 6e 20 5b 6c 69 73 74 5d 20 7d 0a 20  eturn [list] }. 
1d50: 20 72 65 74 75 72 6e 20 24 61 0a 7d 0a 0a 23 2d   return $a.}..#-
1d60: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
1d70: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
1d80: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
1d90: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d  ----------------
1da0: 2d 2d 2d 2d 2d 2d 2d 2d 0a 23 20 54 68 69 73 20  --------.# This 
1db0: 63 6f 6d 6d 61 6e 64 20 69 73 20 73 69 6d 69 6c  command is simil
1dc0: 61 72 20 74 6f 20 5b 73 70 6c 69 74 5d 2c 20 65  ar to [split], e
1dd0: 78 63 65 70 74 20 74 68 61 74 20 69 74 20 61 6c  xcept that it al
1de0: 73 6f 20 70 72 6f 76 69 64 65 73 20 74 68 65 0a  so provides the.
1df0: 23 20 73 74 61 72 74 20 61 6e 64 20 65 6e 64 20  # start and end 
1e00: 6f 66 66 73 65 74 73 20 6f 66 20 65 61 63 68 20  offsets of each 
1e10: 74 6f 6b 65 6e 2e 20 46 6f 72 20 65 78 61 6d 70  token. For examp
1e20: 6c 65 3a 0a 23 0a 23 20 20 20 5b 66 74 73 35 5f  le:.#.#   [fts5_
1e30: 74 6f 6b 65 6e 69 7a 65 5f 73 70 6c 69 74 20 22  tokenize_split "
1e40: 61 62 63 20 64 20 65 66 22 5d 20 2d 3e 20 7b 61  abc d ef"] -> {a
1e50: 62 63 20 30 20 33 20 64 20 34 20 35 20 65 66 20  bc 0 3 d 4 5 ef 
1e60: 36 20 38 7d 0a 23 0a 0a 70 72 6f 63 20 67 6f 62  6 8}.#..proc gob
1e70: 62 6c 65 5f 77 68 69 74 65 73 70 61 63 65 20 7b  ble_whitespace {
1e80: 74 65 78 74 76 61 72 7d 20 7b 0a 20 20 75 70 76  textvar} {.  upv
1e90: 61 72 20 24 74 65 78 74 76 61 72 20 74 0a 20 20  ar $textvar t.  
1ea0: 72 65 67 65 78 70 20 7b 28 5b 20 5d 2a 29 28 2e  regexp {([ ]*)(.
1eb0: 2a 29 7d 20 24 74 20 2d 3e 20 73 70 61 63 65 20  *)} $t -> space 
1ec0: 74 0a 20 20 72 65 74 75 72 6e 20 5b 73 74 72 69  t.  return [stri
1ed0: 6e 67 20 6c 65 6e 67 74 68 20 24 73 70 61 63 65  ng length $space
1ee0: 5d 0a 7d 0a 0a 70 72 6f 63 20 67 6f 62 62 6c 65  ].}..proc gobble
1ef0: 5f 74 65 78 74 20 7b 74 65 78 74 76 61 72 20 77  _text {textvar w
1f00: 6f 72 64 76 61 72 7d 20 7b 0a 20 20 75 70 76 61  ordvar} {.  upva
1f10: 72 20 24 74 65 78 74 76 61 72 20 74 0a 20 20 75  r $textvar t.  u
1f20: 70 76 61 72 20 24 77 6f 72 64 76 61 72 20 77 0a  pvar $wordvar w.
1f30: 20 20 72 65 67 65 78 70 20 7b 28 5b 5e 20 5d 2a    regexp {([^ ]*
1f40: 29 28 2e 2a 29 7d 20 24 74 20 2d 3e 20 77 20 74  )(.*)} $t -> w t
1f50: 0a 20 20 72 65 74 75 72 6e 20 5b 73 74 72 69 6e  .  return [strin
1f60: 67 20 6c 65 6e 67 74 68 20 24 77 5d 0a 7d 0a 0a  g length $w].}..
1f70: 70 72 6f 63 20 66 74 73 35 5f 74 6f 6b 65 6e 69  proc fts5_tokeni
1f80: 7a 65 5f 73 70 6c 69 74 20 7b 74 65 78 74 7d 20  ze_split {text} 
1f90: 7b 0a 20 20 73 65 74 20 74 6f 6b 65 6e 20 22 22  {.  set token ""
1fa0: 0a 20 20 73 65 74 20 72 65 74 20 5b 6c 69 73 74  .  set ret [list
1fb0: 5d 0a 20 20 73 65 74 20 69 4f 66 66 20 5b 67 6f  ].  set iOff [go
1fc0: 62 62 6c 65 5f 77 68 69 74 65 73 70 61 63 65 20  bble_whitespace 
1fd0: 74 65 78 74 5d 0a 20 20 77 68 69 6c 65 20 7b 5b  text].  while {[
1fe0: 73 65 74 20 6e 54 6f 6b 65 6e 20 5b 67 6f 62 62  set nToken [gobb
1ff0: 6c 65 5f 74 65 78 74 20 74 65 78 74 20 77 6f 72  le_text text wor
2000: 64 5d 5d 7d 20 7b 0a 20 20 20 20 6c 61 70 70 65  d]]} {.    lappe
2010: 6e 64 20 72 65 74 20 24 77 6f 72 64 20 24 69 4f  nd ret $word $iO
2020: 66 66 20 5b 65 78 70 72 20 24 69 4f 66 66 2b 24  ff [expr $iOff+$
2030: 6e 54 6f 6b 65 6e 5d 0a 20 20 20 20 69 6e 63 72  nToken].    incr
2040: 20 69 4f 66 66 20 24 6e 54 6f 6b 65 6e 0a 20 20   iOff $nToken.  
2050: 20 20 69 6e 63 72 20 69 4f 66 66 20 5b 67 6f 62    incr iOff [gob
2060: 62 6c 65 5f 77 68 69 74 65 73 70 61 63 65 20 74  ble_whitespace t
2070: 65 78 74 5d 0a 20 20 7d 0a 0a 20 20 73 65 74 20  ext].  }..  set 
2080: 72 65 74 0a 7d 0a 0a                             ret.}..