~ubuntu-branches/ubuntu/maverick/sqlite3/maverick-updates

« back to all changes in this revision

Viewing changes to test/where2.test

  • Committer: Bazaar Package Importer
  • Author(s): Otavio Salvador
  • Date: 2007-03-06 08:53:43 UTC
  • mfrom: (3.1.5 feisty)
  • Revision ID: james.westby@ubuntu.com-20070306085343-658sxlyhl4behigh
Tags: 3.3.8-1.1
* NMU
* Revert PRAGMA table_info format change on a minor version release
  (closes: #397531)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# 2005 July 28
 
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 use of indices in WHERE clauses
 
13
# based on recent changes to the optimizer.
 
14
#
 
15
# $Id: where2.test,v 1.9 2006/05/11 13:26:26 drh Exp $
 
16
 
 
17
set testdir [file dirname $argv0]
 
18
source $testdir/tester.tcl
 
19
 
 
20
# Build some test data
 
21
#
 
22
do_test where2-1.0 {
 
23
  execsql {
 
24
    BEGIN;
 
25
    CREATE TABLE t1(w int, x int, y int, z int);
 
26
  }
 
27
  for {set i 1} {$i<=100} {incr i} {
 
28
    set w $i
 
29
    set x [expr {int(log($i)/log(2))}]
 
30
    set y [expr {$i*$i + 2*$i + 1}]
 
31
    set z [expr {$x+$y}]
 
32
    ifcapable tclvar {
 
33
      execsql {INSERT INTO t1 VALUES($::w,$::x,$::y,$::z)}
 
34
    } else {
 
35
      execsql {INSERT INTO t1 VALUES(:w,:x,:y,:z)}
 
36
    }
 
37
  }
 
38
  execsql {
 
39
    CREATE UNIQUE INDEX i1w ON t1(w);
 
40
    CREATE INDEX i1xy ON t1(x,y);
 
41
    CREATE INDEX i1zyx ON t1(z,y,x);
 
42
    COMMIT;
 
43
  }
 
44
} {}
 
45
 
 
46
# Do an SQL statement.  Append the search count to the end of the result.
 
47
#
 
48
proc count sql {
 
49
  set ::sqlite_search_count 0
 
50
  return [concat [execsql $sql] $::sqlite_search_count]
 
51
}
 
52
 
 
53
# This procedure executes the SQL.  Then it checks to see if the OP_Sort
 
54
# opcode was executed.  If an OP_Sort did occur, then "sort" is appended
 
55
# to the result.  If no OP_Sort happened, then "nosort" is appended.
 
56
#
 
57
# This procedure is used to check to make sure sorting is or is not
 
58
# occurring as expected.
 
59
#
 
60
proc cksort {sql} {
 
61
  set ::sqlite_sort_count 0
 
62
  set data [execsql $sql]
 
63
  if {$::sqlite_sort_count} {set x sort} {set x nosort}
 
64
  lappend data $x
 
65
  return $data
 
66
}
 
67
 
 
68
# This procedure executes the SQL.  Then it appends to the result the
 
69
# "sort" or "nosort" keyword (as in the cksort procedure above) then
 
70
# it appends the ::sqlite_query_plan variable.
 
71
#
 
72
proc queryplan {sql} {
 
73
  set ::sqlite_sort_count 0
 
74
  set data [execsql $sql]
 
75
  if {$::sqlite_sort_count} {set x sort} {set x nosort}
 
76
  lappend data $x
 
77
  return [concat $data $::sqlite_query_plan]
 
78
}
 
79
 
 
80
 
 
81
# Prefer a UNIQUE index over another index.
 
82
#
 
83
do_test where2-1.1 {
 
84
  queryplan {
 
85
    SELECT * FROM t1 WHERE w=85 AND x=6 AND y=7396
 
86
  }
 
87
} {85 6 7396 7402 nosort t1 i1w}
 
88
 
 
89
# Always prefer a rowid== constraint over any other index.
 
90
#
 
91
do_test where2-1.3 {
 
92
  queryplan {
 
93
    SELECT * FROM t1 WHERE w=85 AND x=6 AND y=7396 AND rowid=85
 
94
  }
 
95
} {85 6 7396 7402 nosort t1 *}
 
96
 
 
97
# When constrained by a UNIQUE index, the ORDER BY clause is always ignored.
 
98
#
 
99
do_test where2-2.1 {
 
100
  queryplan {
 
101
    SELECT * FROM t1 WHERE w=85 ORDER BY random(5);
 
102
  }
 
103
} {85 6 7396 7402 nosort t1 i1w}
 
104
do_test where2-2.2 {
 
105
  queryplan {
 
106
    SELECT * FROM t1 WHERE x=6 AND y=7396 ORDER BY random(5);
 
107
  }
 
108
} {85 6 7396 7402 sort t1 i1xy}
 
109
do_test where2-2.3 {
 
110
  queryplan {
 
111
    SELECT * FROM t1 WHERE rowid=85 AND x=6 AND y=7396 ORDER BY random(5);
 
112
  }
 
113
} {85 6 7396 7402 nosort t1 *}
 
114
 
 
115
 
 
116
# Efficient handling of forward and reverse table scans.
 
117
#
 
118
do_test where2-3.1 {
 
119
  queryplan {
 
120
    SELECT * FROM t1 ORDER BY rowid LIMIT 2
 
121
  }
 
122
} {1 0 4 4 2 1 9 10 nosort t1 *}
 
123
do_test where2-3.2 {
 
124
  queryplan {
 
125
    SELECT * FROM t1 ORDER BY rowid DESC LIMIT 2
 
126
  }
 
127
} {100 6 10201 10207 99 6 10000 10006 nosort t1 *}
 
128
 
 
129
# The IN operator can be used by indices at multiple layers
 
130
#
 
131
ifcapable subquery {
 
132
  do_test where2-4.1 {
 
133
    queryplan {
 
134
      SELECT * FROM t1 WHERE z IN (10207,10006) AND y IN (10000,10201)
 
135
                       AND x>0 AND x<10
 
136
      ORDER BY w
 
137
    }
 
138
  } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
 
139
  do_test where2-4.2 {
 
140
    queryplan {
 
141
      SELECT * FROM t1 WHERE z IN (10207,10006) AND y=10000
 
142
                       AND x>0 AND x<10
 
143
      ORDER BY w
 
144
    }
 
145
  } {99 6 10000 10006 sort t1 i1zyx}
 
146
  do_test where2-4.3 {
 
147
    queryplan {
 
148
      SELECT * FROM t1 WHERE z=10006 AND y IN (10000,10201)
 
149
                       AND x>0 AND x<10
 
150
      ORDER BY w
 
151
    }
 
152
  } {99 6 10000 10006 sort t1 i1zyx}
 
153
  ifcapable compound {
 
154
    do_test where2-4.4 {
 
155
      queryplan {
 
156
        SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006)
 
157
                         AND y IN (10000,10201)
 
158
                         AND x>0 AND x<10
 
159
        ORDER BY w
 
160
      }
 
161
    } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
 
162
    do_test where2-4.5 {
 
163
      queryplan {
 
164
        SELECT * FROM t1 WHERE z IN (SELECT 10207 UNION SELECT 10006)
 
165
                         AND y IN (SELECT 10000 UNION SELECT 10201)
 
166
                         AND x>0 AND x<10
 
167
        ORDER BY w
 
168
      }
 
169
    } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
 
170
  }
 
171
  do_test where2-4.6 {
 
172
    queryplan {
 
173
      SELECT * FROM t1
 
174
       WHERE x IN (1,2,3,4,5,6,7,8)
 
175
         AND y IN (10000,10001,10002,10003,10004,10005)
 
176
       ORDER BY 2
 
177
    }
 
178
  } {99 6 10000 10006 sort t1 i1xy}
 
179
 
 
180
  # Duplicate entires on the RHS of an IN operator do not cause duplicate
 
181
  # output rows.
 
182
  #
 
183
  do_test where2-4.6 {
 
184
    queryplan {
 
185
      SELECT * FROM t1 WHERE z IN (10207,10006,10006,10207)
 
186
      ORDER BY w
 
187
    }
 
188
  } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
 
189
  ifcapable compound {
 
190
    do_test where2-4.7 {
 
191
      queryplan {
 
192
        SELECT * FROM t1 WHERE z IN (
 
193
           SELECT 10207 UNION ALL SELECT 10006
 
194
           UNION ALL SELECT 10006 UNION ALL SELECT 10207)
 
195
        ORDER BY w
 
196
      }
 
197
    } {99 6 10000 10006 100 6 10201 10207 sort t1 i1zyx}
 
198
  }
 
199
 
 
200
} ;# ifcapable subquery
 
