Annotation of embedaddon/sqlite3/test/fts3aux1.test, revision 1.1
1.1 ! misho 1: # 2011 January 27
! 2: #
! 3: # The author disclaims copyright to this source code. In place of
! 4: # a legal notice, here is a blessing:
! 5: #
! 6: # May you do good and not evil.
! 7: # May you find forgiveness for yourself and forgive others.
! 8: # May you share freely, never taking more than you give.
! 9: #
! 10: #*************************************************************************
! 11: # This file implements regression tests for SQLite library. The
! 12: # focus of this script is testing the FTS3 module.
! 13: #
! 14:
! 15: set testdir [file dirname $argv0]
! 16: source $testdir/tester.tcl
! 17: ifcapable !fts3 { finish_test ; return }
! 18: set ::testprefix fts3aux1
! 19:
! 20: do_execsql_test 1.1 {
! 21: CREATE VIRTUAL TABLE t1 USING fts4;
! 22: INSERT INTO t1 VALUES('one two three four');
! 23: INSERT INTO t1 VALUES('three four five six');
! 24: INSERT INTO t1 VALUES('one three five seven');
! 25:
! 26: CREATE VIRTUAL TABLE terms USING fts4aux(t1);
! 27: SELECT term, documents, occurrences FROM terms WHERE col = '*';
! 28: } {
! 29: five 2 2 four 2 2 one 2 2 seven 1 1
! 30: six 1 1 three 3 3 two 1 1
! 31: }
! 32:
! 33: do_execsql_test 1.2 {
! 34: INSERT INTO t1 VALUES('one one one three three three');
! 35: SELECT term, documents, occurrences FROM terms WHERE col = '*';
! 36: } {
! 37: five 2 2 four 2 2 one 3 5 seven 1 1
! 38: six 1 1 three 4 6 two 1 1
! 39: }
! 40:
! 41: do_execsql_test 1.3.1 { DELETE FROM t1; }
! 42: do_execsql_test 1.3.2 {
! 43: SELECT term, documents, occurrences FROM terms WHERE col = '*';
! 44: }
! 45:
! 46: do_execsql_test 1.4 {
! 47: INSERT INTO t1 VALUES('a b a b a b a');
! 48: INSERT INTO t1 SELECT * FROM t1;
! 49: INSERT INTO t1 SELECT * FROM t1;
! 50: INSERT INTO t1 SELECT * FROM t1;
! 51: INSERT INTO t1 SELECT * FROM t1;
! 52: INSERT INTO t1 SELECT * FROM t1;
! 53: INSERT INTO t1 SELECT * FROM t1;
! 54: INSERT INTO t1 SELECT * FROM t1;
! 55: INSERT INTO t1 SELECT * FROM t1;
! 56: SELECT term, documents, occurrences FROM terms WHERE col = '*';
! 57: } {a 256 1024 b 256 768}
! 58:
! 59: #-------------------------------------------------------------------------
! 60: # The following tests verify that the fts4aux module uses the full-text
! 61: # index to reduce the number of rows scanned in the following circumstances:
! 62: #
! 63: # * when there is equality comparison against the term column using the
! 64: # BINARY collating sequence.
! 65: #
! 66: # * when there is a range constraint on the term column using the BINARY
! 67: # collating sequence.
! 68: #
! 69: # And also uses the full-text index to optimize ORDER BY clauses of the
! 70: # form "ORDER BY term ASC" or equivalent.
! 71: #
! 72: # Test organization is:
! 73: #
! 74: # fts3aux1-2.1.*: equality constraints.
! 75: # fts3aux1-2.2.*: range constraints.
! 76: # fts3aux1-2.3.*: ORDER BY optimization.
! 77: #
! 78:
! 79: do_execsql_test 2.0 {
! 80: DROP TABLE t1;
! 81: DROP TABLE terms;
! 82:
! 83: CREATE VIRTUAL TABLE x1 USING fts4(x);
! 84: INSERT INTO x1(x1) VALUES('nodesize=24');
! 85: CREATE VIRTUAL TABLE terms USING fts4aux(x1);
! 86:
! 87: CREATE VIEW terms_v AS
! 88: SELECT term, documents, occurrences FROM terms WHERE col = '*';
! 89:
! 90: INSERT INTO x1 VALUES('braes brag bragged bragger bragging');
! 91: INSERT INTO x1 VALUES('brags braid braided braiding braids');
! 92: INSERT INTO x1 VALUES('brain brainchild brained braining brains');
! 93: INSERT INTO x1 VALUES('brainstem brainstems brainstorm brainstorms');
! 94: }
! 95:
! 96: proc rec {varname x} {
! 97: global $varname
! 98: incr $varname
! 99: return 1
! 100: }
! 101: db func rec rec
! 102:
! 103: # Use EQP to show that the WHERE expression "term='braid'" uses a different
! 104: # index number (1) than "+term='braid'" (0).
! 105: #
! 106: do_execsql_test 2.1.1.1 {
! 107: EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term='braid'
! 108: } { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 1: (~0 rows)} }
! 109: do_execsql_test 2.1.1.2 {
! 110: EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term='braid'
! 111: } {0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0: (~0 rows)}}
! 112:
! 113: # Now show that using "term='braid'" means the virtual table returns
! 114: # only 1 row to SQLite, but "+term='braid'" means all 19 are returned.
! 115: #
! 116: do_test 2.1.2.1 {
! 117: set cnt 0
! 118: execsql { SELECT * FROM terms_v WHERE rec('cnt', term) AND term='braid' }
! 119: set cnt
! 120: } {2}
! 121: do_test 2.1.2.2 {
! 122: set cnt 0
! 123: execsql { SELECT * FROM terms_v WHERE rec('cnt', term) AND +term='braid' }
! 124: set cnt
! 125: } {38}
! 126:
! 127: # Similar to the test immediately above, but using a term ("breakfast") that
! 128: # is not featured in the dataset.
! 129: #
! 130: do_test 2.1.3.1 {
! 131: set cnt 0
! 132: execsql { SELECT * FROM terms_v WHERE rec('cnt', term) AND term='breakfast' }
! 133: set cnt
! 134: } {0}
! 135: do_test 2.1.3.2 {
! 136: set cnt 0
! 137: execsql { SELECT * FROM terms_v WHERE rec('cnt', term) AND +term='breakfast' }
! 138: set cnt
! 139: } {38}
! 140:
! 141: do_execsql_test 2.1.4.1 { SELECT * FROM terms_v WHERE term='braid' } {braid 1 1}
! 142: do_execsql_test 2.1.4.2 { SELECT * FROM terms_v WHERE +term='braid'} {braid 1 1}
! 143: do_execsql_test 2.1.4.3 { SELECT * FROM terms_v WHERE term='breakfast' } {}
! 144: do_execsql_test 2.1.4.4 { SELECT * FROM terms_v WHERE +term='breakfast' } {}
! 145:
! 146: do_execsql_test 2.1.4.5 { SELECT * FROM terms_v WHERE term='cba' } {}
! 147: do_execsql_test 2.1.4.6 { SELECT * FROM terms_v WHERE +term='cba' } {}
! 148: do_execsql_test 2.1.4.7 { SELECT * FROM terms_v WHERE term='abc' } {}
! 149: do_execsql_test 2.1.4.8 { SELECT * FROM terms_v WHERE +term='abc' } {}
! 150:
! 151: # Special case: term=NULL
! 152: #
! 153: do_execsql_test 2.1.5 { SELECT * FROM terms WHERE term=NULL } {}
! 154:
! 155: do_execsql_test 2.2.1.1 {
! 156: EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term>'brain'
! 157: } { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 2: (~0 rows)} }
! 158: do_execsql_test 2.2.1.2 {
! 159: EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term>'brain'
! 160: } { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0: (~0 rows)} }
! 161:
! 162: do_execsql_test 2.2.1.3 {
! 163: EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term<'brain'
! 164: } { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 4: (~0 rows)} }
! 165: do_execsql_test 2.2.1.4 {
! 166: EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term<'brain'
! 167: } { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0: (~0 rows)} }
! 168:
! 169: do_execsql_test 2.2.1.5 {
! 170: EXPLAIN QUERY PLAN SELECT * FROM terms WHERE term BETWEEN 'brags' AND 'brain'
! 171: } { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 6: (~0 rows)} }
! 172: do_execsql_test 2.2.1.6 {
! 173: EXPLAIN QUERY PLAN SELECT * FROM terms WHERE +term BETWEEN 'brags' AND 'brain'
! 174: } { 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0: (~0 rows)} }
! 175:
! 176: do_test 2.2.2.1 {
! 177: set cnt 0
! 178: execsql { SELECT * FROM terms WHERE rec('cnt', term) AND term>'brain' }
! 179: set cnt
! 180: } {18}
! 181: do_test 2.2.2.2 {
! 182: set cnt 0
! 183: execsql { SELECT * FROM terms WHERE rec('cnt', term) AND +term>'brain' }
! 184: set cnt
! 185: } {38}
! 186: do_execsql_test 2.2.2.3 {
! 187: SELECT term, documents, occurrences FROM terms_v WHERE term>'brain'
! 188: } {
! 189: brainchild 1 1 brained 1 1 braining 1 1 brains 1 1
! 190: brainstem 1 1 brainstems 1 1 brainstorm 1 1 brainstorms 1 1
! 191: }
! 192: do_execsql_test 2.2.2.4 {
! 193: SELECT term, documents, occurrences FROM terms_v WHERE +term>'brain'
! 194: } {
! 195: brainchild 1 1 brained 1 1 braining 1 1 brains 1 1
! 196: brainstem 1 1 brainstems 1 1 brainstorm 1 1 brainstorms 1 1
! 197: }
! 198: do_execsql_test 2.2.2.5 {
! 199: SELECT term, documents, occurrences FROM terms_v WHERE term>='brain'
! 200: } {
! 201: brain 1 1
! 202: brainchild 1 1 brained 1 1 braining 1 1 brains 1 1
! 203: brainstem 1 1 brainstems 1 1 brainstorm 1 1 brainstorms 1 1
! 204: }
! 205: do_execsql_test 2.2.2.6 {
! 206: SELECT term, documents, occurrences FROM terms_v WHERE +term>='brain'
! 207: } {
! 208: brain 1 1
! 209: brainchild 1 1 brained 1 1 braining 1 1 brains 1 1
! 210: brainstem 1 1 brainstems 1 1 brainstorm 1 1 brainstorms 1 1
! 211: }
! 212:
! 213: do_execsql_test 2.2.2.7 {
! 214: SELECT term, documents, occurrences FROM terms_v WHERE term>='abc'
! 215: } {
! 216: braes 1 1 brag 1 1 bragged 1 1 bragger 1 1
! 217: bragging 1 1 brags 1 1 braid 1 1 braided 1 1
! 218: braiding 1 1 braids 1 1 brain 1 1 brainchild 1 1
! 219: brained 1 1 braining 1 1 brains 1 1 brainstem 1 1
! 220: brainstems 1 1 brainstorm 1 1 brainstorms 1 1
! 221: }
! 222: do_execsql_test 2.2.2.8 {
! 223: SELECT term, documents, occurrences FROM terms_v WHERE +term>='abc'
! 224: } {
! 225: braes 1 1 brag 1 1 bragged 1 1 bragger 1 1
! 226: bragging 1 1 brags 1 1 braid 1 1 braided 1 1
! 227: braiding 1 1 braids 1 1 brain 1 1 brainchild 1 1
! 228: brained 1 1 braining 1 1 brains 1 1 brainstem 1 1
! 229: brainstems 1 1 brainstorm 1 1 brainstorms 1 1
! 230: }
! 231:
! 232: do_execsql_test 2.2.2.9 {
! 233: SELECT term, documents, occurrences FROM terms_v WHERE term>='brainstorms'
! 234: } {brainstorms 1 1}
! 235: do_execsql_test 2.2.2.10 {
! 236: SELECT term, documents, occurrences FROM terms_v WHERE term>='brainstorms'
! 237: } {brainstorms 1 1}
! 238: do_execsql_test 2.2.2.11 { SELECT * FROM terms_v WHERE term>'brainstorms' } {}
! 239: do_execsql_test 2.2.2.12 { SELECT * FROM terms_v WHERE term>'brainstorms' } {}
! 240:
! 241: do_execsql_test 2.2.2.13 { SELECT * FROM terms_v WHERE term>'cba' } {}
! 242: do_execsql_test 2.2.2.14 { SELECT * FROM terms_v WHERE term>'cba' } {}
! 243:
! 244: do_test 2.2.3.1 {
! 245: set cnt 0
! 246: execsql { SELECT * FROM terms WHERE rec('cnt', term) AND term<'brain' }
! 247: set cnt
! 248: } {22}
! 249: do_test 2.2.3.2 {
! 250: set cnt 0
! 251: execsql { SELECT * FROM terms WHERE rec('cnt', term) AND +term<'brain' }
! 252: set cnt
! 253: } {38}
! 254: do_execsql_test 2.2.3.3 {
! 255: SELECT term, documents, occurrences FROM terms_v WHERE term<'brain'
! 256: } {
! 257: braes 1 1 brag 1 1 bragged 1 1 bragger 1 1 bragging 1 1
! 258: brags 1 1 braid 1 1 braided 1 1 braiding 1 1 braids 1 1
! 259: }
! 260: do_execsql_test 2.2.3.4 {
! 261: SELECT term, documents, occurrences FROM terms_v WHERE +term<'brain'
! 262: } {
! 263: braes 1 1 brag 1 1 bragged 1 1 bragger 1 1 bragging 1 1
! 264: brags 1 1 braid 1 1 braided 1 1 braiding 1 1 braids 1 1
! 265: }
! 266: do_execsql_test 2.2.3.5 {
! 267: SELECT term, documents, occurrences FROM terms_v WHERE term<='brain'
! 268: } {
! 269: braes 1 1 brag 1 1 bragged 1 1 bragger 1 1 bragging 1 1
! 270: brags 1 1 braid 1 1 braided 1 1 braiding 1 1 braids 1 1
! 271: brain 1 1
! 272: }
! 273: do_execsql_test 2.2.3.6 {
! 274: SELECT term, documents, occurrences FROM terms_v WHERE +term<='brain'
! 275: } {
! 276: braes 1 1 brag 1 1 bragged 1 1 bragger 1 1 bragging 1 1
! 277: brags 1 1 braid 1 1 braided 1 1 braiding 1 1 braids 1 1
! 278: brain 1 1
! 279: }
! 280:
! 281: do_test 2.2.4.1 {
! 282: set cnt 0
! 283: execsql {
! 284: SELECT term, documents, occurrences FROM terms
! 285: WHERE rec('cnt', term) AND term BETWEEN 'brags' AND 'brain'
! 286: }
! 287: set cnt
! 288: } {12}
! 289: do_test 2.2.4.2 {
! 290: set cnt 0
! 291: execsql {
! 292: SELECT term, documents, occurrences FROM terms
! 293: WHERE rec('cnt', term) AND +term BETWEEN 'brags' AND 'brain'
! 294: }
! 295: set cnt
! 296: } {38}
! 297: do_execsql_test 2.2.4.3 {
! 298: SELECT term, documents, occurrences FROM terms_v
! 299: WHERE rec('cnt', term) AND term BETWEEN 'brags' AND 'brain'
! 300: } {
! 301: brags 1 1 braid 1 1 braided 1 1 braiding 1 1 braids 1 1 brain 1 1
! 302: }
! 303: do_execsql_test 2.2.4.4 {
! 304: SELECT term, documents, occurrences FROM terms_v
! 305: WHERE rec('cnt', term) AND +term BETWEEN 'brags' AND 'brain'
! 306: } {
! 307: brags 1 1 braid 1 1 braided 1 1 braiding 1 1 braids 1 1 brain 1 1
! 308: }
! 309: do_execsql_test 2.2.4.5 {
! 310: SELECT term, documents, occurrences FROM terms_v
! 311: WHERE rec('cnt', term) AND term > 'brags' AND term < 'brain'
! 312: } {
! 313: braid 1 1 braided 1 1 braiding 1 1 braids 1 1
! 314: }
! 315: do_execsql_test 2.2.4.6 {
! 316: SELECT term, documents, occurrences FROM terms_v
! 317: WHERE rec('cnt', term) AND +term > 'brags' AND +term < 'brain'
! 318: } {
! 319: braid 1 1 braided 1 1 braiding 1 1 braids 1 1
! 320: }
! 321:
! 322: # Check that "ORDER BY term ASC" and equivalents are sorted by the
! 323: # virtual table implementation. Any other ORDER BY clause requires
! 324: # SQLite to sort results using a temporary b-tree.
! 325: #
! 326: foreach {tn sort orderby} {
! 327: 1 0 "ORDER BY term ASC"
! 328: 2 0 "ORDER BY term"
! 329: 3 1 "ORDER BY term DESC"
! 330: 4 1 "ORDER BY documents ASC"
! 331: 5 1 "ORDER BY documents"
! 332: 6 1 "ORDER BY documents DESC"
! 333: 7 1 "ORDER BY occurrences ASC"
! 334: 8 1 "ORDER BY occurrences"
! 335: 9 1 "ORDER BY occurrences DESC"
! 336: } {
! 337:
! 338: set res [list 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0: (~0 rows)}]
! 339: if {$sort} { lappend res 0 0 0 {USE TEMP B-TREE FOR ORDER BY} }
! 340:
! 341: set sql "SELECT * FROM terms $orderby"
! 342: do_execsql_test 2.3.1.$tn "EXPLAIN QUERY PLAN $sql" $res
! 343: }
! 344:
! 345: #-------------------------------------------------------------------------
! 346: # The next set of tests, fts3aux1-3.*, test error conditions in the
! 347: # fts4aux module. Except, fault injection testing (OOM, IO error etc.) is
! 348: # done in fts3fault2.test
! 349: #
! 350:
! 351: do_execsql_test 3.1.1 {
! 352: CREATE VIRTUAL TABLE t2 USING fts4;
! 353: }
! 354:
! 355: do_catchsql_test 3.1.2 {
! 356: CREATE VIRTUAL TABLE terms2 USING fts4aux;
! 357: } {1 {wrong number of arguments to fts4aux constructor}}
! 358: do_catchsql_test 3.1.3 {
! 359: CREATE VIRTUAL TABLE terms2 USING fts4aux(t2, t2);
! 360: } {1 {wrong number of arguments to fts4aux constructor}}
! 361:
! 362: do_execsql_test 3.2.1 {
! 363: CREATE VIRTUAL TABLE terms3 USING fts4aux(does_not_exist)
! 364: }
! 365: do_catchsql_test 3.2.2 {
! 366: SELECT * FROM terms3
! 367: } {1 {SQL logic error or missing database}}
! 368: do_catchsql_test 3.2.3 {
! 369: SELECT * FROM terms3 WHERE term = 'abc'
! 370: } {1 {SQL logic error or missing database}}
! 371:
! 372: do_catchsql_test 3.3.1 {
! 373: INSERT INTO terms VALUES(1,2,3);
! 374: } {1 {table terms may not be modified}}
! 375: do_catchsql_test 3.3.2 {
! 376: DELETE FROM terms
! 377: } {1 {table terms may not be modified}}
! 378: do_catchsql_test 3.3.3 {
! 379: UPDATE terms set documents = documents+1;
! 380: } {1 {table terms may not be modified}}
! 381:
! 382:
! 383: #-------------------------------------------------------------------------
! 384: # The following tests - fts4aux-4.* - test that joins work with fts4aux
! 385: # tables. And that fts4aux provides reasonably sane cost information via
! 386: # xBestIndex to the query planner.
! 387: #
! 388: db close
! 389: forcedelete test.db
! 390: sqlite3 db test.db
! 391: do_execsql_test 4.1 {
! 392: CREATE VIRTUAL TABLE x1 USING fts4(x);
! 393: CREATE VIRTUAL TABLE terms USING fts4aux(x1);
! 394: CREATE TABLE x2(y);
! 395: CREATE TABLE x3(y);
! 396: CREATE INDEX i1 ON x3(y);
! 397:
! 398: INSERT INTO x1 VALUES('a b c d e');
! 399: INSERT INTO x1 VALUES('f g h i j');
! 400: INSERT INTO x1 VALUES('k k l l a');
! 401:
! 402: INSERT INTO x2 SELECT term FROM terms WHERE col = '*';
! 403: INSERT INTO x3 SELECT term FROM terms WHERE col = '*';
! 404: }
! 405:
! 406: proc do_plansql_test {tn sql r} {
! 407: uplevel do_execsql_test $tn [list "EXPLAIN QUERY PLAN $sql ; $sql"] [list $r]
! 408: }
! 409:
! 410: do_plansql_test 4.2 {
! 411: SELECT y FROM x2, terms WHERE y = term AND col = '*'
! 412: } {
! 413: 0 0 0 {SCAN TABLE x2 (~1000000 rows)}
! 414: 0 1 1 {SCAN TABLE terms VIRTUAL TABLE INDEX 1: (~0 rows)}
! 415: a b c d e f g h i j k l
! 416: }
! 417:
! 418: do_plansql_test 4.3 {
! 419: SELECT y FROM terms, x2 WHERE y = term AND col = '*'
! 420: } {
! 421: 0 0 1 {SCAN TABLE x2 (~1000000 rows)}
! 422: 0 1 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 1: (~0 rows)}
! 423: a b c d e f g h i j k l
! 424: }
! 425:
! 426: do_plansql_test 4.4 {
! 427: SELECT y FROM x3, terms WHERE y = term AND col = '*'
! 428: } {
! 429: 0 0 1 {SCAN TABLE terms VIRTUAL TABLE INDEX 0: (~0 rows)}
! 430: 0 1 0 {SEARCH TABLE x3 USING COVERING INDEX i1 (y=?) (~10 rows)}
! 431: a b c d e f g h i j k l
! 432: }
! 433:
! 434: do_plansql_test 4.5 {
! 435: SELECT y FROM terms, x3 WHERE y = term AND occurrences>1 AND col = '*'
! 436: } {
! 437: 0 0 0 {SCAN TABLE terms VIRTUAL TABLE INDEX 0: (~0 rows)}
! 438: 0 1 1 {SEARCH TABLE x3 USING COVERING INDEX i1 (y=?) (~10 rows)}
! 439: a k l
! 440: }
! 441:
! 442: #-------------------------------------------------------------------------
! 443: # The following tests check that fts4aux can handle an fts table with an
! 444: # odd name (one that requires quoting for use in SQL statements). And that
! 445: # the argument to the fts4aux constructor is properly dequoted before use.
! 446: #
! 447: #
! 448: do_execsql_test 5.1 {
! 449: CREATE VIRTUAL TABLE "abc '!' def" USING fts4(x, y);
! 450: INSERT INTO "abc '!' def" VALUES('XX', 'YY');
! 451:
! 452: CREATE VIRTUAL TABLE terms3 USING fts4aux("abc '!' def");
! 453: SELECT * FROM terms3;
! 454: } {xx * 1 1 xx 0 1 1 yy * 1 1 yy 1 1 1}
! 455:
! 456: do_execsql_test 5.2 {
! 457: CREATE VIRTUAL TABLE "%%^^%%" USING fts4aux('abc ''!'' def');
! 458: SELECT * FROM "%%^^%%";
! 459: } {xx * 1 1 xx 0 1 1 yy * 1 1 yy 1 1 1}
! 460:
! 461:
! 462: finish_test
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>