Fix a case where a corrupt stat4 record could go unrecognized due to integer overflow.
[sqlite.git] / test / alter.test
blob9201f40adcad2c9ec9c399883f293e1a1b2ddd11
1 # 2004 November 10
3 # The author disclaims copyright to this source code.  In place of
4 # a legal notice, here is a blessing:
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.
10 #*************************************************************************
11 # This file implements regression tests for SQLite library.  The
12 # focus of this script is testing the ALTER TABLE statement.
14 # $Id: alter.test,v 1.32 2009/03/24 15:08:10 drh Exp $
17 set testdir [file dirname $argv0]
18 source $testdir/tester.tcl
20 # If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
21 ifcapable !altertable {
22   finish_test
23   return
26 #----------------------------------------------------------------------
27 # Test organization:
29 # alter-1.1.* - alter-1.7.*: Basic tests of ALTER TABLE, including tables
30 #     with implicit and explicit indices. These tests came from an earlier
31 #     fork of SQLite that also supported ALTER TABLE.
32 # alter-1.8.*: Tests for ALTER TABLE when the table resides in an 
33 #     attached database.
34 # alter-1.9.*: Tests for ALTER TABLE when their is whitespace between the
35 #     table name and left parenthesis token. i.e: 
36 #     "CREATE TABLE abc       (a, b, c);"
37 # alter-2.*: Test error conditions and messages.
38 # alter-3.*: Test ALTER TABLE on tables that have TRIGGERs attached to them.
39 # alter-4.*: Test ALTER TABLE on tables that have AUTOINCREMENT fields.
40 # ...
41 # alter-12.*: Test ALTER TABLE on views.
44 # Create some tables to rename.  Be sure to include some TEMP tables
45 # and some tables with odd names.
47 do_test alter-1.1 {
48   ifcapable tempdb {
49     set ::temp TEMP
50   } else {
51     set ::temp {}
52   }
53   execsql [subst -nocommands {
54     CREATE TABLE t1(a,b);
55     INSERT INTO t1 VALUES(1,2);
56     CREATE TABLE [t1'x1](c UNIQUE, b PRIMARY KEY);
57     INSERT INTO [t1'x1] VALUES(3,4);
58     CREATE INDEX t1i1 ON T1(B);
59     CREATE INDEX t1i2 ON t1(a,b);
60     CREATE INDEX i3 ON [t1'x1](b,c);
61     CREATE $::temp TABLE "temp table"(e,f,g UNIQUE);
62     CREATE INDEX i2 ON [temp table](f);
63     INSERT INTO [temp table] VALUES(5,6,7);
64   }]
65   execsql {
66     SELECT 't1', * FROM t1;
67     SELECT 't1''x1', * FROM "t1'x1";
68     SELECT * FROM [temp table];
69   }
70 } {t1 1 2 t1'x1 3 4 5 6 7}
71 do_test alter-1.2 {
72   execsql [subst {
73     CREATE $::temp TABLE objlist(type, name, tbl_name);
74     INSERT INTO objlist SELECT type, name, tbl_name 
75         FROM sqlite_master WHERE NAME!='objlist';
76   }]
77   ifcapable tempdb {
78     execsql {
79       INSERT INTO objlist SELECT type, name, tbl_name 
80           FROM temp.sqlite_master WHERE NAME!='objlist';
81     }
82   }
84   execsql {
85     SELECT type, name, tbl_name FROM objlist ORDER BY tbl_name, type desc, name;
86   }
87 } [list \
88      table t1                              t1             \
89      index t1i1                            t1             \
90      index t1i2                            t1             \
91      table t1'x1                           t1'x1          \
92      index i3                              t1'x1          \
93      index {sqlite_autoindex_t1'x1_1}      t1'x1          \
94      index {sqlite_autoindex_t1'x1_2}      t1'x1          \
95      table {temp table}                    {temp table}   \
96      index i2                              {temp table}   \
97      index {sqlite_autoindex_temp table_1} {temp table}   \
98   ]
100 # Make some changes
102 integrity_check alter-1.3.0
103 do_test alter-1.3 {
104   execsql {
105     ALTER TABLE [T1] RENAME to [-t1-];
106     ALTER TABLE "t1'x1" RENAME TO T2;
107     ALTER TABLE [temp table] RENAME to TempTab;
108   }
109 } {}
110 integrity_check alter-1.3.1
111 do_test alter-1.4 {
112   execsql {
113     SELECT 't1', * FROM [-t1-];
114     SELECT 't2', * FROM t2;
115     SELECT * FROM temptab;
116   }
117 } {t1 1 2 t2 3 4 5 6 7}
118 do_test alter-1.5 {
119   execsql {
120     DELETE FROM objlist;
121     INSERT INTO objlist SELECT type, name, tbl_name
122         FROM sqlite_master WHERE NAME!='objlist';
123   }
124   catchsql {
125     INSERT INTO objlist SELECT type, name, tbl_name 
126         FROM sqlite_temp_master WHERE NAME!='objlist';
127   }
128   execsql {
129     SELECT type, name, tbl_name FROM objlist ORDER BY tbl_name, type desc, name;
130   }
131 } [list \
132      table -t1-                         -t1-        \
133      index t1i1                         -t1-        \
134      index t1i2                         -t1-        \
135      table T2                           T2          \
136      index i3                           T2          \
137      index {sqlite_autoindex_T2_1}      T2          \
138      index {sqlite_autoindex_T2_2}      T2          \
139      table {TempTab}                    {TempTab}   \
140      index i2                           {TempTab}   \
141      index {sqlite_autoindex_TempTab_1} {TempTab}   \
142   ]
144 # Make sure the changes persist after restarting the database.
145 # (The TEMP table will not persist, of course.)
147 ifcapable tempdb {
148   do_test alter-1.6 {
149     db close
150     sqlite3 db test.db
151     set DB [sqlite3_connection_pointer db]
152     execsql {
153       CREATE TEMP TABLE objlist(type, name, tbl_name);
154       INSERT INTO objlist SELECT type, name, tbl_name FROM sqlite_master;
155       INSERT INTO objlist 
156           SELECT type, name, tbl_name FROM temp.sqlite_master 
157           WHERE NAME!='objlist';
158       SELECT type, name, tbl_name FROM objlist 
159           ORDER BY tbl_name, type desc, name;
160     }
161   } [list \
162        table -t1-                         -t1-           \
163        index t1i1                         -t1-           \
164        index t1i2                         -t1-           \
165        table T2                           T2          \
166        index i3                           T2          \
167        index {sqlite_autoindex_T2_1}      T2          \
168        index {sqlite_autoindex_T2_2}      T2          \
169     ]
170 } else {
171   execsql {
172     DROP TABLE TempTab;
173   }
176 # Create bogus application-defined functions for functions used 
177 # internally by ALTER TABLE, to ensure that ALTER TABLE falls back
178 # to the built-in functions.
180 proc failing_app_func {args} {error "bad function"}
181 do_test alter-1.7-prep {
182   db func substr failing_app_func
183   db func like failing_app_func
184   db func sqlite_rename_table failing_app_func
185   db func sqlite_rename_trigger failing_app_func
186   db func sqlite_rename_parent failing_app_func
187   catchsql {SELECT substr(name,1,3) FROM sqlite_master}
188 } {1 {bad function}}
190 # Make sure the ALTER TABLE statements work with the
191 # non-callback API
193 do_test alter-1.7 {
194   stepsql $DB {
195     ALTER TABLE [-t1-] RENAME to [*t1*];
196     ALTER TABLE T2 RENAME TO [<t2>];
197   }
198   execsql {
199     DELETE FROM objlist;
200     INSERT INTO objlist SELECT type, name, tbl_name
201         FROM sqlite_master WHERE NAME!='objlist';
202   }
203   catchsql {
204     INSERT INTO objlist SELECT type, name, tbl_name 
205         FROM sqlite_temp_master WHERE NAME!='objlist';
206   }
207   execsql {
208     SELECT type, name, tbl_name FROM objlist ORDER BY tbl_name, type desc, name;
209   }
210 } [list \
211      table *t1*                         *t1*           \
212      index t1i1                         *t1*           \
213      index t1i2                         *t1*           \
214      table <t2>                         <t2>          \
215      index i3                           <t2>          \
216      index {sqlite_autoindex_<t2>_1}    <t2>          \
217      index {sqlite_autoindex_<t2>_2}    <t2>          \
218   ]
220 # Check that ALTER TABLE works on attached databases.
222 ifcapable attach {
223   do_test alter-1.8.1 {
224     forcedelete test2.db
225     forcedelete test2.db-journal
226     execsql {
227       ATTACH 'test2.db' AS aux;
228     }
229   } {}
230   do_test alter-1.8.2 {
231     execsql {
232       CREATE TABLE t4(a PRIMARY KEY, b, c);
233       CREATE TABLE aux.t4(a PRIMARY KEY, b, c);
234       CREATE INDEX i4 ON t4(b);
235       CREATE INDEX aux.i4 ON t4(b);
236     }
237   } {}
238   do_test alter-1.8.3 {
239     execsql {
240       INSERT INTO t4 VALUES('main', 'main', 'main');
241       INSERT INTO aux.t4 VALUES('aux', 'aux', 'aux');
242       SELECT * FROM t4 WHERE a = 'main';
243     }
244   } {main main main}
245   do_test alter-1.8.4 {
246     execsql {
247       ALTER TABLE t4 RENAME TO t5;
248       SELECT * FROM t4 WHERE a = 'aux';
249     }
250   } {aux aux aux}
251   do_test alter-1.8.5 {
252     execsql {
253       SELECT * FROM t5;
254     }
255   } {main main main}
256   do_test alter-1.8.6 {
257     execsql {
258       SELECT * FROM t5 WHERE b = 'main';
259     }
260   } {main main main}
261   do_test alter-1.8.7 {
262     execsql {
263       ALTER TABLE aux.t4 RENAME TO t5;
264       SELECT * FROM aux.t5 WHERE b = 'aux';
265     }
266   } {aux aux aux}
269 do_test alter-1.9.1 {
270   execsql {
271     CREATE TABLE tbl1   (a, b, c);
272     INSERT INTO tbl1 VALUES(1, 2, 3);
273   }
274 } {}
275 do_test alter-1.9.2 {
276   execsql {
277     SELECT * FROM tbl1;
278   }
279 } {1 2 3}
280 do_test alter-1.9.3 {
281   execsql {
282     ALTER TABLE tbl1 RENAME TO tbl2;
283     SELECT * FROM tbl2;
284   }
285 } {1 2 3}
286 do_test alter-1.9.4 {
287   execsql {
288     DROP TABLE tbl2;
289   }
290 } {}
292 # Test error messages
294 do_test alter-2.1 {
295   catchsql {
296     ALTER TABLE none RENAME TO hi;
297   }
298 } {1 {no such table: none}}
299 do_test alter-2.2 {
300   execsql {
301     CREATE TABLE t3(p,q,r);
302   }
303   catchsql {
304     ALTER TABLE [<t2>] RENAME TO t3;
305   }
306 } {1 {there is already another table or index with this name: t3}}
307 do_test alter-2.3 {
308   catchsql {
309     ALTER TABLE [<t2>] RENAME TO i3;
310   }
311 } {1 {there is already another table or index with this name: i3}}
312 do_test alter-2.4 {
313   catchsql {
314     ALTER TABLE SqLiTe_master RENAME TO master;
315   }
316 } {1 {table sqlite_master may not be altered}}
317 do_test alter-2.5 {
318   catchsql {
319     ALTER TABLE t3 RENAME TO sqlite_t3;
320   }
321 } {1 {object name reserved for internal use: sqlite_t3}}
322 do_test alter-2.6 {
323   catchsql {
324     ALTER TABLE t3 ADD COLUMN (ALTER TABLE t3 ADD COLUMN);
325   }
326 } {1 {near "(": syntax error}}
328 # If this compilation does not include triggers, omit the alter-3.* tests.
329 ifcapable trigger {
331 #-----------------------------------------------------------------------
332 # Tests alter-3.* test ALTER TABLE on tables that have triggers.
334 # alter-3.1.*: ALTER TABLE with triggers.
335 # alter-3.2.*: Test that the ON keyword cannot be used as a database,
336 #     table or column name unquoted. This is done because part of the
337 #     ALTER TABLE code (specifically the implementation of SQL function
338 #     "sqlite_alter_trigger") will break in this case.
339 # alter-3.3.*: ALTER TABLE with TEMP triggers (todo).
342 # An SQL user-function for triggers to fire, so that we know they
343 # are working.
344 proc trigfunc {args} {
345   set ::TRIGGER $args
347 db func trigfunc trigfunc
349 do_test alter-3.1.0 {
350   execsql {
351     CREATE TABLE t6(a, b, c);
352     -- Different case for the table name in the trigger.
353     CREATE TRIGGER trig1 AFTER INSERT ON T6 BEGIN
354       SELECT trigfunc('trig1', new.a, new.b, new.c);
355     END;
356   }
357 } {}
358 do_test alter-3.1.1 {
359   execsql {
360     INSERT INTO t6 VALUES(1, 2, 3);
361   }
362   set ::TRIGGER
363 } {trig1 1 2 3}
364 do_test alter-3.1.2 {
365   execsql {
366     ALTER TABLE t6 RENAME TO t7;
367     INSERT INTO t7 VALUES(4, 5, 6);
368   }
369   set ::TRIGGER
370 } {trig1 4 5 6}
371 do_test alter-3.1.3 {
372   execsql {
373     DROP TRIGGER trig1;
374   }
375 } {}
376 do_test alter-3.1.4 {
377   execsql {
378     CREATE TRIGGER trig2 AFTER INSERT ON main.t7 BEGIN
379       SELECT trigfunc('trig2', new.a, new.b, new.c);
380     END;
381     INSERT INTO t7 VALUES(1, 2, 3);
382   }
383   set ::TRIGGER
384 } {trig2 1 2 3}
385 do_test alter-3.1.5 {
386   execsql {
387     ALTER TABLE t7 RENAME TO t8;
388     INSERT INTO t8 VALUES(4, 5, 6);
389   }
390   set ::TRIGGER
391 } {trig2 4 5 6}
392 do_test alter-3.1.6 {
393   execsql {
394     DROP TRIGGER trig2;
395   }
396 } {}
397 do_test alter-3.1.7 {
398   execsql {
399     CREATE TRIGGER trig3 AFTER INSERT ON main.'t8'BEGIN
400       SELECT trigfunc('trig3', new.a, new.b, new.c);
401     END;
402     INSERT INTO t8 VALUES(1, 2, 3);
403   }
404   set ::TRIGGER
405 } {trig3 1 2 3}
406 do_test alter-3.1.8 {
407   execsql {
408     ALTER TABLE t8 RENAME TO t9;
409     INSERT INTO t9 VALUES(4, 5, 6);
410   }
411   set ::TRIGGER
412 } {trig3 4 5 6}
414 # Make sure "ON" cannot be used as a database, table or column name without
415 # quoting. Otherwise the sqlite_alter_trigger() function might not work.
416 forcedelete test3.db
417 forcedelete test3.db-journal
418 ifcapable attach {
419   do_test alter-3.2.1 {
420     catchsql {
421       ATTACH 'test3.db' AS ON;
422     }
423   } {1 {near "ON": syntax error}}
424   do_test alter-3.2.2 {
425     catchsql {
426       ATTACH 'test3.db' AS 'ON';
427     }
428   } {0 {}}
429   do_test alter-3.2.3 {
430     catchsql {
431       CREATE TABLE ON.t1(a, b, c); 
432     }
433   } {1 {near "ON": syntax error}}
434   do_test alter-3.2.4 {
435     catchsql {
436       CREATE TABLE 'ON'.t1(a, b, c); 
437     }
438   } {0 {}}
439   do_test alter-3.2.4 {
440     catchsql {
441       CREATE TABLE 'ON'.ON(a, b, c); 
442     }
443   } {1 {near "ON": syntax error}}
444   do_test alter-3.2.5 {
445     catchsql {
446       CREATE TABLE 'ON'.'ON'(a, b, c); 
447     }
448   } {0 {}}
450 do_test alter-3.2.6 {
451   catchsql {
452     CREATE TABLE t10(a, ON, c);
453   }
454 } {1 {near "ON": syntax error}}
455 do_test alter-3.2.7 {
456   catchsql {
457     CREATE TABLE t10(a, 'ON', c);
458   }
459 } {0 {}}
460 do_test alter-3.2.8 {
461   catchsql {
462     CREATE TRIGGER trig4 AFTER INSERT ON ON BEGIN SELECT 1; END;
463   }
464 } {1 {near "ON": syntax error}}
465 ifcapable attach {
466   do_test alter-3.2.9 {
467     catchsql {
468       CREATE TRIGGER 'on'.trig4 AFTER INSERT ON 'ON' BEGIN SELECT 1; END;
469     }
470   } {0 {}}
472 do_test alter-3.2.10 {
473   execsql {
474     DROP TABLE t10;
475   }
476 } {}
478 do_test alter-3.3.1 {
479   execsql [subst {
480     CREATE TABLE tbl1(a, b, c);
481     CREATE $::temp TRIGGER trig1 AFTER INSERT ON tbl1 BEGIN
482       SELECT trigfunc('trig1', new.a, new.b, new.c);
483     END;
484   }]
485 } {}
486 do_test alter-3.3.2 {
487   execsql {
488     INSERT INTO tbl1 VALUES('a', 'b', 'c');
489   }
490   set ::TRIGGER
491 } {trig1 a b c}
492 do_test alter-3.3.3 {
493   execsql {
494     ALTER TABLE tbl1 RENAME TO tbl2;
495     INSERT INTO tbl2 VALUES('d', 'e', 'f');
496   } 
497   set ::TRIGGER
498 } {trig1 d e f}
499 do_test alter-3.3.4 {
500   execsql [subst {
501     CREATE $::temp TRIGGER trig2 AFTER UPDATE ON tbl2 BEGIN
502       SELECT trigfunc('trig2', new.a, new.b, new.c);
503     END;
504   }] 
505 } {}
506 do_test alter-3.3.5 {
507   execsql {
508     ALTER TABLE tbl2 RENAME TO tbl3;
509     INSERT INTO tbl3 VALUES('g', 'h', 'i');
510   } 
511   set ::TRIGGER
512 } {trig1 g h i}
513 do_test alter-3.3.6 {
514   execsql {
515     UPDATE tbl3 SET a = 'G' where a = 'g';
516   } 
517   set ::TRIGGER
518 } {trig2 G h i}
519 do_test alter-3.3.7 {
520   execsql {
521     DROP TABLE tbl3;
522   }
523 } {}
524 ifcapable tempdb {
525   do_test alter-3.3.8 {
526     execsql {
527       SELECT * FROM temp.sqlite_master WHERE type = 'trigger';
528     }
529   } {}
532 } ;# ifcapable trigger
534 # If the build does not include AUTOINCREMENT fields, omit alter-4.*.
535 ifcapable autoinc {
537 do_test alter-4.1 {
538   execsql {
539     CREATE TABLE tbl1(a INTEGER PRIMARY KEY AUTOINCREMENT);
540     INSERT INTO tbl1 VALUES(10);
541   }
542 } {}
543 do_test alter-4.2 {
544   execsql {
545     INSERT INTO tbl1 VALUES(NULL);
546     SELECT a FROM tbl1;
547   }
548 } {10 11}
549 do_test alter-4.3 {
550   execsql {
551     ALTER TABLE tbl1 RENAME TO tbl2;
552     DELETE FROM tbl2;
553     INSERT INTO tbl2 VALUES(NULL);
554     SELECT a FROM tbl2;
555   }
556 } {12}
557 do_test alter-4.4 {
558   execsql {
559     DROP TABLE tbl2;
560   }
561 } {}
563 } ;# ifcapable autoinc
565 # Test that it is Ok to execute an ALTER TABLE immediately after
566 # opening a database.
567 do_test alter-5.1 {
568   execsql {
569     CREATE TABLE tbl1(a, b, c);
570     INSERT INTO tbl1 VALUES('x', 'y', 'z');
571   }
572 } {}
573 do_test alter-5.2 {
574   sqlite3 db2 test.db
575   execsql {
576     ALTER TABLE tbl1 RENAME TO tbl2;
577     SELECT * FROM tbl2;
578   } db2
579 } {x y z}
580 do_test alter-5.3 {
581   db2 close
582 } {}
584 foreach tblname [execsql {
585   SELECT name FROM sqlite_master
586    WHERE type='table' AND name NOT GLOB 'sqlite*'
587 }] {
588   execsql "DROP TABLE \"$tblname\""
591 set ::tbl_name "abc\uABCDdef"
592 do_test alter-6.1 {
593   string length $::tbl_name
594 } {7}
595 do_test alter-6.2 {
596   execsql "
597     CREATE TABLE ${tbl_name}(a, b, c);
598   "
599   set ::oid [execsql {SELECT max(oid) FROM sqlite_master}]
600   execsql "
601     SELECT sql FROM sqlite_master WHERE oid = $::oid;
602   "
603 } "{CREATE TABLE ${::tbl_name}(a, b, c)}"
604 execsql "
605   SELECT * FROM ${::tbl_name}
607 set ::tbl_name2 "abcXdef"
608 do_test alter-6.3 {
609   execsql "
610     ALTER TABLE $::tbl_name RENAME TO $::tbl_name2 
611   "
612   execsql "
613     SELECT sql FROM sqlite_master WHERE oid = $::oid
614   "
615 } "{CREATE TABLE \"${::tbl_name2}\"(a, b, c)}"
616 do_test alter-6.4 {
617   execsql "
618     ALTER TABLE $::tbl_name2 RENAME TO $::tbl_name
619   "
620   execsql "
621     SELECT sql FROM sqlite_master WHERE oid = $::oid
622   "
623 } "{CREATE TABLE \"${::tbl_name}\"(a, b, c)}"
624 set ::col_name ghi\1234\jkl
625 do_test alter-6.5 {
626   execsql "
627     ALTER TABLE $::tbl_name ADD COLUMN $::col_name VARCHAR
628   "
629   execsql "
630     SELECT sql FROM sqlite_master WHERE oid = $::oid
631   "
632 } "{CREATE TABLE \"${::tbl_name}\"(a, b, c, $::col_name VARCHAR)}"
633 set ::col_name2 B\3421\A
634 do_test alter-6.6 {
635   db close
636   sqlite3 db test.db
637   execsql "
638     ALTER TABLE $::tbl_name ADD COLUMN $::col_name2
639   "
640   execsql "
641     SELECT sql FROM sqlite_master WHERE oid = $::oid
642   "
643 } "{CREATE TABLE \"${::tbl_name}\"(a, b, c, $::col_name VARCHAR, $::col_name2)}"
644 do_test alter-6.7 {
645   execsql "
646     INSERT INTO ${::tbl_name} VALUES(1, 2, 3, 4, 5);
647     SELECT $::col_name, $::col_name2 FROM $::tbl_name;
648   "
649 } {4 5}
651 # Ticket #1665:  Make sure ALTER TABLE ADD COLUMN works on a table
652 # that includes a COLLATE clause.
654 do_realnum_test alter-7.1 {
655   execsql {
656     CREATE TABLE t1(a TEXT COLLATE BINARY);
657     ALTER TABLE t1 ADD COLUMN b INTEGER COLLATE NOCASE;
658     INSERT INTO t1 VALUES(1,'-2');
659     INSERT INTO t1 VALUES(5.4e-08,'5.4e-08');
660     SELECT typeof(a), a, typeof(b), b FROM t1;
661   }
662 } {text 1 integer -2 text 5.4e-08 real 5.4e-08}
664 # Make sure that when a column is added by ALTER TABLE ADD COLUMN and has
665 # a default value that the default value is used by aggregate functions.
667 do_test alter-8.1 {
668   execsql {
669     CREATE TABLE t2(a INTEGER);
670     INSERT INTO t2 VALUES(1);
671     INSERT INTO t2 VALUES(1);
672     INSERT INTO t2 VALUES(2);
673     ALTER TABLE t2 ADD COLUMN b INTEGER DEFAULT 9;
674     SELECT sum(b) FROM t2;
675   }
676 } {27}
677 do_test alter-8.2 {
678   execsql {
679     SELECT a, sum(b) FROM t2 GROUP BY a;
680   }
681 } {1 18 2 9}
683 #--------------------------------------------------------------------------
684 # alter-9.X - Special test: Make sure the sqlite_rename_column() and
685 # rename_table() functions do not crash when handed bad input.
687 sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
688 do_test alter-9.1 {
689   execsql {SELECT SQLITE_RENAME_COLUMN(0,0,0,0,0,0,0,0,0)}
690 } {{}}
691 foreach {tn sql} {
692     1 { SELECT SQLITE_RENAME_TABLE(0,0,0,0,0,0,0) }
693     2 { SELECT SQLITE_RENAME_TABLE(10,20,30,40,50,60,70) }
694     3 { SELECT SQLITE_RENAME_TABLE('foo','foo','foo','foo','foo','foo','foo') }
695 } {
696   do_test alter-9.2.$tn {
697     catch { execsql $sql }
698   } 1
700 sqlite3_test_control SQLITE_TESTCTRL_INTERNAL_FUNCTIONS db
702 # If the INTERNAL_FUNCTIONS test-control is disabled (which is the default),
703 # then the sqlite_rename_table() SQL function is not accessible to ordinary SQL.
705 do_catchsql_test alter-9.3 {
706   SELECT sqlite_rename_table(0,0,0,0,0,0,0);
707 } {1 {no such function: sqlite_rename_table}}
709 #------------------------------------------------------------------------
710 # alter-10.X - Make sure ALTER TABLE works with multi-byte UTF-8 characters 
711 # in the names.
713 do_test alter-10.1 {
714   execsql "CREATE TABLE xyz(x UNIQUE)"
715   execsql "ALTER TABLE xyz RENAME TO xyz\u1234abc"
716   execsql {SELECT name FROM sqlite_master WHERE name GLOB 'xyz*'}
717 } [list xyz\u1234abc]
718 do_test alter-10.2 {
719   execsql {SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_autoindex*'}
720 } [list sqlite_autoindex_xyz\u1234abc_1]
721 do_test alter-10.3 {
722   execsql "ALTER TABLE xyz\u1234abc RENAME TO xyzabc"
723   execsql {SELECT name FROM sqlite_master WHERE name GLOB 'xyz*'}
724 } [list xyzabc]
725 do_test alter-10.4 {
726   execsql {SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_autoindex*'}
727 } [list sqlite_autoindex_xyzabc_1]
729 do_test alter-11.1 {
730   sqlite3_exec db {CREATE TABLE t11(%c6%c6)}
731   execsql {
732     ALTER TABLE t11 ADD COLUMN abc;
733   }
734   catchsql {
735     ALTER TABLE t11 ADD COLUMN abc;
736   }
737 } {1 {duplicate column name: abc}}
738 set isutf16 [regexp 16 [db one {PRAGMA encoding}]]
739 if {!$isutf16} {
740   do_test alter-11.2 {
741     execsql {INSERT INTO t11 VALUES(1,2)}
742     sqlite3_exec db {SELECT %c6%c6 AS xyz, abc FROM t11}
743   } {0 {xyz abc 1 2}}
745 do_test alter-11.3 {
746   sqlite3_exec db {CREATE TABLE t11b("%81%82%83" text)}
747   execsql {
748     ALTER TABLE t11b ADD COLUMN abc;
749   }
750   catchsql {
751     ALTER TABLE t11b ADD COLUMN abc;
752   }
753 } {1 {duplicate column name: abc}}
754 if {!$isutf16} {
755   do_test alter-11.4 {
756     execsql {INSERT INTO t11b VALUES(3,4)}
757     sqlite3_exec db {SELECT %81%82%83 AS xyz, abc FROM t11b}
758   } {0 {xyz abc 3 4}}
759   do_test alter-11.5 {
760     sqlite3_exec db {SELECT [%81%82%83] AS xyz, abc FROM t11b}
761   } {0 {xyz abc 3 4}}
762   do_test alter-11.6 {
763     sqlite3_exec db {SELECT "%81%82%83" AS xyz, abc FROM t11b}
764   } {0 {xyz abc 3 4}}
766 do_test alter-11.7 {
767   sqlite3_exec db {CREATE TABLE t11c(%81%82%83 text)}
768   execsql {
769     ALTER TABLE t11c ADD COLUMN abc;
770   }
771   catchsql {
772     ALTER TABLE t11c ADD COLUMN abc;
773   }
774 } {1 {duplicate column name: abc}}
775 if {!$isutf16} {
776   do_test alter-11.8 {
777     execsql {INSERT INTO t11c VALUES(5,6)}
778     sqlite3_exec db {SELECT %81%82%83 AS xyz, abc FROM t11c}
779   } {0 {xyz abc 5 6}}
780   do_test alter-11.9 {
781     sqlite3_exec db {SELECT [%81%82%83] AS xyz, abc FROM t11c}
782   } {0 {xyz abc 5 6}}
783   do_test alter-11.10 {
784     sqlite3_exec db {SELECT "%81%82%83" AS xyz, abc FROM t11c}
785   } {0 {xyz abc 5 6}}
788 do_test alter-12.1 {
789   execsql {
790     CREATE TABLE t12(a, b, c);
791     CREATE VIEW v1 AS SELECT * FROM t12;
792   }
793 } {}
794 do_test alter-12.2 {
795   catchsql {
796     ALTER TABLE v1 RENAME TO v2;
797   }
798 } {1 {view v1 may not be altered}}
799 do_test alter-12.3 {
800   execsql { SELECT * FROM v1; }
801 } {}
802 do_test alter-12.4 {
803   db close
804   sqlite3 db test.db
805   execsql { SELECT * FROM v1; }
806 } {}
807 do_test alter-12.5 {
808   catchsql { 
809     ALTER TABLE v1 ADD COLUMN new_column;
810   }
811 } {1 {Cannot add a column to a view}}
813 # Ticket #3102:
814 # Verify that comments do not interfere with the table rename
815 # algorithm.
817 do_test alter-13.1 {
818   execsql {
819     CREATE TABLE /* hi */ t3102a(x);
820     CREATE TABLE t3102b -- comment
821     (y);
822     CREATE INDEX t3102c ON t3102a(x);
823     SELECT name FROM sqlite_master WHERE name GLOB 't3102*' ORDER BY 1;
824   }
825 } {t3102a t3102b t3102c}
826 do_test alter-13.2 {
827   execsql {
828     ALTER TABLE t3102a RENAME TO t3102a_rename;
829     SELECT name FROM sqlite_master WHERE name GLOB 't3102*' ORDER BY 1;
830   }
831 } {t3102a_rename t3102b t3102c}
832 do_test alter-13.3 {
833   execsql {
834     ALTER TABLE t3102b RENAME TO t3102b_rename;
835     SELECT name FROM sqlite_master WHERE name GLOB 't3102*' ORDER BY 1;
836   }
837 } {t3102a_rename t3102b_rename t3102c}
839 # Ticket #3651
840 do_test alter-14.1 {
841   catchsql {
842     CREATE TABLE t3651(a UNIQUE);
843     INSERT INTO t3651 VALUES(5);
844     ALTER TABLE t3651 ADD COLUMN b UNIQUE;
845   }
846 } {1 {Cannot add a UNIQUE column}}
847 do_test alter-14.2 {
848   catchsql {
849     ALTER TABLE t3651 ADD COLUMN b PRIMARY KEY;
850   }
851 } {1 {Cannot add a PRIMARY KEY column}}
854 #-------------------------------------------------------------------------
855 # Test that it is not possible to use ALTER TABLE on any system table.
857 set system_table_list {1 sqlite_master}
858 catchsql ANALYZE
859 ifcapable analyze { lappend system_table_list 2 sqlite_stat1 }
860 ifcapable stat4   { lappend system_table_list 4 sqlite_stat4 }
862 foreach {tn tbl} $system_table_list {
863   do_test alter-15.$tn.1 {
864     catchsql "ALTER TABLE $tbl RENAME TO xyz"
865   } [list 1 "table $tbl may not be altered"]
867   do_test alter-15.$tn.2 {
868     catchsql "ALTER TABLE $tbl ADD COLUMN xyz"
869   } [list 1 "table $tbl may not be altered"]
872 #------------------------------------------------------------------------
873 # Verify that ALTER TABLE works on tables with the WITHOUT rowid option.
875 do_execsql_test alter-16.1 {
876   CREATE TABLE t16a(a TEXT, b REAL, c INT, PRIMARY KEY(a,b)) WITHOUT rowid;
877   INSERT INTO t16a VALUES('abc',1.25,99);
878   ALTER TABLE t16a ADD COLUMN d TEXT DEFAULT 'xyzzy';
879   INSERT INTO t16a VALUES('cba',5.5,98,'fizzle');
880   SELECT * FROM t16a ORDER BY a;
881 } {abc 1.25 99 xyzzy cba 5.5 98 fizzle}
882 do_execsql_test alter-16.2 {
883   ALTER TABLE t16a RENAME TO t16a_rn;
884   SELECT * FROM t16a_rn ORDER BY a;
885 } {abc 1.25 99 xyzzy cba 5.5 98 fizzle}
887 # 2018-09-16 ticket b41031ea2b5372378cb3d2d43cf9fe2a4a5c2510
889 ifcapable rtree {
890   db close
891   sqlite3 db :memory:
892   do_execsql_test alter-17.100 {
893     CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
894     CREATE VIRTUAL TABLE t2 USING rtree(id,x0,x1);
895     INSERT INTO t1 VALUES(1,'apple'),(2,'fig'),(3,'pear');
896     INSERT INTO t2 VALUES(1,1.0,2.0),(2,2.0,3.0),(3,1.5,3.5);
897     CREATE TRIGGER r1 AFTER UPDATE ON t1 BEGIN
898       DELETE FROM t2 WHERE id = OLD.a;
899     END;
900     ALTER TABLE t1 RENAME TO t3;
901     UPDATE t3 SET b='peach' WHERE a=2;
902     SELECT * FROM t2 ORDER BY 1;
903   } {1 1.0 2.0 3 1.5 3.5}
906 # 2021-03-08 dbsqlfuzz 3f0a7245b69cd08617d7d7781ebaedb0fe765a93
907 reset_db
908 do_catchsql_test alter-18.1 {
909   CREATE TABLE t1(a,b,c);
910   CREATE TABLE log(a INTEGER PRIMARY KEY,b,c);
911   CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
912     INSERT INTO logx(a,b,c) VALUES(new.a,new.b,new.c)
913     ON CONFLICT(a) DO UPDATE SET c=excluded.c, b=new.b;
914   END;
915   ALTER TABLE log RENAME COLUMN a TO x;
916 } {1 {error in trigger tr1: no such table: main.logx}}
918 # 2021-10-13 dbsqlfuzz e89174cbfad2d904f06b5e24df0a22510b6a1c1e
919 reset_db
920 do_execsql_test alter-19.1 {
921   CREATE TABLE t1(x);
922   CREATE TABLE t2(c);
923   CREATE TRIGGER r1 AFTER INSERT ON t2 BEGIN
924     UPDATE t2 SET (c)=(
925        EXISTS(SELECT 1 WHERE (WITH cte1(a) AS (SELECT 1 FROM t1 WHERE (SELECT 1 WHERE (WITH cte2(b) AS (VALUES(1))SELECT b FROM cte2)))SELECT a FROM cte1))
926     );
927   END;
928   ALTER TABLE t2 RENAME TO t3;
929 } {}
930 do_execsql_test alter-19.2 {
931   SELECT name FROM sqlite_schema WHERE sql LIKE '%t2%';
932 } {}
933 do_execsql_test alter-19.3 {
934   SELECT name FROM sqlite_schema WHERE sql LIKE '%t3%' ORDER BY name;
935 } {r1 t3}
937 # 2023-10-14
938 # On an ALTER TABLE ADD COLUMN with a DEFAULT clause on a STRICT table
939 # make sure that the DEFAULT has a compatible type.
941 reset_db
942 do_execsql_test alter-20.1 {
943   CREATE TABLE t1(a INT) STRICT;
944   INSERT INTO t1(a) VALUES(45);
945 } {}
946 do_catchsql_test alter-20.2 {
947   ALTER TABLE t1 ADD COLUMN b TEXT DEFAULT x'313233';
948 } {1 {type mismatch on DEFAULT}}
949 do_execsql_test alter-20.2 {
950   DELETE FROM t1;
951   ALTER TABLE t1 ADD COLUMN b TEXT DEFAULT x'313233';
952 } {}
953 do_catchsql_test alter-20.3 {
954   INSERT INTO t1(a) VALUES(45);
955 } {1 {cannot store BLOB value in TEXT column t1.b}}
957 # 2023-11-17 dbsqlfuzz e0900262dadd5c78c2226ad6a435c7f0255be2cd
958 # Assertion fault associated with ALTER TABLE and an
959 # aggregate ORDER BY within an unknown aggregate function.
961 reset_db
962 do_execsql_test alter-21.1 {
963   CREATE TABLE t1(a,b,c,d);
964   CREATE TABLE t2(a,b,c,d,x);
965   CREATE TRIGGER r1 AFTER INSERT ON t2 BEGIN
966     SELECT unknown_function(a ORDER BY (SELECT group_concat(DISTINCT a ORDER BY a) FROM t1)) FROM t1;
967   END;
968   ALTER TABLE t2 RENAME TO e;
969 } {}
970 do_execsql_test alter-21.2 {
971   SELECT name, type FROM sqlite_schema ORDER BY name;
972 } {e table r1 trigger t1 table}
973 do_execsql_test alter-21.3 {
974   DROP TRIGGER r1;
975   CREATE TRIGGER r2 AFTER INSERT ON e BEGIN
976     SELECT unknown_function(a ORDER BY (SELECT group_concat(a ORDER BY a) FROM (SELECT b FROM t1))) FROM t1;
977   END;
978   ALTER TABLE e RENAME TO t99;
980 do_execsql_test alter-21.4 {
981   SELECT name, type FROM sqlite_schema ORDER BY name;
982 } {r2 trigger t1 table t99 table}
986 finish_test