SQLite

Check-in [c1f9a4b76c]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fixes for tcl list generation in fts5_test().
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | fts5
Files: files | file ages | folders
SHA1: c1f9a4b76c0bbc1ef9f6cdb5d62aa5d536fdf38e
User & Date: dan 2014-07-16 20:07:59.378
Context
2014-07-17
15:14
Fix a problem with position list processing for OR queries. (check-in: 5808f30fae user: dan tags: fts5)
2014-07-16
20:07
Fixes for tcl list generation in fts5_test(). (check-in: c1f9a4b76c user: dan tags: fts5)
19:15
Begin adding interface for auxiliary functions. (check-in: 1e2a7ba088 user: dan tags: fts5)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/fts5/fts5_aux.c.
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
    }
  }

  if( zReq==0 ){
    sqlite3Fts5BufferAppendPrintf(&rc, &s, " poslist ");
  }
  if( 0==zReq || 0==sqlite3_stricmp(zReq, "poslist") ){

    sqlite3Fts5BufferAppendPrintf(&rc, &s, "{");



    for(i=0; i<nPhrase; i++){

      int j = 0;
      int iOff = 0;
      int iCol = 0;
      int bFirst = 1;
      sqlite3Fts5BufferAppendPrintf(&rc, &s, "%s{", (i==0?"":" "));

      while( 0==pApi->xPoslist(pFts, i, &j, &iCol, &iOff) ){

        sqlite3Fts5BufferAppendPrintf(


            &rc, &s, "%s%d.%d", (bFirst?"":" "), iCol, iOff
        );
        bFirst = 0;

      }

      sqlite3Fts5BufferAppendPrintf(&rc, &s, "}");



    }




    sqlite3Fts5BufferAppendPrintf(&rc, &s, "}");




  }

  if( zReq==0 ){
    sqlite3Fts5BufferAppendPrintf(&rc, &s, " rowid ");
  }
  if( 0==zReq || 0==sqlite3_stricmp(zReq, "rowid") ){
    iRowid = pApi->xRowid(pFts);







>
|
>
>
>

>



|
|
>

>
|
>
>
|
|
<
>

>
|
>
>
>
|
>
>
>
>
|
>
>
>
>







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
    }
  }

  if( zReq==0 ){
    sqlite3Fts5BufferAppendPrintf(&rc, &s, " poslist ");
  }
  if( 0==zReq || 0==sqlite3_stricmp(zReq, "poslist") ){
    int bParen = 0;
    Fts5Buffer s3;
    memset(&s3, 0, sizeof(s3));


    for(i=0; i<nPhrase; i++){
      Fts5Buffer s2;                  /* List of positions for phrase/column */
      int j = 0;
      int iOff = 0;
      int iCol = 0;
      int nElem = 0;

      memset(&s2, 0, sizeof(s2));
      while( 0==pApi->xPoslist(pFts, i, &j, &iCol, &iOff) ){
        if( nElem!=0 ) sqlite3Fts5BufferAppendPrintf(&rc, &s2, " ");
        sqlite3Fts5BufferAppendPrintf(&rc, &s2, "%d.%d", iCol, iOff);
        nElem++;
      }

      if( i!=0 ){

        sqlite3Fts5BufferAppendPrintf(&rc, &s3, " ");
      }
      if( nElem==1 ){
        sqlite3Fts5BufferAppendPrintf(&rc, &s3, "%s", (const char*)s2.p);
      }else{
        sqlite3Fts5BufferAppendPrintf(&rc, &s3, "{%s}", (const char*)s2.p);
        bParen = 1;
      }
      sqlite3_free(s2.p);
    }

    if(zReq==0 && (nPhrase>1 || bParen) ){
      sqlite3Fts5BufferAppendPrintf(&rc, &s, "{%s}", (const char*)s3.p);
    }else{
      sqlite3Fts5BufferAppendPrintf(&rc, &s, "%s", (const char*)s3.p);
    }
    sqlite3_free(s3.p);
  }

  if( zReq==0 ){
    sqlite3Fts5BufferAppendPrintf(&rc, &s, " rowid ");
  }
  if( 0==zReq || 0==sqlite3_stricmp(zReq, "rowid") ){
    iRowid = pApi->xRowid(pFts);
Changes to test/fts5ac.test.
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

do_test 1.1 {
  foreach {id x y} $data {
    execsql { INSERT INTO xx(rowid, x, y) VALUES($id, $x, $y) }
  }
} {}

proc phrasematch {phrase value} {
  if {[string first $phrase $value]>=0} { return 1 }
  return 0
}

# Usage:
#
proc nearmatch {nNear phraselist value} {
  set nPhrase [llength $phraselist]

  set phraselist [string tolower $phraselist]
  set value [string tolower $value]

  if {$nPhrase==1} {
    set bMatch [phrasematch [lindex $phraselist 0] $value]
  } else {
    set nValue [llength $value]
    if {$nNear >= $nValue} {set nNear [expr $nValue-1]}

    for {set i $nNear} {$i < $nValue} {incr i} {
      set bMatch 1
      foreach phrase $phraselist {
        set iMin [expr $i - $nNear - [llength $phrase]]
        set iMax [expr $i - 1 + [llength $phrase]]
        set subdoc [lrange $value $iMin $iMax]
        if {![phrasematch $phrase $subdoc]} {
          set bMatch 0
          break
        }
      }
      if {$bMatch} break
    }
  }
  return $bMatch
}

# Usage:
#
#   poslist aCol ?-near N? ?-col C? -- phrase1 phrase2...
#
proc poslist {aCol args} {
  set O(-near) 10
  set O(-col)  -1







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







133
134
135
136
137
138
139




































140
141
142
143
144
145
146

do_test 1.1 {
  foreach {id x y} $data {
    execsql { INSERT INTO xx(rowid, x, y) VALUES($id, $x, $y) }
  }
} {}





































# Usage:
#
#   poslist aCol ?-near N? ?-col C? -- phrase1 phrase2...
#
proc poslist {aCol args} {
  set O(-near) 10
  set O(-col)  -1
239
240
241
242
243
244
245

246
247
248
249
250
251
252
      foreach a $A($iCol,$iPhrase) {
        lappend plist "$iCol.$a"
      }
    }
    lappend res $plist
  }


  return $res
}

