xref: /sqlite-3.40.0/test/where3.test (revision f2fcd075)
1# 2006 January 31
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 file is testing the join reordering optimization
13# in cases that include a LEFT JOIN.
14#
15# $Id: where3.test,v 1.4 2008/04/17 19:14:02 drh Exp $
16
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19
20# The following is from ticket #1652.
21#
22# A comma join then a left outer join:  A,B left join C.
23# Arrange indices so that the B table is chosen to go first.
24# Also put an index on C, but make sure that A is chosen before C.
25#
26do_test where3-1.1 {
27  execsql {
28    CREATE TABLE t1(a, b);
29    CREATE TABLE t2(p, q);
30    CREATE TABLE t3(x, y);
31
32    INSERT INTO t1 VALUES(111,'one');
33    INSERT INTO t1 VALUES(222,'two');
34    INSERT INTO t1 VALUES(333,'three');
35
36    INSERT INTO t2 VALUES(1,111);
37    INSERT INTO t2 VALUES(2,222);
38    INSERT INTO t2 VALUES(4,444);
39    CREATE INDEX t2i1 ON t2(p);
40
41    INSERT INTO t3 VALUES(999,'nine');
42    CREATE INDEX t3i1 ON t3(x);
43
44    SELECT * FROM t1, t2 LEFT JOIN t3 ON q=x WHERE p=2 AND a=q;
45  }
46} {222 two 2 222 {} {}}
47
48ifcapable explain {
49  do_test where3-1.1.1 {
50     explain_no_trace {SELECT * FROM t1, t2 LEFT JOIN t3 ON q=x
51                        WHERE p=2 AND a=q}
52  } [explain_no_trace {SELECT * FROM t1, t2 LEFT JOIN t3 ON x=q
53                        WHERE p=2 AND a=q}]
54}
55
56# Ticket #1830
57#
58# This is similar to the above but with the LEFT JOIN on the
59# other side.
60#
61do_test where3-1.2 {
62  execsql {
63    CREATE TABLE parent1(parent1key, child1key, Child2key, child3key);
64    CREATE TABLE child1 ( child1key NVARCHAR, value NVARCHAR );
65    CREATE UNIQUE INDEX PKIDXChild1 ON child1 ( child1key );
66    CREATE TABLE child2 ( child2key NVARCHAR, value NVARCHAR );
67
68    INSERT INTO parent1(parent1key,child1key,child2key)
69       VALUES ( 1, 'C1.1', 'C2.1' );
70    INSERT INTO child1 ( child1key, value ) VALUES ( 'C1.1', 'Value for C1.1' );
71    INSERT INTO child2 ( child2key, value ) VALUES ( 'C2.1', 'Value for C2.1' );
72
73    INSERT INTO parent1 ( parent1key, child1key, child2key )
74       VALUES ( 2, 'C1.2', 'C2.2' );
75    INSERT INTO child2 ( child2key, value ) VALUES ( 'C2.2', 'Value for C2.2' );
76
77    INSERT INTO parent1 ( parent1key, child1key, child2key )
78       VALUES ( 3, 'C1.3', 'C2.3' );
79    INSERT INTO child1 ( child1key, value ) VALUES ( 'C1.3', 'Value for C1.3' );
80    INSERT INTO child2 ( child2key, value ) VALUES ( 'C2.3', 'Value for C2.3' );
81
82    SELECT parent1.parent1key, child1.value, child2.value
83    FROM parent1
84    LEFT OUTER JOIN child1 ON child1.child1key = parent1.child1key
85    INNER JOIN child2 ON child2.child2key = parent1.child2key;
86  }
87} {1 {Value for C1.1} {Value for C2.1} 2 {} {Value for C2.2} 3 {Value for C1.3} {Value for C2.3}}
88
89ifcapable explain {
90  do_test where3-1.2.1 {
91     explain_no_trace {
92       SELECT parent1.parent1key, child1.value, child2.value
93       FROM parent1
94       LEFT OUTER JOIN child1 ON child1.child1key = parent1.child1key
95       INNER JOIN child2 ON child2.child2key = parent1.child2key;
96     }
97  } [explain_no_trace {
98       SELECT parent1.parent1key, child1.value, child2.value
99       FROM parent1
100       LEFT OUTER JOIN child1 ON parent1.child1key = child1.child1key
101       INNER JOIN child2 ON child2.child2key = parent1.child2key;
102     }]
103}
104
105# This procedure executes the SQL.  Then it appends
106# the ::sqlite_query_plan variable.
107#
108proc queryplan {sql} {
109  set ::sqlite_sort_count 0
110  set data [execsql $sql]
111  return [concat $data $::sqlite_query_plan]
112}
113
114
115# If you have a from clause of the form:   A B C left join D
116# then make sure the query optimizer is able to reorder the
117# A B C part anyway it wants.
118#
119# Following the fix to ticket #1652, there was a time when
120# the C table would not reorder.  So the following reorderings
121# were possible:
122#
123#            A B C left join D
124#            B A C left join D
125#
126# But these reorders were not allowed
127#
128#            C A B left join D
129#            A C B left join D
130#            C B A left join D
131#            B C A left join D
132#
133# The following tests are here to verify that the latter four
134# reorderings are allowed again.
135#
136do_test where3-2.1 {
137  execsql {
138    CREATE TABLE tA(apk integer primary key, ax);
139    CREATE TABLE tB(bpk integer primary key, bx);
140    CREATE TABLE tC(cpk integer primary key, cx);
141    CREATE TABLE tD(dpk integer primary key, dx);
142  }
143  queryplan {
144    SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx
145     WHERE cpk=bx AND bpk=ax
146  }
147} {tA {} tB * tC * tD *}
148do_test where3-2.1.1 {
149  queryplan {
150    SELECT * FROM tA, tB, tC LEFT JOIN tD ON cx=dpk
151     WHERE cpk=bx AND bpk=ax
152  }
153} {tA {} tB * tC * tD *}
154do_test where3-2.1.2 {
155  queryplan {
156    SELECT * FROM tA, tB, tC LEFT JOIN tD ON cx=dpk
157     WHERE bx=cpk AND bpk=ax
158  }
159} {tA {} tB * tC * tD *}
160do_test where3-2.1.3 {
161  queryplan {
162    SELECT * FROM tA, tB, tC LEFT JOIN tD ON cx=dpk
163     WHERE bx=cpk AND ax=bpk
164  }
165} {tA {} tB * tC * tD *}
166do_test where3-2.1.4 {
167  queryplan {
168    SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx
169     WHERE bx=cpk AND ax=bpk
170  }
171} {tA {} tB * tC * tD *}
172do_test where3-2.1.5 {
173  queryplan {
174    SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx
175     WHERE cpk=bx AND ax=bpk
176  }
177} {tA {} tB * tC * tD *}
178do_test where3-2.2 {
179  queryplan {
180    SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx
181     WHERE cpk=bx AND apk=bx
182  }
183} {tB {} tA * tC * tD *}
184do_test where3-2.3 {
185  queryplan {
186    SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx
187     WHERE cpk=bx AND apk=bx
188  }
189} {tB {} tA * tC * tD *}
190do_test where3-2.4 {
191  queryplan {
192    SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx
193     WHERE apk=cx AND bpk=ax
194  }
195} {tC {} tA * tB * tD *}
196do_test where3-2.5 {
197  queryplan {
198    SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx
199     WHERE cpk=ax AND bpk=cx
200  }
201} {tA {} tC * tB * tD *}
202do_test where3-2.6 {
203  queryplan {
204    SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx
205     WHERE bpk=cx AND apk=bx
206  }
207} {tC {} tB * tA * tD *}
208do_test where3-2.7 {
209  queryplan {
210    SELECT * FROM tA, tB, tC LEFT JOIN tD ON dpk=cx
211     WHERE cpk=bx AND apk=cx
212  }
213} {tB {} tC * tA * tD *}
214
215# Ticket [13f033c865f878953]
216# If the outer loop must be a full table scan, do not let ANALYZE trick
217# the planner into use a table for the outer loop that might be indexable
218# if held until an inner loop.
219#
220do_test where3-3.0 {
221  execsql {
222    CREATE TABLE t301(a INTEGER PRIMARY KEY,b,c);
223    CREATE INDEX t301c ON t301(c);
224    INSERT INTO t301 VALUES(1,2,3);
225    CREATE TABLE t302(x, y);
226    ANALYZE;
227    explain query plan
228    SELECT * FROM t302, t301 WHERE t302.x=5 AND t301.a=t302.y;
229  }
230} {0 0 {TABLE t302} 1 1 {TABLE t301 USING PRIMARY KEY}}
231do_test where3-3.1 {
232  execsql {
233    explain query plan
234    SELECT * FROM t301, t302 WHERE t302.x=5 AND t301.a=t302.y;
235  }
236} {0 1 {TABLE t302} 1 0 {TABLE t301 USING PRIMARY KEY}}
237
238# Verify that when there are multiple tables in a join which must be
239# full table scans that the query planner attempts put the table with
240# the fewest number of output rows as the outer loop.
241#
242do_test where3-4.0 {
243  execsql {
244    CREATE TABLE t400(a INTEGER PRIMARY KEY, b, c);
245    CREATE TABLE t401(p INTEGER PRIMARY KEY, q, r);
246    CREATE TABLE t402(x INTEGER PRIMARY KEY, y, z);
247    EXPLAIN QUERY PLAN
248    SELECT * FROM t400, t401, t402 WHERE t402.z GLOB 'abc*';
249  }
250} {0 2 {TABLE t402} 1 0 {TABLE t400} 2 1 {TABLE t401}}
251do_test where3-4.1 {
252  execsql {
253    EXPLAIN QUERY PLAN
254    SELECT * FROM t400, t401, t402 WHERE t401.r GLOB 'abc*';
255  }
256} {0 1 {TABLE t401} 1 0 {TABLE t400} 2 2 {TABLE t402}}
257do_test where3-4.2 {
258  execsql {
259    EXPLAIN QUERY PLAN
260    SELECT * FROM t400, t401, t402 WHERE t400.c GLOB 'abc*';
261  }
262} {0 0 {TABLE t400} 1 1 {TABLE t401} 2 2 {TABLE t402}}
263
264finish_test
265