201
 
 
202
# The use of an IN operator disables the index as a sorter.
 
203
#
 
204
do_test where2-5.1 {
 
205
  queryplan {
 
206
    SELECT * FROM t1 WHERE w=99 ORDER BY w
 
207
  }
 
208
} {99 6 10000 10006 nosort t1 i1w}
 
209
 
 
210
ifcapable subquery {
 
211
  do_test where2-5.2 {
 
212
    queryplan {
 
213
      SELECT * FROM t1 WHERE w IN (99) ORDER BY w
 
214
    }
 
215
  } {99 6 10000 10006 sort t1 i1w}
 
216
}
 
217
 
 
218
# Verify that OR clauses get translated into IN operators.
 
219
#
 
220
set ::idx {}
 
221
ifcapable subquery {set ::idx i1w}
 
222
do_test where2-6.1 {
 
223
  queryplan {
 
224
    SELECT * FROM t1 WHERE w=99 OR w=100 ORDER BY +w
 
225
  }
 
226
} [list 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]
 
227
do_test where2-6.2 {
 
228
  queryplan {
 
229
    SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=w ORDER BY +w
 
230
  }
 
231
} [list 6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 $::idx]
 
232
 
 
233
do_test where2-6.3 {
 
234
  queryplan {
 
235
    SELECT * FROM t1 WHERE w=99 OR w=100 OR 6=+w ORDER BY +w
 
236
  }
 
237
} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}}
 
