From: dan Date: Mon, 7 Dec 2009 12:34:51 +0000 (+0000) Subject: Add some tests for OR, AND and NOT operations to fts3rnd.test. Add tests to check... X-Git-Tag: version-3.7.2~741 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ff32e39c8e1689fc2ba1581330bf44e21b1425fa;p=thirdparty%2Fsqlite.git Add some tests for OR, AND and NOT operations to fts3rnd.test. Add tests to check that errors are returned when bad arguments are passed to fts3 functions snippet, offsets and optimize. Minor fix for the same FossilOrigin-Name: 5811df3f0412598d189d46b58de4deff24573651 --- diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index ee3981cfb9..818e130db3 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -646,7 +646,7 @@ int fts3InitVtab( 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--; @@ -1470,8 +1470,7 @@ static int fts3DoclistMerge( 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 ){ @@ -1506,9 +1505,6 @@ static int fts3DoclistMerge( sqlite3_free(aTmp); break; } - - default: - assert(!"Invalid mergetype value passed to fts3DoclistMerge()"); } *pnBuffer = (int)(p-aBuffer); @@ -2085,7 +2081,7 @@ static int fts3FunctionArg( ){ 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); @@ -2101,22 +2097,31 @@ static int fts3FunctionArg( ** 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 = ""; const char *zEnd = ""; const char *zEllipsis = "..."; - 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); diff --git a/manifest b/manifest index ab1ae10f57..af701c58d6 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------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 @@ -59,7 +56,7 @@ F ext/fts2/mkfts2amal.tcl 974d5d438cb3f7c4a652639262f82418c1e4cff0 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 @@ -329,7 +326,7 @@ F test/descidx3.test 3394ad4d089335cac743c36a14129d6d931c316f 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 @@ -405,7 +402,7 @@ F test/fts3expr.test 05dab77387801e4900009917bb18f556037d82da 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 @@ -779,14 +776,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff 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 diff --git a/manifest.uuid b/manifest.uuid index 89f0f2bfcb..ed71393961 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5a511f98877f0f7f12d336b7831f3da901856b02 \ No newline at end of file +5811df3f0412598d189d46b58de4deff24573651 \ No newline at end of file diff --git a/test/e_fts3.test b/test/e_fts3.test index 319f7f67c2..1c7afc2625 100644 --- a/test/e_fts3.test +++ b/test/e_fts3.test @@ -32,6 +32,9 @@ proc write_test {tn tbl sql} { 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] +} #------------------------------------------------------------------------- @@ -43,7 +46,7 @@ proc read_test {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. @@ -435,5 +438,32 @@ read_test 1.8.2.4 { # 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 diff --git a/test/fts3rnd.test b/test/fts3rnd.test index 5acac485ff..0fb1512289 100644 --- a/test/fts3rnd.test +++ b/test/fts3rnd.test @@ -69,27 +69,14 @@ proc update_row {rowid} { 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] @@ -121,6 +108,35 @@ proc simple_near {termlist nNear} { 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 } @@ -162,7 +178,7 @@ foreach nodesize {50 500 1000 2000} { 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 @@ -174,7 +190,7 @@ foreach nodesize {50 500 1000 2000} { 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. @@ -184,9 +200,9 @@ foreach nodesize {50 500 1000 2000} { 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} { @@ -194,7 +210,20 @@ foreach nodesize {50 500 1000 2000} { 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. @@ -202,11 +231,11 @@ foreach nodesize {50 500 1000 2000} { 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} { @@ -214,11 +243,49 @@ foreach nodesize {50 500 1000 2000} { 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] + ] + } + } } }