blob: bec3167758bf8a6b140cf3bd86993ab362b6fce8 [file] [log] [blame]
drhb19a2bc2001-09-16 00:13:26 +00001# 2001 September 15
drhc4a3c772001-04-04 11:48:57 +00002#
drhb19a2bc2001-09-16 00:13:26 +00003# The author disclaims copyright to this source code. In place of
4# a legal notice, here is a blessing:
drhc4a3c772001-04-04 11:48:57 +00005#
drhb19a2bc2001-09-16 00:13:26 +00006# 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.
drhc4a3c772001-04-04 11:48:57 +00009#
10#***********************************************************************
11# This file implements regression tests for SQLite library. The
12# focus of this file is testing the magic ROWID column that is
13# found on all tables.
14#
drha0217ba2003-06-01 01:10:33 +000015# $Id: rowid.test,v 1.11 2003/06/01 01:10:33 drh Exp $
drhc4a3c772001-04-04 11:48:57 +000016
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19
20# Basic ROWID functionality tests.
21#
22do_test rowid-1.1 {
23 execsql {
24 CREATE TABLE t1(x int, y int);
25 INSERT INTO t1 VALUES(1,2);
26 INSERT INTO t1 VALUES(3,4);
27 SELECT x FROM t1 ORDER BY y;
28 }
29} {1 3}
30do_test rowid-1.2 {
31 set r [execsql {SELECT rowid FROM t1 ORDER BY x}]
32 global x2rowid rowid2x
33 set x2rowid(1) [lindex $r 0]
34 set x2rowid(3) [lindex $r 1]
35 set rowid2x($x2rowid(1)) 1
36 set rowid2x($x2rowid(3)) 3
37 llength $r
38} {2}
39do_test rowid-1.3 {
40 global x2rowid
41 set sql "SELECT x FROM t1 WHERE rowid==$x2rowid(1)"
42 execsql $sql
43} {1}
44do_test rowid-1.4 {
45 global x2rowid
46 set sql "SELECT x FROM t1 WHERE rowid==$x2rowid(3)"
47 execsql $sql
48} {3}
49do_test rowid-1.5 {
50 global x2rowid
51 set sql "SELECT x FROM t1 WHERE oid==$x2rowid(1)"
52 execsql $sql
53} {1}
54do_test rowid-1.6 {
55 global x2rowid
56 set sql "SELECT x FROM t1 WHERE OID==$x2rowid(3)"
57 execsql $sql
58} {3}
59do_test rowid-1.7 {
60 global x2rowid
61 set sql "SELECT x FROM t1 WHERE _rowid_==$x2rowid(1)"
62 execsql $sql
63} {1}
drh1eaa2692001-09-18 02:02:23 +000064do_test rowid-1.7.1 {
65 while 1 {
66 set norow [expr {int(rand()*1000000)}]
67 if {$norow!=$x2rowid(1) && $norow!=$x2rowid(3)} break
68 }
69 execsql "SELECT x FROM t1 WHERE rowid=$norow"
70} {}
drhc4a3c772001-04-04 11:48:57 +000071do_test rowid-1.8 {
72 global x2rowid
73 set v [execsql {SELECT x, oid FROM t1 order by x}]
74 set v2 [list 1 $x2rowid(1) 3 $x2rowid(3)]
75 expr {$v==$v2}
76} {1}
77do_test rowid-1.9 {
78 global x2rowid
79 set v [execsql {SELECT x, RowID FROM t1 order by x}]
80 set v2 [list 1 $x2rowid(1) 3 $x2rowid(3)]
81 expr {$v==$v2}
82} {1}
83do_test rowid-1.9 {
84 global x2rowid
85 set v [execsql {SELECT x, _rowid_ FROM t1 order by x}]
86 set v2 [list 1 $x2rowid(1) 3 $x2rowid(3)]
87 expr {$v==$v2}
88} {1}
89
drha0217ba2003-06-01 01:10:33 +000090# We can insert or update the ROWID column.
drhc4a3c772001-04-04 11:48:57 +000091#
92do_test rowid-2.1 {
drha0217ba2003-06-01 01:10:33 +000093 catchsql {
94 INSERT INTO t1(rowid,x,y) VALUES(1234,5,6);
95 SELECT rowid, * FROM t1;
96 }
97} {0 {1 1 2 2 3 4 1234 5 6}}
drhc4a3c772001-04-04 11:48:57 +000098do_test rowid-2.2 {
drha0217ba2003-06-01 01:10:33 +000099 catchsql {
100 UPDATE t1 SET rowid=12345 WHERE x==1;
101 SELECT rowid, * FROM t1
102 }
103} {0 {2 3 4 1234 5 6 12345 1 2}}
drhc4a3c772001-04-04 11:48:57 +0000104do_test rowid-2.3 {
drha0217ba2003-06-01 01:10:33 +0000105 catchsql {
106 INSERT INTO t1(y,x,oid) VALUES(8,7,1235);
107 SELECT rowid, * FROM t1 WHERE rowid>1000;
108 }
109} {0 {1234 5 6 1235 7 8 12345 1 2}}
drhc4a3c772001-04-04 11:48:57 +0000110do_test rowid-2.4 {
drha0217ba2003-06-01 01:10:33 +0000111 catchsql {
112 UPDATE t1 SET oid=12346 WHERE x==1;
113 SELECT rowid, * FROM t1;
114 }
115} {0 {2 3 4 1234 5 6 1235 7 8 12346 1 2}}
drhc4a3c772001-04-04 11:48:57 +0000116do_test rowid-2.5 {
drha0217ba2003-06-01 01:10:33 +0000117 catchsql {
118 INSERT INTO t1(x,_rowid_,y) VALUES(9,1236,10);
119 SELECT rowid, * FROM t1 WHERE rowid>1000;
120 }
121} {0 {1234 5 6 1235 7 8 1236 9 10 12346 1 2}}
drhc4a3c772001-04-04 11:48:57 +0000122do_test rowid-2.6 {
drha0217ba2003-06-01 01:10:33 +0000123 catchsql {
124 UPDATE t1 SET _rowid_=12347 WHERE x==1;
125 SELECT rowid, * FROM t1 WHERE rowid>1000;
126 }
127} {0 {1234 5 6 1235 7 8 1236 9 10 12347 1 2}}
drhc4a3c772001-04-04 11:48:57 +0000128
129# But we can use ROWID in the WHERE clause of an UPDATE that does not
130# change the ROWID.
131#
132do_test rowid-2.7 {
133 global x2rowid
134 set sql "UPDATE t1 SET x=2 WHERE OID==$x2rowid(3)"
135 execsql $sql
136 execsql {SELECT x FROM t1 ORDER BY x}
drha0217ba2003-06-01 01:10:33 +0000137} {1 2 5 7 9}
drhc4a3c772001-04-04 11:48:57 +0000138do_test rowid-2.8 {
139 global x2rowid
140 set sql "UPDATE t1 SET x=3 WHERE _rowid_==$x2rowid(3)"
141 execsql $sql
142 execsql {SELECT x FROM t1 ORDER BY x}
drha0217ba2003-06-01 01:10:33 +0000143} {1 3 5 7 9}
drhc4a3c772001-04-04 11:48:57 +0000144
145# We cannot index by ROWID
146#
147do_test rowid-2.9 {
148 set v [catch {execsql {CREATE INDEX idxt1 ON t1(rowid)}} msg]
149 lappend v $msg
150} {1 {table t1 has no column named rowid}}
151do_test rowid-2.10 {
152 set v [catch {execsql {CREATE INDEX idxt1 ON t1(_rowid_)}} msg]
153 lappend v $msg
154} {1 {table t1 has no column named _rowid_}}
155do_test rowid-2.11 {
156 set v [catch {execsql {CREATE INDEX idxt1 ON t1(oid)}} msg]
157 lappend v $msg
158} {1 {table t1 has no column named oid}}
159do_test rowid-2.12 {
160 set v [catch {execsql {CREATE INDEX idxt1 ON t1(x, rowid)}} msg]
161 lappend v $msg
162} {1 {table t1 has no column named rowid}}
163
164# Columns defined in the CREATE statement override the buildin ROWID
165# column names.
166#
167do_test rowid-3.1 {
168 execsql {
169 CREATE TABLE t2(rowid int, x int, y int);
drh5cf8e8c2002-02-19 22:42:05 +0000170 INSERT INTO t2 VALUES(0,2,3);
drhc4a3c772001-04-04 11:48:57 +0000171 INSERT INTO t2 VALUES(4,5,6);
172 INSERT INTO t2 VALUES(7,8,9);
173 SELECT * FROM t2 ORDER BY x;
174 }
drh5cf8e8c2002-02-19 22:42:05 +0000175} {0 2 3 4 5 6 7 8 9}
drhc4a3c772001-04-04 11:48:57 +0000176do_test rowid-3.2 {
177 execsql {SELECT * FROM t2 ORDER BY rowid}
drh5cf8e8c2002-02-19 22:42:05 +0000178} {0 2 3 4 5 6 7 8 9}
drhc4a3c772001-04-04 11:48:57 +0000179do_test rowid-3.3 {
180 execsql {SELECT rowid, x, y FROM t2 ORDER BY rowid}
drh5cf8e8c2002-02-19 22:42:05 +0000181} {0 2 3 4 5 6 7 8 9}
drhc4a3c772001-04-04 11:48:57 +0000182do_test rowid-3.4 {
183 set r1 [execsql {SELECT _rowid_, rowid FROM t2 ORDER BY rowid}]
184 foreach {a b c d e f} $r1 {}
185 set r2 [execsql {SELECT _rowid_, rowid FROM t2 ORDER BY x DESC}]
186 foreach {u v w x y z} $r2 {}
187 expr {$u==$e && $w==$c && $y==$a}
188} {1}
189do_probtest rowid-3.5 {
190 set r1 [execsql {SELECT _rowid_, rowid FROM t2 ORDER BY rowid}]
191 foreach {a b c d e f} $r1 {}
192 expr {$a!=$b && $c!=$d && $e!=$f}
193} {1}
194
195# Let's try some more complex examples, including some joins.
196#
197do_test rowid-4.1 {
198 execsql {
199 DELETE FROM t1;
200 DELETE FROM t2;
201 }
202 for {set i 1} {$i<=50} {incr i} {
203 execsql "INSERT INTO t1(x,y) VALUES($i,[expr {$i*$i}])"
204 }
205 execsql {INSERT INTO t2 SELECT _rowid_, x*y, y*y FROM t1}
206 execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t1.rowid==t2.rowid}
207} {256}
208do_test rowid-4.2 {
209 execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1.rowid==t2.rowid}
210} {256}
211do_test rowid-4.2.1 {
212 execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1.oid==t2.rowid}
213} {256}
214do_test rowid-4.2.2 {
215 execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1._rowid_==t2.rowid}
216} {256}
217do_test rowid-4.2.3 {
218 execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t2.rowid==t1.rowid}
219} {256}
220do_test rowid-4.2.4 {
221 execsql {SELECT t2.y FROM t2, t1 WHERE t2.rowid==t1.oid AND t1.x==4}
222} {256}
223do_test rowid-4.2.5 {
224 execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t1._rowid_==t2.rowid}
225} {256}
226do_test rowid-4.2.6 {
227 execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t2.rowid==t1.rowid}
228} {256}
229do_test rowid-4.2.7 {
230 execsql {SELECT t2.y FROM t1, t2 WHERE t2.rowid==t1.oid AND t1.x==4}
231} {256}
232do_test rowid-4.3 {
233 execsql {CREATE INDEX idxt1 ON t1(x)}
234 execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t1.rowid==t2.rowid}
235} {256}
236do_test rowid-4.3.1 {
237 execsql {SELECT t2.y FROM t1, t2 WHERE t1.x==4 AND t1._rowid_==t2.rowid}
238} {256}
239do_test rowid-4.3.2 {
240 execsql {SELECT t2.y FROM t1, t2 WHERE t2.rowid==t1.oid AND 4==t1.x}
241} {256}
242do_test rowid-4.4 {
243 execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1.rowid==t2.rowid}
244} {256}
245do_test rowid-4.4.1 {
246 execsql {SELECT t2.y FROM t2, t1 WHERE t1.x==4 AND t1._rowid_==t2.rowid}
247} {256}
248do_test rowid-4.4.2 {
249 execsql {SELECT t2.y FROM t2, t1 WHERE t2.rowid==t1.oid AND 4==t1.x}
250} {256}
251do_test rowid-4.5 {
252 execsql {CREATE INDEX idxt2 ON t2(y)}
drh487ab3c2001-11-08 00:45:21 +0000253 set sqlite_search_count 0
254 concat [execsql {
255 SELECT t1.x FROM t2, t1
drhc4a3c772001-04-04 11:48:57 +0000256 WHERE t2.y==256 AND t1.rowid==t2.rowid
drh487ab3c2001-11-08 00:45:21 +0000257 }] $sqlite_search_count
258} {4 3}
drhc4a3c772001-04-04 11:48:57 +0000259do_test rowid-4.5.1 {
drh487ab3c2001-11-08 00:45:21 +0000260 set sqlite_search_count 0
261 concat [execsql {
262 SELECT t1.x FROM t2, t1
drhc4a3c772001-04-04 11:48:57 +0000263 WHERE t1.OID==t2.rowid AND t2.y==81
drh487ab3c2001-11-08 00:45:21 +0000264 }] $sqlite_search_count
265} {3 3}
drhc4a3c772001-04-04 11:48:57 +0000266do_test rowid-4.6 {
267 execsql {
268 SELECT t1.x FROM t1, t2
269 WHERE t2.y==256 AND t1.rowid==t2.rowid
270 }
271} {4}
272
273do_test rowid-5.1 {
274 execsql {DELETE FROM t1 WHERE _rowid_ IN (SELECT oid FROM t1 WHERE x>8)}
275 execsql {SELECT max(x) FROM t1}
276} {8}
drh3543b3e2001-09-15 00:57:59 +0000277
drhc6b52df2002-01-04 03:09:29 +0000278# Make sure a "WHERE rowid=X" clause works when there is no ROWID of X.
279#
280do_test rowid-6.1 {
281 execsql {
282 SELECT x FROM t1
283 }
284} {1 2 3 4 5 6 7 8}
285do_test rowid-6.2 {
drh5cf8e8c2002-02-19 22:42:05 +0000286 for {set ::norow 1} {1} {incr ::norow} {
287 if {[execsql "SELECT x FROM t1 WHERE rowid=$::norow"]==""} break
288 }
drhc6b52df2002-01-04 03:09:29 +0000289 execsql [subst {
290 DELETE FROM t1 WHERE rowid=$::norow
291 }]
292} {}
293do_test rowid-6.3 {
294 execsql {
295 SELECT x FROM t1
296 }
297} {1 2 3 4 5 6 7 8}
298
drh5cf8e8c2002-02-19 22:42:05 +0000299# Beginning with version 2.3.4, SQLite computes rowids of new rows by
300# finding the maximum current rowid and adding one. It falls back to
301# the old random algorithm if the maximum rowid is the largest integer.
302# The following tests are for this new behavior.
303#
304do_test rowid-7.0 {
305 execsql {
306 DELETE FROM t1;
307 DROP TABLE t2;
308 DROP INDEX idxt1;
309 INSERT INTO t1 VALUES(1,2);
310 SELECT rowid, * FROM t1;
311 }
312} {1 1 2}
313do_test rowid-7.1 {
314 execsql {
315 INSERT INTO t1 VALUES(99,100);
316 SELECT rowid,* FROM t1
317 }
318} {1 1 2 2 99 100}
319do_test rowid-7.2 {
320 execsql {
321 CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
322 INSERT INTO t2(b) VALUES(55);
323 SELECT * FROM t2;
324 }
325} {1 55}
326do_test rowid-7.3 {
327 execsql {
328 INSERT INTO t2(b) VALUES(66);
329 SELECT * FROM t2;
330 }
331} {1 55 2 66}
332do_test rowid-7.4 {
333 execsql {
334 INSERT INTO t2(a,b) VALUES(1000000,77);
335 INSERT INTO t2(b) VALUES(88);
336 SELECT * FROM t2;
337 }
338} {1 55 2 66 1000000 77 1000001 88}
339do_test rowid-7.5 {
340 execsql {
341 INSERT INTO t2(a,b) VALUES(2147483647,99);
342 INSERT INTO t2(b) VALUES(11);
343 SELECT b FROM t2 ORDER BY b;
344 }
345} {11 55 66 77 88 99}
346do_test rowid-7.6 {
347 execsql {
348 SELECT b FROM t2 WHERE a NOT IN(1,2,1000000,1000001,2147483647);
349 }
350} {11}
351do_test rowid-7.7 {
352 execsql {
353 INSERT INTO t2(b) VALUES(22);
354 INSERT INTO t2(b) VALUES(33);
355 INSERT INTO t2(b) VALUES(44);
356 INSERT INTO t2(b) VALUES(55);
357 SELECT b FROM t2 WHERE a NOT IN(1,2,1000000,1000001,2147483647) ORDER BY b;
358 }
359} {11 22 33 44 55}
360do_test rowid-7.8 {
361 execsql {
362 DELETE FROM t2 WHERE a!=2;
363 INSERT INTO t2(b) VALUES(111);
364 SELECT * FROM t2;
365 }
366} {2 66 3 111}
drhc6b52df2002-01-04 03:09:29 +0000367
drh49449832003-04-15 14:01:43 +0000368# Make sure AFTER triggers that do INSERTs do not change the last_insert_rowid.
369# Ticket #290
370#
371do_test rowid-8.1 {
372 execsql {
373 CREATE TABLE t3(a integer primary key);
374 CREATE TABLE t4(x);
375 INSERT INTO t4 VALUES(1);
376 CREATE TRIGGER r3 AFTER INSERT on t3 FOR EACH ROW BEGIN
377 INSERT INTO t4 VALUES(NEW.a+10);
378 END;
379 SELECT * FROM t3;
380 }
381} {}
382do_test rowid-8.2 {
383 execsql {
384 SELECT rowid, * FROM t4;
385 }
386} {1 1}
387do_test rowid-8.3 {
388 execsql {
389 INSERT INTO t3 VALUES(123);
390 SELECT last_insert_rowid();
391 }
392} {123}
393do_test rowid-8.4 {
394 execsql {
395 SELECT * FROM t3;
396 }
397} {123}
398do_test rowid-8.5 {
399 execsql {
400 SELECT rowid, * FROM t4;
401 }
402} {1 1 2 133}
403do_test rowid-8.6 {
404 execsql {
405 INSERT INTO t3 VALUES(NULL);
406 SELECT last_insert_rowid();
407 }
408} {124}
409do_test rowid-8.7 {
410 execsql {
411 SELECT * FROM t3;
412 }
413} {123 124}
414do_test rowid-8.8 {
415 execsql {
416 SELECT rowid, * FROM t4;
417 }
drh70ce3f02003-04-15 19:22:22 +0000418} {1 1 2 133 3 134}
drh49449832003-04-15 14:01:43 +0000419
420
drh3543b3e2001-09-15 00:57:59 +0000421finish_test