# Usage:
#
#   nearset aCol ?-near N? ?-col C? -- phrase1 phrase2...
#







>







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
      foreach a $A($iCol,$iPhrase) {
        lappend plist "$iCol.$a"
      }
    }
    lappend res $plist
  }

    #puts $res
  return $res
}

# Usage:
#
#   nearset aCol ?-near N? ?-col C? -- phrase1 phrase2...
#
280
281
282
283
284
285
286
287

288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306






307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327

328
329
330
331
332



333
334
335
336


337
338
339
340
341
342
343
344
345
346
347
348
    set cols [list $x $y]
    if $tclexpr {
      if {$bPos} {
        set N [regexp -all -inline {\[nearset [^\]]*\]} $tclexpr]
        set rowres [list]
        foreach phrase $N {
          set cmd "poslist [string range $phrase 9 end-1]"
          lappend rowres [eval $cmd]

        }
        if {[string first "\{" $rowres]<0} { set rowres "{{$rowres}}" }
        lappend res [list $id $rowres]
      } else {
        lappend res $id
      }
    }
  }

  if {$bAsc} {
    set res [lsort -integer -increasing -index 0 $res]
  } else {
    set res [lsort -integer -decreasing -index 0 $res]
  }

  return [concat {*}$res]
}








foreach {tn phrase} {
  1 "o"
  2 "b q"
  3 "e a e"
  4 "m d g q q b k b w f q q p p"
  5 "l o o l v v k"
  6 "a"
  7 "b"
  8 "c"
  9 "no"
  10 "L O O L V V K"
} {

  set expr "\"$phrase\""
  set res [matchdata 1 $expr]

  do_execsql_test 1.2.$tn.[llength $res] { 
    SELECT rowid, fts5_test(xx, 'poslist') FROM xx WHERE xx match $expr
  } $res
}


