xref: /sqlite-3.40.0/test/alter.test (revision 45f31be8)
1# 2004 November 10
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 the ALTER TABLE statement.
13#
14# $Id: alter.test,v 1.32 2009/03/24 15:08:10 drh Exp $
15#
16
17set testdir [file dirname $argv0]
18source $testdir/tester.tcl
19
20# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
21ifcapable !altertable {
22  finish_test
23  return
24}
25
26#----------------------------------------------------------------------
27# Test organization:
28#
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.
42#
43
44# Create some tables to rename.  Be sure to include some TEMP tables
45# and some tables with odd names.
46#
47do_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}
71do_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 sqlite_temp_master WHERE NAME!='objlist';
81    }
82  }
83
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  ]
99
100# Make some changes
101#
102integrity_check alter-1.3.0
103do_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} {}
110integrity_check alter-1.3.1
111do_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}
118do_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  ]
143
144# Make sure the changes persist after restarting the database.
145# (The TEMP table will not persist, of course.)
146#
147ifcapable 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 sqlite_temp_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  }
174}
175
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.
179#
180proc failing_app_func {args} {error "bad function"}
181do_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}}
189
190# Make sure the ALTER TABLE statements work with the
191# non-callback API
192#
193do_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  ]
219
220# Check that ALTER TABLE works on attached databases.
221#
222ifcapable 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}
267}
268
269do_test alter-1.9.1 {
270  execsql {
271    CREATE TABLE tbl1   (a, b, c);
272    INSERT INTO tbl1 VALUES(1, 2, 3);
273  }
274} {}
275do_test alter-1.9.2 {
276  execsql {
277    SELECT * FROM tbl1;
278  }
279} {1 2 3}
280do_test alter-1.9.3 {
281  execsql {
282    ALTER TABLE tbl1 RENAME TO tbl2;
283    SELECT * FROM tbl2;
284  }
285} {1 2 3}
286do_test alter-1.9.4 {
287  execsql {
288    DROP TABLE tbl2;
289  }
290} {}
291
292# Test error messages
293#
294do_test alter-2.1 {
295  catchsql {
296    ALTER TABLE none RENAME TO hi;
297  }
298} {1 {no such table: none}}
299do_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}}
307do_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}}
312do_test alter-2.4 {
313  catchsql {
314    ALTER TABLE SqLiTe_master RENAME TO master;
315  }
316} {1 {table sqlite_master may not be altered}}
317do_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}}
322do_test alter-2.6 {
323  catchsql {
324    ALTER TABLE t3 ADD COLUMN (ALTER TABLE t3 ADD COLUMN);
325  }
326} {1 {near "(": syntax error}}
327
328# If this compilation does not include triggers, omit the alter-3.* tests.
329ifcapable trigger {
330
331#-----------------------------------------------------------------------
332# Tests alter-3.* test ALTER TABLE on tables that have triggers.
333#
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).
340#
341
342# An SQL user-function for triggers to fire, so that we know they
343# are working.
344proc trigfunc {args} {
345  set ::TRIGGER $args
346}
347db func trigfunc trigfunc
348
349do_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} {}
358do_test alter-3.1.1 {
359  execsql {
360    INSERT INTO t6 VALUES(1, 2, 3);
361  }
362  set ::TRIGGER
363} {trig1 1 2 3}
364do_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}
371do_test alter-3.1.3 {
372  execsql {
373    DROP TRIGGER trig1;
374  }
375} {}
376do_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}
385do_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}
392do_test alter-3.1.6 {
393  execsql {
394    DROP TRIGGER trig2;
395  }
396} {}
397do_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}
406do_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}
413
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.
416forcedelete test3.db
417forcedelete test3.db-journal
418ifcapable 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 {}}
449}
450do_test alter-3.2.6 {
451  catchsql {
452    CREATE TABLE t10(a, ON, c);
453  }
454} {1 {near "ON": syntax error}}
455do_test alter-3.2.7 {
456  catchsql {
457    CREATE TABLE t10(a, 'ON', c);
458  }
459} {0 {}}
460do_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}}
465ifcapable 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 {}}
471}
472do_test alter-3.2.10 {
473  execsql {
474    DROP TABLE t10;
475  }
476} {}
477
478do_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} {}
486do_test alter-3.3.2 {
487  execsql {
488    INSERT INTO tbl1 VALUES('a', 'b', 'c');
489  }
490  set ::TRIGGER
491} {trig1 a b c}
492do_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}
499do_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} {}
506do_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}
513do_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}
519do_test alter-3.3.7 {
520  execsql {
521    DROP TABLE tbl3;
522  }
523} {}
524ifcapable tempdb {
525  do_test alter-3.3.8 {
526    execsql {
527      SELECT * FROM sqlite_temp_master WHERE type = 'trigger';
528    }
529  } {}
530}
531
532} ;# ifcapable trigger
533
534# If the build does not include AUTOINCREMENT fields, omit alter-4.*.
535ifcapable autoinc {
536
537do_test alter-4.1 {
538  execsql {
539    CREATE TABLE tbl1(a INTEGER PRIMARY KEY AUTOINCREMENT);
540    INSERT INTO tbl1 VALUES(10);
541  }
542} {}
543do_test alter-4.2 {
544  execsql {
545    INSERT INTO tbl1 VALUES(NULL);
546    SELECT a FROM tbl1;
547  }
548} {10 11}
549do_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}
557do_test alter-4.4 {
558  execsql {
559    DROP TABLE tbl2;
560  }
561} {}
562
563} ;# ifcapable autoinc
564
565# Test that it is Ok to execute an ALTER TABLE immediately after
566# opening a database.
567do_test alter-5.1 {
568  execsql {
569    CREATE TABLE tbl1(a, b, c);
570    INSERT INTO tbl1 VALUES('x', 'y', 'z');
571  }
572} {}
573do_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}
580do_test alter-5.3 {
581  db2 close
582} {}
583
584foreach tblname [execsql {
585  SELECT name FROM sqlite_master
586   WHERE type='table' AND name NOT GLOB 'sqlite*'
587}] {
588  execsql "DROP TABLE \"$tblname\""
589}
590
591set ::tbl_name "abc\uABCDdef"
592do_test alter-6.1 {
593  string length $::tbl_name
594} {7}
595do_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)}"
604execsql "
605  SELECT * FROM ${::tbl_name}
606"
607set ::tbl_name2 "abcXdef"
608do_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)}"
616do_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)}"
624set ::col_name ghi\1234\jkl
625do_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)}"
633set ::col_name2 B\3421\A
634do_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)}"
644do_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}
650
651# Ticket #1665:  Make sure ALTER TABLE ADD COLUMN works on a table
652# that includes a COLLATE clause.
653#
654do_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}
663
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.
666#
667do_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}
677do_test alter-8.2 {
678  execsql {
679    SELECT a, sum(b) FROM t2 GROUP BY a;
680  }
681} {1 18 2 9}
682
683#--------------------------------------------------------------------------
684# alter-9.X - Special test: Make sure the sqlite_rename_trigger() and
685# rename_table() functions do not crash when handed bad input.
686#
687ifcapable trigger {
688  do_test alter-9.1 {
689    execsql {SELECT SQLITE_RENAME_TRIGGER(0,0)}
690  } {{}}
691}
692do_test alter-9.2 {
693  execsql {
694    SELECT SQLITE_RENAME_TABLE(0,0);
695    SELECT SQLITE_RENAME_TABLE(10,20);
696    SELECT SQLITE_RENAME_TABLE('foo', 'foo');
697  }
698} {{} {} {}}
699
700#------------------------------------------------------------------------
701# alter-10.X - Make sure ALTER TABLE works with multi-byte UTF-8 characters
702# in the names.
703#
704do_test alter-10.1 {
705  execsql "CREATE TABLE xyz(x UNIQUE)"
706  execsql "ALTER TABLE xyz RENAME TO xyz\u1234abc"
707  execsql {SELECT name FROM sqlite_master WHERE name GLOB 'xyz*'}
708} [list xyz\u1234abc]
709do_test alter-10.2 {
710  execsql {SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_autoindex*'}
711} [list sqlite_autoindex_xyz\u1234abc_1]
712do_test alter-10.3 {
713  execsql "ALTER TABLE xyz\u1234abc RENAME TO xyzabc"
714  execsql {SELECT name FROM sqlite_master WHERE name GLOB 'xyz*'}
715} [list xyzabc]
716do_test alter-10.4 {
717  execsql {SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_autoindex*'}
718} [list sqlite_autoindex_xyzabc_1]
719
720do_test alter-11.1 {
721  sqlite3_exec db {CREATE TABLE t11(%c6%c6)}
722  execsql {
723    ALTER TABLE t11 ADD COLUMN abc;
724  }
725  catchsql {
726    ALTER TABLE t11 ADD COLUMN abc;
727  }
728} {1 {duplicate column name: abc}}
729set isutf16 [regexp 16 [db one {PRAGMA encoding}]]
730if {!$isutf16} {
731  do_test alter-11.2 {
732    execsql {INSERT INTO t11 VALUES(1,2)}
733    sqlite3_exec db {SELECT %c6%c6 AS xyz, abc FROM t11}
734  } {0 {xyz abc 1 2}}
735}
736do_test alter-11.3 {
737  sqlite3_exec db {CREATE TABLE t11b("%81%82%83" text)}
738  execsql {
739    ALTER TABLE t11b ADD COLUMN abc;
740  }
741  catchsql {
742    ALTER TABLE t11b ADD COLUMN abc;
743  }
744} {1 {duplicate column name: abc}}
745if {!$isutf16} {
746  do_test alter-11.4 {
747    execsql {INSERT INTO t11b VALUES(3,4)}
748    sqlite3_exec db {SELECT %81%82%83 AS xyz, abc FROM t11b}
749  } {0 {xyz abc 3 4}}
750  do_test alter-11.5 {
751    sqlite3_exec db {SELECT [%81%82%83] AS xyz, abc FROM t11b}
752  } {0 {xyz abc 3 4}}
753  do_test alter-11.6 {
754    sqlite3_exec db {SELECT "%81%82%83" AS xyz, abc FROM t11b}
755  } {0 {xyz abc 3 4}}
756}
757do_test alter-11.7 {
758  sqlite3_exec db {CREATE TABLE t11c(%81%82%83 text)}
759  execsql {
760    ALTER TABLE t11c ADD COLUMN abc;
761  }
762  catchsql {
763    ALTER TABLE t11c ADD COLUMN abc;
764  }
765} {1 {duplicate column name: abc}}
766if {!$isutf16} {
767  do_test alter-11.8 {
768    execsql {INSERT INTO t11c VALUES(5,6)}
769    sqlite3_exec db {SELECT %81%82%83 AS xyz, abc FROM t11c}
770  } {0 {xyz abc 5 6}}
771  do_test alter-11.9 {
772    sqlite3_exec db {SELECT [%81%82%83] AS xyz, abc FROM t11c}
773  } {0 {xyz abc 5 6}}
774  do_test alter-11.10 {
775    sqlite3_exec db {SELECT "%81%82%83" AS xyz, abc FROM t11c}
776  } {0 {xyz abc 5 6}}
777}
778
779do_test alter-12.1 {
780  execsql {
781    CREATE TABLE t12(a, b, c);
782    CREATE VIEW v1 AS SELECT * FROM t12;
783  }
784} {}
785do_test alter-12.2 {
786  catchsql {
787    ALTER TABLE v1 RENAME TO v2;
788  }
789} {1 {view v1 may not be altered}}
790do_test alter-12.3 {
791  execsql { SELECT * FROM v1; }
792} {}
793do_test alter-12.4 {
794  db close
795  sqlite3 db test.db
796  execsql { SELECT * FROM v1; }
797} {}
798do_test alter-12.5 {
799  catchsql {
800    ALTER TABLE v1 ADD COLUMN new_column;
801  }
802} {1 {Cannot add a column to a view}}
803
804# Ticket #3102:
805# Verify that comments do not interfere with the table rename
806# algorithm.
807#
808do_test alter-13.1 {
809  execsql {
810    CREATE TABLE /* hi */ t3102a(x);
811    CREATE TABLE t3102b -- comment
812    (y);
813    CREATE INDEX t3102c ON t3102a(x);
814    SELECT name FROM sqlite_master WHERE name GLOB 't3102*' ORDER BY 1;
815  }
816} {t3102a t3102b t3102c}
817do_test alter-13.2 {
818  execsql {
819    ALTER TABLE t3102a RENAME TO t3102a_rename;
820    SELECT name FROM sqlite_master WHERE name GLOB 't3102*' ORDER BY 1;
821  }
822} {t3102a_rename t3102b t3102c}
823do_test alter-13.3 {
824  execsql {
825    ALTER TABLE t3102b RENAME TO t3102b_rename;
826    SELECT name FROM sqlite_master WHERE name GLOB 't3102*' ORDER BY 1;
827  }
828} {t3102a_rename t3102b_rename t3102c}
829
830# Ticket #3651
831do_test alter-14.1 {
832  catchsql {
833    CREATE TABLE t3651(a UNIQUE);
834    ALTER TABLE t3651 ADD COLUMN b UNIQUE;
835  }
836} {1 {Cannot add a UNIQUE column}}
837do_test alter-14.2 {
838  catchsql {
839    ALTER TABLE t3651 ADD COLUMN b PRIMARY KEY;
840  }
841} {1 {Cannot add a PRIMARY KEY column}}
842
843
844#-------------------------------------------------------------------------
845# Test that it is not possible to use ALTER TABLE on any system table.
846#
847set system_table_list {1 sqlite_master}
848catchsql ANALYZE
849ifcapable analyze { lappend system_table_list 2 sqlite_stat1 }
850ifcapable stat3   { lappend system_table_list 3 sqlite_stat3 }
851ifcapable stat4   { lappend system_table_list 4 sqlite_stat4 }
852
853foreach {tn tbl} $system_table_list {
854  do_test alter-15.$tn.1 {
855    catchsql "ALTER TABLE $tbl RENAME TO xyz"
856  } [list 1 "table $tbl may not be altered"]
857
858  do_test alter-15.$tn.2 {
859    catchsql "ALTER TABLE $tbl ADD COLUMN xyz"
860  } [list 1 "table $tbl may not be altered"]
861}
862
863#------------------------------------------------------------------------
864# Verify that ALTER TABLE works on tables with the WITHOUT rowid option.
865#
866do_execsql_test alter-16.1 {
867  CREATE TABLE t16a(a TEXT, b REAL, c INT, PRIMARY KEY(a,b)) WITHOUT rowid;
868  INSERT INTO t16a VALUES('abc',1.25,99);
869  ALTER TABLE t16a ADD COLUMN d TEXT DEFAULT 'xyzzy';
870  INSERT INTO t16a VALUES('cba',5.5,98,'fizzle');
871  SELECT * FROM t16a ORDER BY a;
872} {abc 1.25 99 xyzzy cba 5.5 98 fizzle}
873do_execsql_test alter-16.2 {
874  ALTER TABLE t16a RENAME TO t16a_rn;
875  SELECT * FROM t16a_rn ORDER BY a;
876} {abc 1.25 99 xyzzy cba 5.5 98 fizzle}
877
878#-------------------------------------------------------------------------
879# Verify that NULL values into the internal-use-only sqlite_rename_*()
880# functions do not cause problems.
881#
882do_execsql_test alter-17.1 {
883  SELECT sqlite_rename_table('CREATE TABLE xyz(a,b,c)','abc');
884} {{CREATE TABLE "abc"(a,b,c)}}
885do_execsql_test alter-17.2 {
886  SELECT sqlite_rename_table('CREATE TABLE xyz(a,b,c)',NULL);
887} {{CREATE TABLE "(NULL)"(a,b,c)}}
888do_execsql_test alter-17.3 {
889  SELECT sqlite_rename_table(NULL,'abc');
890} {{}}
891do_execsql_test alter-17.4 {
892  SELECT sqlite_rename_trigger('CREATE TRIGGER r1 ON xyz WHEN','abc');
893} {{CREATE TRIGGER r1 ON "abc" WHEN}}
894do_execsql_test alter-17.5 {
895  SELECT sqlite_rename_trigger('CREATE TRIGGER r1 ON xyz WHEN',NULL);
896} {{CREATE TRIGGER r1 ON "(NULL)" WHEN}}
897do_execsql_test alter-17.6 {
898  SELECT sqlite_rename_trigger(NULL,'abc');
899} {{}}
900do_execsql_test alter-17.7 {
901  SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")',
902         'xyzzy','lmnop');
903} {{CREATE TABLE t1(a REFERENCES "lmnop")}}
904do_execsql_test alter-17.8 {
905  SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")',
906         'xyzzy',NULL);
907} {{CREATE TABLE t1(a REFERENCES "(NULL)")}}
908do_execsql_test alter-17.9 {
909  SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")',
910         NULL, 'lmnop');
911} {{}}
912do_execsql_test alter-17.10 {
913  SELECT sqlite_rename_parent(NULL,'abc','xyz');
914} {{}}
915do_execsql_test alter-17.11 {
916  SELECT sqlite_rename_parent('create references ''','abc','xyz');
917} {{create references '}}
918do_execsql_test alter-17.12 {
919  SELECT sqlite_rename_parent('create references "abc"123" ','abc','xyz');
920} {{create references "xyz"123" }}
921do_execsql_test alter-17.13 {
922  SELECT sqlite_rename_parent("references '''",'abc','xyz');
923} {{references '''}}
924
925finish_test
926