int nName;
#ifdef SQLITE_TEST
- char *zTestParam = 0;
+ const char *zTestParam = 0;
if( strncmp(argv[argc-1], "test:", 5)==0 ){
zTestParam = argv[argc-1];
argc--;
break;
}
- case MERGE_POS_NEAR:
- case MERGE_NEAR: {
+ default: assert( mergetype==MERGE_POS_NEAR || mergetype==MERGE_NEAR ); {
char *aTmp = 0;
char **ppPos = 0;
if( mergetype==MERGE_POS_NEAR ){
sqlite3_free(aTmp);
break;
}
-
- default:
- assert(!"Invalid mergetype value passed to fts3DoclistMerge()");
}
*pnBuffer = (int)(p-aBuffer);
){
Fts3Cursor *pRet;
if( sqlite3_value_type(pVal)!=SQLITE_BLOB
- && sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
+ || sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
){
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
sqlite3_result_error(pContext, zErr, -1);
** Implementation of the snippet() function for FTS3
*/
static void fts3SnippetFunc(
- sqlite3_context *pContext,
- int argc,
- sqlite3_value **argv
+ sqlite3_context *pContext, /* SQLite function call context */
+ int nVal, /* Size of apVal[] array */
+ sqlite3_value **apVal /* Array of arguments */
){
Fts3Cursor *pCsr; /* Cursor handle passed through apVal[0] */
const char *zStart = "<b>";
const char *zEnd = "</b>";
const char *zEllipsis = "<b>...</b>";
- if( argc<1 || argc>4 ) return;
- if( fts3FunctionArg(pContext, "snippet", argv[0], &pCsr) ) return;
+ /* There must be at least one argument passed to this function (otherwise
+ ** the non-overloaded version would have been called instead of this one).
+ */
+ assert( nVal>=1 );
+
+ if( nVal>4 ){
+ sqlite3_result_error(pContext,
+ "wrong number of arguments to function snippet()", -1);
+ return;
+ }
+ if( fts3FunctionArg(pContext, "snippet", apVal[0], &pCsr) ) return;
- switch( argc ){
- case 4: zEllipsis = (const char*)sqlite3_value_text(argv[3]);
- case 3: zEnd = (const char*)sqlite3_value_text(argv[2]);
- case 2: zStart = (const char*)sqlite3_value_text(argv[1]);
+ switch( nVal ){
+ case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]);
+ case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]);
+ case 2: zStart = (const char*)sqlite3_value_text(apVal[1]);
}
sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis);
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-C Enhanced\sdetection\sof\sdatabase\scorruption\sin\sbtree.c:allocateSpace().
-D 2009-12-06T03:35:51
+C Add\ssome\stests\sfor\sOR,\sAND\sand\sNOT\soperations\sto\sfts3rnd.test.\sAdd\stests\sto\scheck\sthat\serrors\sare\sreturned\swhen\sbad\sarguments\sare\spassed\sto\sfts3\sfunctions\ssnippet,\soffsets\sand\soptimize.\sMinor\sfix\sfor\sthe\ssame
+D 2009-12-07T12:34:52
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers 998756696647400de63d5ba60e9655036cb966e9
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c f4152f277722781048c9bba19aa605dbb831ad9a
+F ext/fts3/fts3.c 43d8cfd021d06d594ec74eb01d35c0a5731055ae
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h cc716c74afa7da8e0f8ef39404f33ea62a823eb3
F ext/fts3/fts3_expr.c c18794a62c257d3456d3314c5a18e348ae0d84bd
F test/diskfull.test 0cede7ef9d8f415d9d3944005c76be7589bb5ebb
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
F test/e_fkey.test fd1fcf89badd5f2773d7ac04775b5ff3488eda17
-F test/e_fts3.test ad278add0deca99d2d8ec3d8b06ffed965d5abc2
+F test/e_fts3.test 8907e25b2c7d6bda9f7077356f64bc5e26c251a7
F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 6d91a5286f59add0cfcbb2d0da913b76f2242398
F test/enc3.test 5c550d59ff31dccdba5d1a02ae11c7047d77c041
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
F test/fts3malloc.test d02ee86b21edd2b43044e0d6dfdcd26cb6efddcb
F test/fts3near.test dc196dd17b4606f440c580d45b3d23aa975fd077
-F test/fts3rnd.test 351197c4459c9d0a20e6413e5bc541a0dbfc4765
+F test/fts3rnd.test ec82795eb358b7a4d6ce79e764d8d55556197584
F test/func.test af106ed834001738246d276659406823e35cde7b
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/fuzz.test a4174c3009a3e2c2e14b31b364ebf7ddb49de2c9
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 7a9a35327c55452e858335933ce11669fc888aeb
-R 0f3ea22a321de0315884a4805815ec31
-U drh
-Z 107d016b4cea97422dcf94676d1dec5c
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.6 (GNU/Linux)
-
-iD8DBQFLGyaaoxKgR168RlERAqRoAJ9BqTXTTVZfQIaYlvy+t0KsL1+C7ACfZ/dm
-hnb7PcWLb+b0XHgfDg673P4=
-=+6jS
------END PGP SIGNATURE-----
+P 5a511f98877f0f7f12d336b7831f3da901856b02
+R 2006ff195b109f8cae8438329e516c90
+U dan
+Z 55cd6fd2906fc3343a73a0ae677b4c81
-5a511f98877f0f7f12d336b7831f3da901856b02
\ No newline at end of file
+5811df3f0412598d189d46b58de4deff24573651
\ No newline at end of file
proc read_test {tn sql result} {
uplevel [list do_select_test e_fts3-$tn $sql $result]
}
+proc error_test {tn sql result} {
+ uplevel [list do_error_test e_fts3-$tn $sql $result]
+}
#-------------------------------------------------------------------------
# DO_MALLOC_TEST=1: Run tests with transient OOM errors.
# DO_MALLOC_TEST=2: Run tests with persistent OOM errors.
#
-foreach DO_MALLOC_TEST {0 1 2} {
+foreach DO_MALLOC_TEST [lrange {0 1 2} 0 end] {
# Reset the database and database connection. If this iteration of the
# [foreach] loop is testing with OOM errors, disable the lookaside buffer.
# End of tests of example code in fts3.html
#-------------------------------------------------------------------------
+#-------------------------------------------------------------------------
+# Test that errors in the arguments passed to the snippet and offsets
+# functions are handled correctly.
+#
+set DO_MALLOC_TEST 0
+ddl_test 2.1.1 { CREATE VIRTUAL TABLE t1 USING fts3(a, b) }
+write_test 2.1.2 t1_content {
+ INSERT INTO t1 VALUES('one two three', x'A1B2C3D4E5F6');
+}
+error_test 2.1.3 {
+ SELECT offsets(a) FROM t1 WHERE a MATCH 'one'
+} {illegal first argument to offsets}
+error_test 2.1.4 {
+ SELECT offsets(b) FROM t1 WHERE a MATCH 'one'
+} {illegal first argument to offsets}
+error_test 2.1.5 {
+ SELECT optimize(a) FROM t1 LIMIT 1
+} {illegal first argument to optimize}
+error_test 2.1.6 {
+ SELECT snippet(a) FROM t1 WHERE a MATCH 'one'
+} {illegal first argument to snippet}
+error_test 2.1.7 {
+ SELECT snippet() FROM t1 WHERE a MATCH 'one'
+} {unable to use function snippet in the requested context}
+error_test 2.1.8 {
+ SELECT snippet(a, b, 'A', 'B', 'C') FROM t1 WHERE a MATCH 'one'
+} {wrong number of arguments to function snippet()}
finish_test
execsql "UPDATE t1 SET [lindex $cols $iCol] = \$doc WHERE rowid = \$rowid"
}
-# Primitives to query the in-memory table.
-#
-proc simple_term {zTerm} {
+proc simple_phrase {zPrefix} {
set ret [list]
- foreach {key value} [array get ::t1] {
- if {[string first $zTerm $value]>=0} { lappend ret $key }
- }
- lsort -integer $ret
-}
-
-proc simple_prefix {zPrefix} {
- set ret [list]
- set pattern [format "*%s%s*" $zPrefix [
- string repeat {[a-z]} [expr {3-[string length $zPrefix]}]
- ]]
+ set pattern "*[string map {* \[a-z\]} $zPrefix]*"
foreach {key value} [array get ::t1] {
if {[string match $pattern $value]} { lappend ret $key }
}
lsort -integer $ret
}
-
proc simple_near {termlist nNear} {
set ret [list]
lsort -unique -integer $ret
}
+# The following three procs:
+#
+# setup_not A B
+# setup_or A B
+# setup_and A B
+#
+# each take two arguments. Both arguments must be lists of integer values
+# sorted by value. The return value is the list produced by evaluating
+# the equivalent of "A op B", where op is the FTS3 operator NOT, OR or
+# AND.
+#
+proc setop_not {A B} {
+ foreach b $B { set n($b) {} }
+ set ret [list]
+ foreach a $A { if {![info exists n($a)]} {lappend ret $a} }
+ return $ret
+}
+proc setop_or {A B} {
+ lsort -integer -uniq [concat $A $B]
+}
+proc setop_and {A B} {
+ foreach b $B { set n($b) {} }
+ set ret [list]
+ foreach a $A { if {[info exists n($a)]} {lappend ret $a} }
+ return $ret
+}
+
+set sqlite_fts3_enable_parentheses 1
+
foreach nodesize {50 500 1000 2000} {
catch { array unset ::t1 }
set term [random_term]
do_test fts3rnd-1.$nodesize.$iTest.1.$i {
execsql { SELECT docid FROM t1 WHERE t1 MATCH $term }
- } [simple_term $term]
+ } [simple_phrase $term]
}
# This time, use the first two characters of each term as a term prefix
set match "${prefix}*"
do_test fts3rnd-1.$nodesize.$iTest.2.$i {
execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
- } [simple_prefix $prefix]
+ } [simple_phrase $match]
}
# Similar to the above, except for phrase queries.
set match "\"$term\""
do_test fts3rnd-1.$nodesize.$iTest.3.$i {
execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
- } [simple_term $term]
+ } [simple_phrase $term]
}
-
+
# Three word phrases.
#
for {set i 0} {$i < 10} {incr i} {
set match "\"$term\""
do_test fts3rnd-1.$nodesize.$iTest.4.$i {
execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
- } [simple_term $term]
+ } [simple_phrase $term]
+ }
+
+ # Three word phrases made up of term-prefixes.
+ #
+ for {set i 0} {$i < 10} {incr i} {
+ set query "[string range [random_term] 0 1]* "
+ append query "[string range [random_term] 0 1]* "
+ append query "[string range [random_term] 0 1]*"
+
+ set match "\"$query\""
+ do_test fts3rnd-1.$nodesize.$iTest.5.$i {
+ execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
+ } [simple_phrase $query]
}
# A NEAR query with terms as the arguments.
for {set i 0} {$i < 10} {incr i} {
set terms [list [random_term] [random_term]]
set match [join $terms " NEAR "]
- do_test fts3rnd-1.$nodesize.$iTest.5.$i.$match {
+ do_test fts3rnd-1.$nodesize.$iTest.6.$i {
execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
} [simple_near $terms 10]
}
-
+
# A 3-way NEAR query with terms as the arguments.
#
for {set i 0} {$i < 10} {incr i} {
set nNear 11
set match [join $terms " NEAR/$nNear "]
set fts3 [execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }]
- set tcl [simple_near $terms $nNear]
- do_test fts3rnd-1.$nodesize.$iTest.5.$i.$match {
+ do_test fts3rnd-1.$nodesize.$iTest.7.$i {
execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
} [simple_near $terms $nNear]
}
+
+ # Set operations on simple term queries.
+ #
+ foreach {tn op proc} {
+ 8 OR setop_or
+ 9 NOT setop_not
+ 10 AND setop_and
+ } {
+ for {set i 0} {$i < 10} {incr i} {
+ set term1 [random_term]
+ set term2 [random_term]
+ set match "$term1 $op $term2"
+ do_test fts3rnd-1.$nodesize.$iTest.$tn.$i {
+ execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
+ } [$proc [simple_phrase $term1] [simple_phrase $term2]]
+ }
+ }
+
+ # Set operations on NEAR queries.
+ #
+ foreach {tn op proc} {
+ 8 OR setop_or
+ 9 NOT setop_not
+ 10 AND setop_and
+ } {
+ for {set i 0} {$i < 10} {incr i} {
+ set term1 [random_term]
+ set term2 [random_term]
+ set term3 [random_term]
+ set term4 [random_term]
+ set match "$term1 NEAR $term2 $op $term3 NEAR $term4"
+ do_test fts3rnd-1.$nodesize.$iTest.$tn.$i {
+ execsql { SELECT docid FROM t1 WHERE t1 MATCH $match }
+ } [$proc \
+ [simple_near [list $term1 $term2] 10] \
+ [simple_near [list $term3 $term4] 10]
+ ]
+ }
+ }
}
}