# Test the "nearmatch" commnad.
#
do_test 2.0 { nearmatch 2 {a b} {a x x b} } 1
do_test 2.1 { nearmatch 2 {b a} {a x x b} } 1
do_test 2.2 { nearmatch 1 {b a} {a x x b} } 0



do_test 2.3 { nearmatch 1 {"a b" "c d"} {x x a b x c d} } 1
do_test 2.4 { nearmatch 1 {"a b" "c d"} {x a b x x c d} } 0
do_test 2.5 { nearmatch 400 {a b} {a x x b} } 1
do_test 2.6 { nearmatch 0 {a} {a x x b} } 1


do_test 2.7 { nearmatch 0 {b} {a x x b} } 1

do_test 2.8  { poslist {{a b c}} -- a } {0.0}
do_test 2.9  { poslist {{a b c}} -- c } {0.2}


foreach {tn expr tclexpr} {
  1 {a b} {[N $x -- {a}] && [N $x -- {b}]}
} {
  do_execsql_test 3.$tn {SELECT fts5_expr_tcl($expr, 'N $x')} [list $tclexpr]
}








|
>

<
















|
>
>
>
>
>
>












<








>
|

<
|
|
>
>
>
|
|
|
|
>
>
|

|
|
<







245
246
247
248
249
250
251
252
253
254

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289

290
291
292
293
294
295
296
297
298
299
300

301
302
303
304
305
306
307
308
309
310
311
312
313
314
315

316
317
318
319
320
321
322
    set cols [list $x $y]
    if $tclexpr {
      if {$bPos} {
        set N [regexp -all -inline {\[nearset [^\]]*\]} $tclexpr]
        set rowres [list]
        foreach phrase $N {
          set cmd "poslist [string range $phrase 9 end-1]"
          set pos [eval $cmd]
          set rowres [concat $rowres $pos]
        }

        lappend res [list $id $rowres]
      } else {
        lappend res $id
      }
    }
  }

  if {$bAsc} {
    set res [lsort -integer -increasing -index 0 $res]
  } else {
    set res [lsort -integer -decreasing -index 0 $res]
  }

  return [concat {*}$res]
}

#
# End of test code
#-------------------------------------------------------------------------

#-------------------------------------------------------------------------
# Test phrase queries.
#
foreach {tn phrase} {
  1 "o"
  2 "b q"
  3 "e a e"
  4 "m d g q q b k b w f q q p p"
  5 "l o o l v v k"
  6 "a"
  7 "b"
  8 "c"
  9 "no"
  10 "L O O L V V K"
} {

  set expr "\"$phrase\""
  set res [matchdata 1 $expr]

  do_execsql_test 1.2.$tn.[llength $res] { 
    SELECT rowid, fts5_test(xx, 'poslist') FROM xx WHERE xx match $expr
  } $res
}

#-------------------------------------------------------------------------
# Test some AND and OR queries.
#

foreach {tn expr} {
  1 "a   AND b"
  2 "a+b AND c"
  3 "d+c AND u"
  4 "d+c AND u+d"
} {
  set res [matchdata 1 $expr]
  do_execsql_test 2.1.$tn.[llength $res] { 
    SELECT rowid, fts5_test(xx, 'poslist') FROM xx WHERE xx match $expr
  } $res
}


do_test 2.1  { poslist {{a b c}} -- a } {0.0}
do_test 2.2  { poslist {{a b c}} -- c } {0.2}


foreach {tn expr tclexpr} {
  1 {a b} {[N $x -- {a}] && [N $x -- {b}]}
} {
  do_execsql_test 3.$tn {SELECT fts5_expr_tcl($expr, 'N $x')} [list $tclexpr]
}