Files
sqlite/test/where8.test
T
danielk1977 5f0ff5d527 Add a couple of extra tests for the "WHERE ... OR" optimization. (CVS 6077)
FossilOrigin-Name: 35c87585b81866e73a58adffe6af79ddcac57cf6
2008-12-30 12:00:12 +00:00

306 lines
7.8 KiB
Plaintext

# 2008 December 23
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The focus
# is testing of where.c. More specifically, the focus is the optimization
# of WHERE clauses that feature the OR operator.
#
# $Id: where8.test,v 1.2 2008/12/30 12:00:12 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Test organization:
#
# where8-1.*: Tests to demonstrate simple cases work with a single table
# in the FROM clause.
#
# where8-2.*: Tests surrounding virtual tables and the OR optimization.
#
# where8-3.*: Tests with more than one table in the FROM clause.
#
proc execsql_status {sql {db db}} {
set result [uplevel $db eval [list $sql]]
concat $result [db status step] [db status sort]
}
proc execsql_status2 {sql {db db}} {
set ::sqlite_search_count 0
set result [uplevel [list execsql_status $sql $db]]
concat $result $::sqlite_search_count
}
do_test where8-1.1 {
execsql {
CREATE TABLE t1(a, b, c);
CREATE INDEX i1 ON t1(a);
CREATE INDEX i2 ON t1(b);
INSERT INTO t1 VALUES(1, 'one', 'I');
INSERT INTO t1 VALUES(2, 'two', 'II');
INSERT INTO t1 VALUES(3, 'three', 'III');
INSERT INTO t1 VALUES(4, 'four', 'IV');
INSERT INTO t1 VALUES(5, 'five', 'V');
INSERT INTO t1 VALUES(6, 'six', 'VI');
INSERT INTO t1 VALUES(7, 'seven', 'VII');
INSERT INTO t1 VALUES(8, 'eight', 'VIII');
INSERT INTO t1 VALUES(9, 'nine', 'IX');
INSERT INTO t1 VALUES(10, 'ten', 'X');
}
} {}
do_test where8-1.2 {
execsql_status2 { SELECT c FROM t1 WHERE a = 1 OR b = 'nine' }
} {I IX 0 0 6}
do_test where8-1.3 {
execsql_status2 { SELECT c FROM t1 WHERE a > 8 OR b = 'two' }
} {II IX X 0 0 6}
do_test where8-1.4 {
execsql_status2 { SELECT c FROM t1 WHERE a > 8 OR b GLOB 't*' }
} {II III IX X 0 0 9}
do_test where8-1.5 {
execsql_status2 { SELECT c FROM t1 WHERE a > 8 OR b GLOB 'f*' }
} {IV V IX X 0 0 9}
do_test where8-1.6 {
execsql_status { SELECT c FROM t1 WHERE a = 1 OR b = 'three' ORDER BY rowid }
} {I III 0 0}
do_test where8-1.7 {
execsql_status { SELECT c FROM t1 WHERE a = 1 OR b = 'three' ORDER BY a }
} {I III 0 1}
do_test where8-1.8 {
# 18 searches. 9 on the index cursor and 9 on the table cursor.
execsql_status2 { SELECT c FROM t1 WHERE a > 1 AND c LIKE 'I%' }
} {II III IV IX 0 0 18}
do_test where8-1.9 {
execsql_status2 { SELECT c FROM t1 WHERE a >= 9 OR b <= 'eight' }
} {VIII IX X 0 0 6}
do_test where8-1.10 {
execsql_status2 {
SELECT c FROM t1 WHERE (a >= 9 AND c != 'X') OR b <= 'eight'
}
} {VIII IX 0 0 7}
do_test where8-1.11 {
execsql_status2 {
SELECT c FROM t1 WHERE (a >= 4 AND a <= 6) OR b = 'nine'
}
} {IV V VI IX 0 0 10}
do_test where8-1.12.1 {
execsql_status2 {
SELECT c FROM t1 WHERE a IN(1, 2, 3) OR a = 5
}
} {I II III V 0 0 14}
do_test where8-1.12.2 {
execsql_status2 {
SELECT c FROM t1 WHERE +a IN(1, 2, 3) OR +a = 5
}
} {I II III V 9 0 9}
do_test where8-1.13 {
execsql_status2 {
SELECT c FROM t1
WHERE a = 2 OR b = 'three' OR a = 4 OR b = 'five' OR a = 6
ORDER BY rowid
}
} {II III IV V VI 0 0 15}
do_test where8-1.14 {
execsql_status2 {
SELECT c FROM t1
WHERE
a = 2 OR b = 'three' OR a = 4 OR b = 'five' OR a = 6 OR
b = 'seven' OR a = 8 OR b = 'nine' OR a = 10
ORDER BY rowid
}
} {II III IV V VI VII VIII IX X 0 0 26}
do_test where8-1.15 {
execsql_status2 {
SELECT c FROM t1 WHERE
a BETWEEN 2 AND 4 OR b = 'nine'
ORDER BY rowid
}
} {II III IV IX 0 0 10}
#--------------------------------------------------------------------------
# Tests where8-2.*: Virtual tables
#
if 0 {
ifcapable vtab {
# Register the 'echo' module used for testing virtual tables.
#
register_echo_module [sqlite3_connection_pointer db]
do_test where8-2.1 {
execsql {
CREATE VIRTUAL TABLE e1 USING echo(t1);
SELECT b FROM e1;
}
} {one two three four five six seven eight nine ten}
do_test where8-2.2.1 {
set echo_module ""
execsql {
SELECT c FROM e1 WHERE a=1 OR b='three';
}
} {I III}
do_test where8-2.2.2 {
set echo_module
} {TODO: What should this be?}
}
}
#--------------------------------------------------------------------------
# Tests where8-3.*: Cases with multiple tables in the FROM clause.
#
do_test where8-3.1 {
execsql {
CREATE TABLE t2(d, e, f);
CREATE INDEX i3 ON t2(d);
CREATE INDEX i4 ON t2(e);
INSERT INTO t2 VALUES(1, NULL, 'I');
INSERT INTO t2 VALUES(2, 'four', 'IV');
INSERT INTO t2 VALUES(3, NULL, 'IX');
INSERT INTO t2 VALUES(4, 'sixteen', 'XVI');
INSERT INTO t2 VALUES(5, NULL, 'XXV');
INSERT INTO t2 VALUES(6, 'thirtysix', 'XXXVI');
INSERT INTO t2 VALUES(7, 'fortynine', 'XLIX');
INSERT INTO t2 VALUES(8, 'sixtyeight', 'LXIV');
INSERT INTO t2 VALUES(9, 'eightyone', 'LXXXIX');
INSERT INTO t2 VALUES(10, NULL, 'C');
}
} {}
do_test where8-3.2 {
execsql_status {
SELECT a, d FROM t1, t2 WHERE b=e
}
} {4 2 9 0}
do_test where8-3.3 {
execsql_status {
SELECT a, d FROM t1, t2 WHERE (a = 2 OR a = 3) AND d = 6
}
} {2 6 3 6 0 0}
do_test where8-3.4 {
execsql_status {
SELECT a, d FROM t1, t2 WHERE (a = 2 OR a = 3) AND d = a
}
} {2 2 3 3 0 0}
do_test where8-3.5 {
execsql_status {
SELECT a, d FROM t1, t2 WHERE (a = 2 OR a = 3) AND (d = a OR e = 'sixteen')
}
} {2 2 2 4 3 3 3 4 0 0}
do_test where8-3.6 {
# The first part of the WHERE clause in this query, (a=2 OR a=3) is
# transformed into "a IN (2, 3)". This is why the sort is required.
#
execsql_status {
SELECT a, d
FROM t1, t2
WHERE (a = 2 OR a = 3) AND (d = a OR e = 'sixteen')
ORDER BY t1.rowid
}
} {2 2 2 4 3 3 3 4 0 1}
do_test where8-3.7 {
execsql_status {
SELECT a, d
FROM t1, t2
WHERE a = 2 AND (d = a OR e = 'sixteen')
ORDER BY t1.rowid
}
} {2 2 2 4 0 0}
do_test where8-3.8 {
execsql_status {
SELECT a, d
FROM t1, t2
WHERE (a = 2 OR b = 'three') AND (d = a OR e = 'sixteen')
ORDER BY t1.rowid
}
} {2 2 2 4 3 3 3 4 0 0}
do_test where8-3.9 {
# The "OR c = 'IX'" term forces a linear scan.
execsql_status {
SELECT a, d
FROM t1, t2
WHERE (a = 2 OR b = 'three' OR c = 'IX') AND (d = a OR e = 'sixteen')
ORDER BY t1.rowid
}
} {2 2 2 4 3 3 3 4 9 4 9 9 9 0}
do_test where8-3.10 {
execsql_status {
SELECT d FROM t2 WHERE e IS NULL OR e = 'four'
}
} {1 2 3 5 10 0 0}
do_test where8-3.11 {
execsql_status {
SELECT a, d FROM t1, t2 WHERE (a=d OR b=e) AND a<5 ORDER BY a
}
} {1 1 2 2 3 3 4 2 4 4 0 0}
do_test where8-3.12 {
execsql_status {
SELECT a, d FROM t1, t2 WHERE (a=d OR b=e) AND +a<5 ORDER BY a
}
} {1 1 2 2 3 3 4 2 4 4 0 0}
do_test where8-3.13 {
execsql_status {
SELECT a, d FROM t1, t2 WHERE (a=d OR b=e) AND +a<5
}
} {1 1 2 2 3 3 4 2 4 4 9 0}
do_test where8-3.14 {
execsql_status {
SELECT c FROM t1 WHERE a > (SELECT d FROM t2 WHERE e = b) OR a = 5
}
} {IV V 9 0}
do_test where8-3.15 {
execsql_status {
SELECT c FROM t1, t2 WHERE a BETWEEN 1 AND 2 OR a = (
SELECT sum(e IS NULL) FROM t2 AS inner WHERE t2.d>inner.d
)
}
} {I I I I I I I I I I II II II II II II II II II II III III III III III 99 0}
#-----------------------------------------------------------------------
# The following tests - where8-4.* - verify that adding or removing
# indexes does not change the results returned by various queries.
#
do_test where8-4.1 {
execsql {
CREATE TABLE t3(a INTEGER, b REAL, c TEXT);
CREATE TABLE t4(f INTEGER, g REAL, h TEXT);
}
} {}
finish_test