238
do_test where2-6.4 {
 
239
  queryplan {
 
240
    SELECT * FROM t1 WHERE w=99 OR +w=100 OR 6=w ORDER BY +w
 
241
  }
 
242
} {6 2 49 51 99 6 10000 10006 100 6 10201 10207 sort t1 {}}
 
243
 
 
244
set ::idx {}
 
245
ifcapable subquery {set ::idx i1zyx}
 
246
do_test where2-6.5 {
 
247
  queryplan {
 
248
    SELECT b.* FROM t1 a, t1 b
 
249
     WHERE a.w=1 AND (a.y=b.z OR b.z=10)
 
250
     ORDER BY +b.w
 
251
  }
 
252
} [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx]
 
253
do_test where2-6.6 {
 
254
  queryplan {
 
255
    SELECT b.* FROM t1 a, t1 b
 
256
     WHERE a.w=1 AND (b.z=10 OR a.y=b.z OR b.z=10)
 
257
     ORDER BY +b.w
 
258
  }
 
259
} [list 1 0 4 4 2 1 9 10 sort a i1w b $::idx]
 
260
 
 
261
# Unique queries (queries that are guaranteed to return only a single
 
262
# row of result) do not call the sorter.  But all tables must give
 
263
# a unique result.  If any one table in the join does not give a unique
 
264
# result then sorting is necessary.
 
265
#
 
