blob: de025ac61c4720528af01f7d9de8c3823bfab17e [file] [log] [blame]
dancf8f2892018-08-09 20:47:01 +00001# 2009 February 2
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 that SQLite can handle a subtle
13# file format change that may be used in the future to implement
14# "ALTER TABLE ... RENAME COLUMN ... TO".
15#
16# $Id: alter4.test,v 1.1 2009/02/02 18:03:22 drh Exp $
17#
18
19set testdir [file dirname $argv0]
20source $testdir/tester.tcl
21set testprefix altercol
22
23# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
24ifcapable !altertable {
25 finish_test
26 return
27}
28
dan24fedb92018-08-18 17:35:38 +000029# Drop all the tables and views in the 'main' database of database connect
30# [db]. Sort the objects by name before dropping them.
31#
32proc drop_all_tables_and_views {db} {
33 set SQL {
34 SELECT name, type FROM sqlite_master
35 WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%'
36 ORDER BY 1
37 }
38 foreach {z t} [db eval $SQL] {
39 db eval "DROP $t $z"
40 }
41}
42
dancf8f2892018-08-09 20:47:01 +000043foreach {tn before after} {
44 1 {CREATE TABLE t1(a INTEGER, b TEXT, c BLOB)}
45 {CREATE TABLE t1(a INTEGER, d TEXT, c BLOB)}
46
47 2 {CREATE TABLE t1(a INTEGER, x TEXT, "b" BLOB)}
48 {CREATE TABLE t1(a INTEGER, x TEXT, "d" BLOB)}
49
50 3 {CREATE TABLE t1(a INTEGER, b TEXT, c BLOB, CHECK(b!=''))}
51 {CREATE TABLE t1(a INTEGER, d TEXT, c BLOB, CHECK(d!=''))}
52
53 4 {CREATE TABLE t1(a INTEGER, b TEXT, c BLOB, CHECK(t1.b!=''))}
54 {CREATE TABLE t1(a INTEGER, d TEXT, c BLOB, CHECK(t1.d!=''))}
55
56 5 {CREATE TABLE t1(a INTEGER, b TEXT, c BLOB, CHECK( coalesce(b,c) ))}
57 {CREATE TABLE t1(a INTEGER, d TEXT, c BLOB, CHECK( coalesce(d,c) ))}
58
59 6 {CREATE TABLE t1(a INTEGER, "b"TEXT, c BLOB, CHECK( coalesce(b,c) ))}
60 {CREATE TABLE t1(a INTEGER, "d"TEXT, c BLOB, CHECK( coalesce(d,c) ))}
61
62 7 {CREATE TABLE t1(a INTEGER, b TEXT, c BLOB, PRIMARY KEY(b, c))}
63 {CREATE TABLE t1(a INTEGER, d TEXT, c BLOB, PRIMARY KEY(d, c))}
64
65 8 {CREATE TABLE t1(a INTEGER, b TEXT PRIMARY KEY, c BLOB)}
66 {CREATE TABLE t1(a INTEGER, d TEXT PRIMARY KEY, c BLOB)}
67
68 9 {CREATE TABLE t1(a, b TEXT, c, PRIMARY KEY(a, b), UNIQUE("B"))}
69 {CREATE TABLE t1(a, d TEXT, c, PRIMARY KEY(a, d), UNIQUE("d"))}
70
71 10 {CREATE TABLE t1(a, b, c); CREATE INDEX t1i ON t1(a, c)}
72 {{CREATE TABLE t1(a, d, c)} {CREATE INDEX t1i ON t1(a, c)}}
73
74 11 {CREATE TABLE t1(a, b, c); CREATE INDEX t1i ON t1(b, c)}
75 {{CREATE TABLE t1(a, d, c)} {CREATE INDEX t1i ON t1(d, c)}}
76
77 12 {CREATE TABLE t1(a, b, c); CREATE INDEX t1i ON t1(b+b+b+b, c) WHERE b>0}
78 {{CREATE TABLE t1(a, d, c)} {CREATE INDEX t1i ON t1(d+d+d+d, c) WHERE d>0}}
79
80 13 {CREATE TABLE t1(a, b, c, FOREIGN KEY (b) REFERENCES t2)}
81 {CREATE TABLE t1(a, d, c, FOREIGN KEY (d) REFERENCES t2)}
82
dan987db762018-08-14 20:18:50 +000083 14 {CREATE TABLE t1(a INTEGER, b TEXT, c BLOB, PRIMARY KEY(b))}
84 {CREATE TABLE t1(a INTEGER, d TEXT, c BLOB, PRIMARY KEY(d))}
85
86 15 {CREATE TABLE t1(a INTEGER, b INTEGER, c BLOB, PRIMARY KEY(b))}
87 {CREATE TABLE t1(a INTEGER, d INTEGER, c BLOB, PRIMARY KEY(d))}
88
89 16 {CREATE TABLE t1(a INTEGER, b INTEGER PRIMARY KEY, c BLOB)}
90 {CREATE TABLE t1(a INTEGER, d INTEGER PRIMARY KEY, c BLOB)}
91
danf62e8932018-08-14 21:03:38 +000092 17 {CREATE TABLE t1(a INTEGER, b INTEGER PRIMARY KEY, c BLOB, FOREIGN KEY (b) REFERENCES t2)}
93 {CREATE TABLE t1(a INTEGER, d INTEGER PRIMARY KEY, c BLOB, FOREIGN KEY (d) REFERENCES t2)}
94
dancf8f2892018-08-09 20:47:01 +000095} {
96 reset_db
97 do_execsql_test 1.$tn.0 $before
98
99 do_execsql_test 1.$tn.1 {
100 INSERT INTO t1 VALUES(1, 2, 3);
101 }
102
103 do_execsql_test 1.$tn.2 {
104 ALTER TABLE t1 RENAME COLUMN b TO d;
105 }
106
107 do_execsql_test 1.$tn.3 {
108 SELECT * FROM t1;
109 } {1 2 3}
110
111 if {[string first INDEX $before]>0} {
112 set res $after
113 } else {
114 set res [list $after]
115 }
116 do_execsql_test 1.$tn.4 {
117 SELECT sql FROM sqlite_master WHERE tbl_name='t1' AND sql!=''
118 } $res
119}
120
dane9a2fa32018-08-10 14:23:41 +0000121#-------------------------------------------------------------------------
dan6fe7f232018-08-10 19:19:33 +0000122#
dane9a2fa32018-08-10 14:23:41 +0000123do_execsql_test 2.0 {
124 CREATE TABLE t3(a, b, c, d, e, f, g, h, i, j, k, l, m, FOREIGN KEY (b, c, d, e, f, g, h, i, j, k, l, m) REFERENCES t4);
125}
126
dan5da06d32018-08-10 20:19:34 +0000127sqlite3 db2 test.db
128do_execsql_test -db db2 2.1 { SELECT b FROM t3 }
129
130do_execsql_test 2.2 {
dane9a2fa32018-08-10 14:23:41 +0000131 ALTER TABLE t3 RENAME b TO biglongname;
132 SELECT sql FROM sqlite_master WHERE name='t3';
133} {{CREATE TABLE t3(a, biglongname, c, d, e, f, g, h, i, j, k, l, m, FOREIGN KEY (biglongname, c, d, e, f, g, h, i, j, k, l, m) REFERENCES t4)}}
134
dan5da06d32018-08-10 20:19:34 +0000135do_execsql_test -db db2 2.3 { SELECT biglongname FROM t3 }
dancf8f2892018-08-09 20:47:01 +0000136
dan6fe7f232018-08-10 19:19:33 +0000137#-------------------------------------------------------------------------
138#
139do_execsql_test 3.0 {
140 CREATE TABLE t4(x, y, z);
141 CREATE TRIGGER ttt AFTER INSERT ON t4 WHEN new.y<0 BEGIN
dan5be60c52018-08-15 20:28:39 +0000142 SELECT x, y, z FROM t4;
143 DELETE FROM t4 WHERE y=32;
144 UPDATE t4 SET x=y+1, y=0 WHERE y=32;
145 INSERT INTO t4(x, y, z) SELECT 4, 5, 6 WHERE 0;
dan6fe7f232018-08-10 19:19:33 +0000146 END;
147 INSERT INTO t4 VALUES(3, 2, 1);
148}
149
150do_execsql_test 3.1 {
151 ALTER TABLE t4 RENAME y TO abc;
152 SELECT sql FROM sqlite_master WHERE name='t4';
153} {{CREATE TABLE t4(x, abc, z)}}
154
dan6fe7f232018-08-10 19:19:33 +0000155do_execsql_test 3.2 {
156 SELECT * FROM t4;
157} {3 2 1}
158
dan5496d6a2018-08-13 17:14:26 +0000159do_execsql_test 3.3 { INSERT INTO t4 VALUES(6, 5, 4); } {}
dan6fe7f232018-08-10 19:19:33 +0000160
dan5be60c52018-08-15 20:28:39 +0000161do_execsql_test 3.4 { SELECT sql FROM sqlite_master WHERE type='trigger' } {
162{CREATE TRIGGER ttt AFTER INSERT ON t4 WHEN new.abc<0 BEGIN
163 SELECT x, abc, z FROM t4;
164 DELETE FROM t4 WHERE abc=32;
165 UPDATE t4 SET x=abc+1, abc=0 WHERE abc=32;
166 INSERT INTO t4(x, abc, z) SELECT 4, 5, 6 WHERE 0;
167 END}
168}
169
dan6fe7f232018-08-10 19:19:33 +0000170#-------------------------------------------------------------------------
171#
172do_execsql_test 4.0 {
173 CREATE TABLE c1(a, b, FOREIGN KEY (a, b) REFERENCES p1(c, d));
174 CREATE TABLE p1(c, d, PRIMARY KEY(c, d));
175 PRAGMA foreign_keys = 1;
176 INSERT INTO p1 VALUES(1, 2);
177 INSERT INTO p1 VALUES(3, 4);
178}
179
180do_execsql_test 4.1 {
181 ALTER TABLE p1 RENAME d TO "silly name";
182 SELECT sql FROM sqlite_master WHERE name IN ('c1', 'p1');
183} {
184 {CREATE TABLE c1(a, b, FOREIGN KEY (a, b) REFERENCES p1(c, "silly name"))}
185 {CREATE TABLE p1(c, "silly name", PRIMARY KEY(c, "silly name"))}
186}
187
dane325ffe2018-08-11 13:40:20 +0000188do_execsql_test 4.2 { INSERT INTO c1 VALUES(1, 2); }
dan5da06d32018-08-10 20:19:34 +0000189
190do_execsql_test 4.3 {
dan6fe7f232018-08-10 19:19:33 +0000191 CREATE TABLE c2(a, b, FOREIGN KEY (a, b) REFERENCES p1);
192}
193
dan5da06d32018-08-10 20:19:34 +0000194do_execsql_test 4.4 {
dan6fe7f232018-08-10 19:19:33 +0000195 ALTER TABLE p1 RENAME "silly name" TO reasonable;
196 SELECT sql FROM sqlite_master WHERE name IN ('c1', 'c2', 'p1');
197} {
198 {CREATE TABLE c1(a, b, FOREIGN KEY (a, b) REFERENCES p1(c, "reasonable"))}
199 {CREATE TABLE p1(c, "reasonable", PRIMARY KEY(c, "reasonable"))}
200 {CREATE TABLE c2(a, b, FOREIGN KEY (a, b) REFERENCES p1)}
201}
202
dan872165f2018-08-11 17:34:38 +0000203#-------------------------------------------------------------------------
204
205do_execsql_test 5.0 {
206 CREATE TABLE t5(a, b, c);
207 CREATE INDEX t5a ON t5(a);
208 INSERT INTO t5 VALUES(1, 2, 3), (4, 5, 6);
209 ANALYZE;
210}
211
212do_execsql_test 5.1 {
213 ALTER TABLE t5 RENAME b TO big;
214 SELECT big FROM t5;
215} {2 5}
216
217do_catchsql_test 6.1 {
218 ALTER TABLE sqlite_stat1 RENAME tbl TO thetable;
219} {1 {table sqlite_stat1 may not be altered}}
220
dana8762ae2018-08-11 17:49:23 +0000221#-------------------------------------------------------------------------
danb0c79202018-08-11 18:34:25 +0000222#
dana8762ae2018-08-11 17:49:23 +0000223do_execsql_test 6.0 {
224 CREATE TABLE blob(
225 rid INTEGER PRIMARY KEY,
226 rcvid INTEGER,
227 size INTEGER,
228 uuid TEXT UNIQUE NOT NULL,
229 content BLOB,
230 CHECK( length(uuid)>=40 AND rid>0 )
231 );
232}
233
dana8762ae2018-08-11 17:49:23 +0000234do_execsql_test 6.1 {
235 ALTER TABLE "blob" RENAME COLUMN "rid" TO "a1";
236}
237
dan404c3ba2018-08-11 20:38:33 +0000238do_catchsql_test 6.2 {
239 ALTER TABLE "blob" RENAME COLUMN "a1" TO [where];
240} {0 {}}
241
242do_execsql_test 6.3 {
243 SELECT "where" FROM blob;
244} {}
245
dan5496d6a2018-08-13 17:14:26 +0000246#-------------------------------------------------------------------------
dan987db762018-08-14 20:18:50 +0000247# Triggers.
dan5496d6a2018-08-13 17:14:26 +0000248#
249reset_db
250do_execsql_test 7.0 {
251 CREATE TABLE c(x);
252 INSERT INTO c VALUES(0);
253 CREATE TABLE t6("col a", "col b", "col c");
254 CREATE TRIGGER zzz AFTER UPDATE OF "col a", "col c" ON t6 BEGIN
255 UPDATE c SET x=x+1;
256 END;
257}
258
dan5be60c52018-08-15 20:28:39 +0000259do_execsql_test 7.1.1 {
dan5496d6a2018-08-13 17:14:26 +0000260 INSERT INTO t6 VALUES(0, 0, 0);
261 UPDATE t6 SET "col c" = 1;
262 SELECT * FROM c;
263} {1}
264
dan5be60c52018-08-15 20:28:39 +0000265do_execsql_test 7.1.2 {
dan5496d6a2018-08-13 17:14:26 +0000266 ALTER TABLE t6 RENAME "col c" TO "col 3";
267}
268
dan5be60c52018-08-15 20:28:39 +0000269do_execsql_test 7.1.3 {
dan5496d6a2018-08-13 17:14:26 +0000270 UPDATE t6 SET "col 3" = 0;
271 SELECT * FROM c;
272} {2}
273
dan987db762018-08-14 20:18:50 +0000274#-------------------------------------------------------------------------
275# Views.
276#
277reset_db
278do_execsql_test 8.0 {
279 CREATE TABLE a1(x INTEGER, y TEXT, z BLOB, PRIMARY KEY(x));
280 CREATE TABLE a2(a, b, c);
281 CREATE VIEW v1 AS SELECT x, y, z FROM a1;
282}
dancf8f2892018-08-09 20:47:01 +0000283
dan987db762018-08-14 20:18:50 +0000284do_execsql_test 8.1 {
285 ALTER TABLE a1 RENAME y TO yyy;
286 SELECT sql FROM sqlite_master WHERE type='view';
287} {{CREATE VIEW v1 AS SELECT x, yyy, z FROM a1}}
288
289do_execsql_test 8.2.1 {
290 DROP VIEW v1;
291 CREATE VIEW v2 AS SELECT x, x+x, a, a+a FROM a1, a2;
292} {}
293do_execsql_test 8.2.2 {
294 ALTER TABLE a1 RENAME x TO xxx;
295}
296do_execsql_test 8.2.3 {
297 SELECT sql FROM sqlite_master WHERE type='view';
298} {{CREATE VIEW v2 AS SELECT xxx, xxx+xxx, a, a+a FROM a1, a2}}
299
300do_execsql_test 8.3.1 {
301 DROP TABLE a2;
302 DROP VIEW v2;
303 CREATE TABLE a2(a INTEGER PRIMARY KEY, b, c);
304 CREATE VIEW v2 AS SELECT xxx, xxx+xxx, a, a+a FROM a1, a2;
305} {}
306do_execsql_test 8.3.2 {
307 ALTER TABLE a1 RENAME xxx TO x;
308}
309do_execsql_test 8.3.3 {
310 SELECT sql FROM sqlite_master WHERE type='view';
311} {{CREATE VIEW v2 AS SELECT x, x+x, a, a+a FROM a1, a2}}
312
313do_execsql_test 8.4.0 {
314 CREATE TABLE b1(a, b, c);
315 CREATE TABLE b2(x, y, z);
316}
317
318do_execsql_test 8.4.1 {
319 CREATE VIEW vvv AS SELECT c+c || coalesce(c, c) FROM b1, b2 WHERE x=c GROUP BY c HAVING c>0;
320 ALTER TABLE b1 RENAME c TO "a;b";
321 SELECT sql FROM sqlite_master WHERE name='vvv';
322} {{CREATE VIEW vvv AS SELECT "a;b"+"a;b" || coalesce("a;b", "a;b") FROM b1, b2 WHERE x="a;b" GROUP BY "a;b" HAVING "a;b">0}}
323
324do_execsql_test 8.4.2 {
325 CREATE VIEW www AS SELECT b FROM b1 UNION ALL SELECT y FROM b2;
326 ALTER TABLE b1 RENAME b TO bbb;
327 SELECT sql FROM sqlite_master WHERE name='www';
328} {{CREATE VIEW www AS SELECT bbb FROM b1 UNION ALL SELECT y FROM b2}}
329
330db collate nocase {string compare}
331
332do_execsql_test 8.4.3 {
333 CREATE VIEW xxx AS SELECT a FROM b1 UNION SELECT x FROM b2 ORDER BY 1 COLLATE nocase;
334}
335
336do_execsql_test 8.4.4 {
337 ALTER TABLE b2 RENAME x TO hello;
338 SELECT sql FROM sqlite_master WHERE name='xxx';
339} {{CREATE VIEW xxx AS SELECT a FROM b1 UNION SELECT hello FROM b2 ORDER BY 1 COLLATE nocase}}
340
dan24fedb92018-08-18 17:35:38 +0000341do_catchsql_test 8.4.5 {
dan987db762018-08-14 20:18:50 +0000342 CREATE VIEW zzz AS SELECT george, ringo FROM b1;
343 ALTER TABLE b1 RENAME a TO aaa;
dan24fedb92018-08-18 17:35:38 +0000344} {1 {error processing view zzz: no such column: george}}
dan987db762018-08-14 20:18:50 +0000345
dan0cbb0b12018-08-16 19:49:16 +0000346#-------------------------------------------------------------------------
347# More triggers.
348#
dandabc2682018-08-17 17:18:16 +0000349proc do_rename_column_test {tn old new lSchema} {
dan499b8252018-08-17 18:08:28 +0000350 for {set i 0} {$i < 2} {incr i} {
dan24fedb92018-08-18 17:35:38 +0000351 drop_all_tables_and_views db
dan499b8252018-08-17 18:08:28 +0000352
353 set lSorted [list]
354 foreach sql $lSchema {
355 execsql $sql
356 lappend lSorted [string trim $sql]
357 }
358 set lSorted [lsort $lSorted]
359
360 do_execsql_test $tn.$i.1 {
361 SELECT sql FROM sqlite_master WHERE sql!='' ORDER BY 1
362 } $lSorted
363
dan24fedb92018-08-18 17:35:38 +0000364 if {$i==1} {
dan499b8252018-08-17 18:08:28 +0000365 db close
366 sqlite3 db test.db
367 }
368
369 do_execsql_test $tn.$i.2 "ALTER TABLE t1 RENAME $old TO $new"
370
371 do_execsql_test $tn.$i.3 {
372 SELECT sql FROM sqlite_master ORDER BY 1
373 } [string map [list $old $new] $lSorted]
dandabc2682018-08-17 17:18:16 +0000374 }
dandabc2682018-08-17 17:18:16 +0000375}
376
dan0cbb0b12018-08-16 19:49:16 +0000377foreach {tn old new lSchema} {
378 1 _x_ _xxx_ {
379 { CREATE TABLE t1(a, b, _x_) }
380 { CREATE TRIGGER AFTER INSERT ON t1 BEGIN
381 SELECT _x_ FROM t1;
382 END }
383 }
384
385 2 _x_ _xxx_ {
386 { CREATE TABLE t1(a, b, _x_) }
387 { CREATE TABLE t2(c, d, e) }
388 { CREATE TRIGGER ttt AFTER INSERT ON t2 BEGIN
389 SELECT _x_ FROM t1;
390 END }
391 }
392
393 3 _x_ _xxx_ {
394 { CREATE TABLE t1(a, b, _x_ INTEGER, PRIMARY KEY(_x_), CHECK(_x_>0)) }
395 { CREATE TABLE t2(c, d, e) }
396 { CREATE TRIGGER ttt AFTER UPDATE ON t1 BEGIN
397 INSERT INTO t2 VALUES(new.a, new.b, new._x_);
398 END }
399 }
400
401 4 _x_ _xxx_ {
402 { CREATE TABLE t1(a, b, _x_ INTEGER, PRIMARY KEY(_x_), CHECK(_x_>0)) }
403 { CREATE TRIGGER ttt AFTER UPDATE ON t1 BEGIN
404 INSERT INTO t1 VALUES(new.a, new.b, new._x_)
405 ON CONFLICT (_x_) WHERE _x_>10 DO UPDATE SET _x_ = _x_+1;
406 END }
407 }
408} {
dandabc2682018-08-17 17:18:16 +0000409 do_rename_column_test 9.$tn $old $new $lSchema
dan0cbb0b12018-08-16 19:49:16 +0000410}
411
dandabc2682018-08-17 17:18:16 +0000412#-------------------------------------------------------------------------
413# Test that views can be edited even if there are missing collation
414# sequences or user defined functions.
415#
dan0cbb0b12018-08-16 19:49:16 +0000416reset_db
dan987db762018-08-14 20:18:50 +0000417
dandabc2682018-08-17 17:18:16 +0000418foreach {tn old new lSchema} {
419 1 _x_ _xxx_ {
420 { CREATE TABLE t1(a, b, _x_) }
dan499b8252018-08-17 18:08:28 +0000421 { CREATE VIEW s1 AS SELECT a, b, _x_ FROM t1 WHERE _x_='abc' COLLATE xyz }
dandabc2682018-08-17 17:18:16 +0000422 }
423
424 2 _x_ _xxx_ {
425 { CREATE TABLE t1(a, b, _x_) }
426 { CREATE VIEW v1 AS SELECT a, b, _x_ FROM t1 WHERE scalar(_x_) }
427 }
428
429 3 _x_ _xxx_ {
430 { CREATE TABLE t1(a, b, _x_) }
431 { CREATE VIEW v1 AS SELECT a, b, _x_ FROM t1 WHERE _x_ = unicode(1, 2, 3) }
432 }
dan499b8252018-08-17 18:08:28 +0000433
434 4 _x_ _xxx_ {
435 { CREATE TABLE t1(a, b, _x_) }
436 { CREATE VIRTUAL TABLE e1 USING echo(t1) }
437 }
dandabc2682018-08-17 17:18:16 +0000438} {
dan499b8252018-08-17 18:08:28 +0000439 register_echo_module db
dandabc2682018-08-17 17:18:16 +0000440 do_rename_column_test 10.$tn $old $new $lSchema
441}
442
dan24fedb92018-08-18 17:35:38 +0000443#--------------------------------------------------------------------------
444# Test that if a view or trigger refers to a virtual table for which the
445# module is not available, RENAME COLUMN cannot proceed.
446#
447reset_db
448register_echo_module db
449do_execsql_test 11.0 {
450 CREATE TABLE x1(a, b, c);
451 CREATE VIRTUAL TABLE e1 USING echo(x1);
452}
453db close
454sqlite3 db test.db
455
456do_execsql_test 11.1 {
457 ALTER TABLE x1 RENAME b TO bbb;
458 SELECT sql FROM sqlite_master;
459} { {CREATE TABLE x1(a, bbb, c)} {CREATE VIRTUAL TABLE e1 USING echo(x1)} }
460
461do_execsql_test 11.2 {
462 CREATE VIEW v1 AS SELECT e1.*, x1.c FROM e1, x1;
463}
464
465do_catchsql_test 11.3 {
466 ALTER TABLE x1 RENAME c TO ccc;
467} {1 {error processing view v1: no such module: echo}}
dandabc2682018-08-17 17:18:16 +0000468
dan987db762018-08-14 20:18:50 +0000469finish_test