266
do_test where2-7.1 {
 
267
  cksort {
 
268
    create table t8(a unique, b, c);
 
269
    insert into t8 values(1,2,3);
 
270
    insert into t8 values(2,3,4);
 
271
    create table t9(x,y);
 
272
    insert into t9 values(2,4);
 
273
    insert into t9 values(2,3);
 
274
    select y from t8, t9 where a=1 order by a, y;
 
275
  }
 
276
} {3 4 sort}
 
277
do_test where2-7.2 {
 
278
  cksort {
 
279
    select * from t8 where a=1 order by b, c
 
280
  }
 
281
} {1 2 3 nosort}
 
282
do_test where2-7.3 {
 
283
  cksort {
 
284
    select * from t8, t9 where a=1 and y=3 order by b, x
 
285
  }
 
286
} {1 2 3 2 3 sort}
 
287
do_test where2-7.4 {
 
288
  cksort {
 
289
    create unique index i9y on t9(y);
 
290
    select * from t8, t9 where a=1 and y=3 order by b, x
 
291
  }
 
292
} {1 2 3 2 3 nosort}
 
293
 
 
294
# Ticket #1807.  Using IN constrains on multiple columns of
 
295
# a multi-column index.
 
296
#
 
297
ifcapable subquery {
 
298
  do_test where2-8.1 {
 
299
    execsql {
 
300
      SELECT * FROM t1 WHERE x IN (20,21) AND y IN (1,2)
 
301
    }
 
302
  } {}
 
303
  do_test where2-8.2 {
 
304
    execsql {
 
305
      SELECT * FROM t1 WHERE x IN (1,2) AND y IN (-5,-6)
 
306
    }
 
307
  } {}
 
308
  execsql {CREATE TABLE tx AS SELECT * FROM t1}
 
309
  do_test where2-8.3 {
 
310
    execsql {
 
311
      SELECT w FROM t1
 
312
       WHERE x IN (SELECT x FROM tx WHERE rowid<0)
 
313
         AND +y IN (SELECT y FROM tx WHERE rowid=1)
 
314
    }
 
315
  } {}
 
316
  do_test where2-8.4 {
 
317
    execsql {
 
318
      SELECT w FROM t1
 
319
       WHERE x IN (SELECT x FROM tx WHERE rowid=1)
 
320
         AND y IN (SELECT y FROM tx WHERE rowid<0)
 
321
    }
 
322
  } {}
 
323
  #set sqlite_where_trace 1
 
324
  do_test where2-8.5 {
 
325
    execsql {
 
326
      CREATE INDEX tx_xyz ON tx(x, y, z, w);
 
327
      SELECT w FROM tx
 
328
       WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
 
329
         AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
 
330
         AND z IN (SELECT z FROM t1 WHERE w BETWEEN 12 AND 14)
 
331
    }
 
332
  } {12 13 14}
 
333
  do_test where2-8.6 {
 
334
    execsql {
 
335
      SELECT w FROM tx
 
336
       WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
 
337
         AND y IN (SELECT y FROM t1 WHERE w BETWEEN 12 AND 14)
 
338
         AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
 
339
    }
 
340
  } {12 13 14}
 
341
  do_test where2-8.7 {
 
342
    execsql {
 
343
      SELECT w FROM tx
 
344
       WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 12 AND 14)
 
345
         AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
 
346
         AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
 
347
    }
 
348
  } {10 11 12 13 14 15}
 
349
  do_test where2-8.8 {
 
350
    execsql {
 
351
      SELECT w FROM tx
 
352
       WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
 
353
         AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
 
354
         AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
 
355
    }
 
356
  } {10 11 12 13 14 15 16 17 18 19 20}
 
357
  do_test where2-8.9 {
 
358
    execsql {
 
359
      SELECT w FROM tx
 
360
       WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
 
361
         AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
 
362
         AND z IN (SELECT z FROM t1 WHERE w BETWEEN 2 AND 4)
 
363
    }
 
364
  } {}
 
365
  do_test where2-8.10 {
 
366
    execsql {
 
367
      SELECT w FROM tx
 
368
       WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
 
369
         AND y IN (SELECT y FROM t1 WHERE w BETWEEN 2 AND 4)
 
370
         AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
 
371
    }
 
372
  } {}
 
373
  do_test where2-8.11 {
 
374
    execsql {
 
375
      SELECT w FROM tx
 
376
       WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 2 AND 4)
 
377
         AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
 
378
         AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
 
379
    }
 
380
  } {}
 
381
  do_test where2-8.12 {
 
382
    execsql {
 
383
      SELECT w FROM tx
 
384
       WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
 
385
         AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
 
386
         AND z IN (SELECT z FROM t1 WHERE w BETWEEN -4 AND -2)
 
387
    }
 
388
  } {}
 
389
  do_test where2-8.13 {
 
390
    execsql {
 
391
      SELECT w FROM tx
 
392
       WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
 
393
         AND y IN (SELECT y FROM t1 WHERE w BETWEEN -4 AND -2)
 
394
         AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
 
395
    }
 
396
  } {}
 
397
  do_test where2-8.14 {
 
398
    execsql {
 
399
      SELECT w FROM tx
 
400
       WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN -4 AND -2)
 
401
         AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
 
402
         AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
 
403
    }
 
404
  } {}
 
405
  do_test where2-8.15 {
 
406
    execsql {
 
407
      SELECT w FROM tx
 
408
       WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
 
409
         AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
 
410
         AND z IN (SELECT z FROM t1 WHERE w BETWEEN 200 AND 300)
 
411
    }
 
412
  } {}
 
413
  do_test where2-8.16 {
 
414
    execsql {
 
415
      SELECT w FROM tx
 
416
       WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 10 AND 20)
 
417
         AND y IN (SELECT y FROM t1 WHERE w BETWEEN 200 AND 300)
 
418
         AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
 
419
    }
 
420
  } {}
 
421
  do_test where2-8.17 {
 
422
    execsql {
 
423
      SELECT w FROM tx
 
424
       WHERE x IN (SELECT x FROM t1 WHERE w BETWEEN 200 AND 300)
 
425
         AND y IN (SELECT y FROM t1 WHERE w BETWEEN 10 AND 20)
 
426
         AND z IN (SELECT z FROM t1 WHERE w BETWEEN 10 AND 20)
 
427
    }
 
428
  } {}
 
429
  do_test where2-8.18 {
 
430
    execsql {
 
431
      SELECT w FROM tx
 
432
       WHERE x IN (SELECT x FROM t1 WHERE +w BETWEEN 10 AND 20)
 
433
         AND y IN (SELECT y FROM t1 WHERE +w BETWEEN 10 AND 20)
 
434
         AND z IN (SELECT z FROM t1 WHERE +w BETWEEN 200 AND 300)
 
435
    }
 
436
  } {}
 
437
  do_test where2-8.19 {
 
438
    execsql {
 
439
      SELECT w FROM tx
 
440
       WHERE x IN (SELECT x FROM t1 WHERE +w BETWEEN 10 AND 20)
 
441
         AND y IN (SELECT y FROM t1 WHERE +w BETWEEN 200 AND 300)
 
442
         AND z IN (SELECT z FROM t1 WHERE +w BETWEEN 10 AND 20)
 
443
    }
 
444
  } {}
 
445
  do_test where2-8.20 {
 
446
    execsql {
 
447
      SELECT w FROM tx
 
448
       WHERE x IN (SELECT x FROM t1 WHERE +w BETWEEN 200 AND 300)
 
449
         AND y IN (SELECT y FROM t1 WHERE +w BETWEEN 10 AND 20)
 
450
         AND z IN (SELECT z FROM t1 WHERE +w BETWEEN 10 AND 20)
 
451
    }
 
452
  } {}
 
453
}  
 
454
finish_test