xref: /sqlite-3.40.0/test/alter2.test (revision 4dcbdbff)
1# 2005 February 18
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 ... ADD COLUMN".
15#
16# $Id: alter2.test,v 1.4 2005/03/10 12:52:47 drh Exp $
17#
18
19set testdir [file dirname $argv0]
20source $testdir/tester.tcl
21
22# We have to have pragmas in order to do this test
23ifcapable {!pragma} return
24
25# These tests do not work if there is a codec.  The
26# btree_open command does not know how to handle codecs.
27#
28if {[catch {sqlite3 -has_codec} r] || $r} return
29
30# The file format change affects the way row-records stored in tables (but
31# not indices) are interpreted. Before version 3.1.3, a row-record for a
32# table with N columns was guaranteed to contain exactly N fields. As
33# of version 3.1.3, the record may contain up to N fields. In this case
34# the M fields that are present are the values for the left-most M
35# columns. The (N-M) rightmost columns contain NULL.
36#
37# If any records in the database contain less fields than their table
38# has columns, then the file-format meta value should be set to (at least) 2.
39#
40
41# This procedure sets the value of the file-format in file 'test.db'
42# to $newval. Also, the schema cookie is incremented.
43#
44proc set_file_format {newval} {
45  set bt [btree_open test.db 10 0]
46  btree_begin_transaction $bt
47  set meta [btree_get_meta $bt]
48  lset meta 2 $newval                    ;# File format
49  lset meta 1 [expr [lindex $meta 1]+1]  ;# Schema cookie
50  eval "btree_update_meta $bt $meta"
51  btree_commit $bt
52  btree_close $bt
53}
54
55# This procedure returns the value of the file-format in file 'test.db'.
56#
57proc get_file_format {{fname test.db}} {
58  set bt [btree_open $fname 10 0]
59  set meta [btree_get_meta $bt]
60  btree_close $bt
61  lindex $meta 2
62}
63
64# This procedure sets the SQL statement stored for table $tbl in the
65# sqlite_master table of file 'test.db' to $sql. Also set the file format
66# to the supplied value. This is 2 if the added column has a default that is
67# NULL, or 3 otherwise.
68#
69proc alter_table {tbl sql {file_format 2}} {
70  sqlite3 dbat test.db
71puts one
72  dbat eval {
73    PRAGMA writable_schema = 1;
74    UPDATE sqlite_master SET sql = $sql WHERE name = $tbl AND type = 'table';
75    PRAGMA writable_schema = 0;
76  }
77puts two
78  dbat close
79puts three
80  set_file_format 2
81puts four
82}
83
84#-----------------------------------------------------------------------
85# Some basic tests to make sure short rows are handled.
86#
87do_test alter2-1.1 {
88  execsql {
89    CREATE TABLE abc(a, b);
90    INSERT INTO abc VALUES(1, 2);
91    INSERT INTO abc VALUES(3, 4);
92    INSERT INTO abc VALUES(5, 6);
93  }
94} {}
95do_test alter2-1.2 {
96  # ALTER TABLE abc ADD COLUMN c;
97  alter_table abc {CREATE TABLE abc(a, b, c);}
98} {}
99exit
100do_test alter2-1.3 {
101  execsql {
102    SELECT * FROM abc;
103  }
104} {1 2 {} 3 4 {} 5 6 {}}
105do_test alter2-1.4 {
106  execsql {
107    UPDATE abc SET c = 10 WHERE a = 1;
108    SELECT * FROM abc;
109  }
110} {1 2 10 3 4 {} 5 6 {}}
111do_test alter2-1.5 {
112  execsql {
113    CREATE INDEX abc_i ON abc(c);
114  }
115} {}
116do_test alter2-1.6 {
117  execsql {
118    SELECT c FROM abc ORDER BY c;
119  }
120} {{} {} 10}
121do_test alter2-1.7 {
122  execsql {
123    SELECT * FROM abc WHERE c = 10;
124  }
125} {1 2 10}
126do_test alter2-1.8 {
127  execsql {
128    SELECT sum(a), c FROM abc GROUP BY c;
129  }
130} {8.0 {} 1.0 10}
131do_test alter2-1.9 {
132  # ALTER TABLE abc ADD COLUMN d;
133  alter_table abc {CREATE TABLE abc(a, b, c, d);}
134  execsql { SELECT * FROM abc; }
135  execsql {
136    UPDATE abc SET d = 11 WHERE c IS NULL AND a<4;
137    SELECT * FROM abc;
138  }
139} {1 2 10 {} 3 4 {} 11 5 6 {} {}}
140do_test alter2-1.10 {
141  execsql {
142    SELECT typeof(d) FROM abc;
143  }
144} {null integer null}
145do_test alter2-1.99 {
146  execsql {
147    DROP TABLE abc;
148  }
149} {}
150
151#-----------------------------------------------------------------------
152# Test that views work when the underlying table structure is changed.
153#
154ifcapable view {
155  do_test alter2-2.1 {
156    execsql {
157      CREATE TABLE abc2(a, b, c);
158      INSERT INTO abc2 VALUES(1, 2, 10);
159      INSERT INTO abc2 VALUES(3, 4, NULL);
160      INSERT INTO abc2 VALUES(5, 6, NULL);
161      CREATE VIEW abc2_v AS SELECT * FROM abc2;
162      SELECT * FROM abc2_v;
163    }
164  } {1 2 10 3 4 {} 5 6 {}}
165  do_test alter2-2.2 {
166    # ALTER TABLE abc ADD COLUMN d;
167    alter_table abc2 {CREATE TABLE abc2(a, b, c, d);}
168    execsql {
169      SELECT * FROM abc2_v;
170    }
171  } {1 2 10 {} 3 4 {} {} 5 6 {} {}}
172  do_test alter2-2.3 {
173    execsql {
174      DROP TABLE abc2;
175      DROP VIEW abc2_v;
176    }
177  } {}
178}
179
180#-----------------------------------------------------------------------
181# Test that triggers work when a short row is copied to the old.*
182# trigger pseudo-table.
183#
184ifcapable trigger {
185  do_test alter2-3.1 {
186    execsql {
187      CREATE TABLE abc3(a, b);
188      CREATE TABLE blog(o, n);
189      CREATE TRIGGER abc3_t AFTER UPDATE OF b ON abc3 BEGIN
190        INSERT INTO blog VALUES(old.b, new.b);
191      END;
192    }
193  } {}
194  do_test alter2-3.2 {
195    execsql {
196      INSERT INTO abc3 VALUES(1, 4);
197      UPDATE abc3 SET b = 2 WHERE b = 4;
198      SELECT * FROM blog;
199    }
200  } {4 2}
201  do_test alter2-3.3 {
202    execsql {
203      INSERT INTO abc3 VALUES(3, 4);
204      INSERT INTO abc3 VALUES(5, 6);
205    }
206    alter_table abc3 {CREATE TABLE abc3(a, b, c);}
207    execsql {
208      SELECT * FROM abc3;
209    }
210  } {1 2 {} 3 4 {} 5 6 {}}
211  do_test alter2-3.4 {
212    execsql {
213      UPDATE abc3 SET b = b*2 WHERE a<4;
214      SELECT * FROM abc3;
215    }
216  } {1 4 {} 3 8 {} 5 6 {}}
217  do_test alter2-3.5 {
218    execsql {
219      SELECT * FROM blog;
220    }
221  } {4 2 2 4 4 8}
222
223  do_test alter2-3.6 {
224    execsql {
225      CREATE TABLE clog(o, n);
226      CREATE TRIGGER abc3_t2 AFTER UPDATE OF c ON abc3 BEGIN
227        INSERT INTO clog VALUES(old.c, new.c);
228      END;
229      UPDATE abc3 SET c = a*2;
230      SELECT * FROM clog;
231    }
232  } {{} 2 {} 6 {} 10}
233}
234
235#---------------------------------------------------------------------
236# Check that an error occurs if the database is upgraded to a file
237# format that SQLite does not support (in this case 4). Note: The
238# file format is checked each time the schema is read, so changing the
239# file format requires incrementing the schema cookie.
240#
241do_test alter2-4.1 {
242  set_file_format 4
243} {}
244do_test alter2-4.2 {
245  catchsql {
246    SELECT * FROM sqlite_master;
247  }
248} {1 {unsupported file format}}
249do_test alter2-4.3 {
250  sqlite3_errcode $::DB
251} {SQLITE_ERROR}
252do_test alter2-4.4 {
253  db close
254  set ::DB [sqlite3 db test.db]
255  catchsql {
256    SELECT * FROM sqlite_master;
257  }
258} {1 {unsupported file format}}
259do_test alter2-4.5 {
260  sqlite3_errcode $::DB
261} {SQLITE_ERROR}
262
263#---------------------------------------------------------------------
264# Check that executing VACUUM on a file with file-format version 2
265# resets the file format to 1.
266#
267do_test alter2-5.1 {
268  set_file_format 2
269  get_file_format
270} {2}
271do_test alter2-5.2 {
272  execsql {
273    VACUUM;
274  }
275} {}
276do_test alter2-5.3 {
277  get_file_format
278} {1}
279
280#---------------------------------------------------------------------
281# Test that when a database with file-format 2 is opened, new
282# databases are still created with file-format 1.
283#
284do_test alter2-6.1 {
285  db close
286  set_file_format 2
287  set ::DB [sqlite3 db test.db]
288  get_file_format
289} {2}
290do_test alter2-6.2 {
291  file delete -force test2.db-journal
292  file delete -force test2.db
293  execsql {
294    ATTACH 'test2.db' AS aux;
295    CREATE TABLE aux.t1(a, b);
296  }
297  get_file_format test2.db
298} {1}
299do_test alter2-6.3 {
300  execsql {
301    CREATE TABLE t1(a, b);
302  }
303  get_file_format
304} {2}
305
306#---------------------------------------------------------------------
307# Test that types and values for columns added with default values
308# other than NULL work with SELECT statements.
309#
310do_test alter2-7.1 {
311  execsql {
312    DROP TABLE t1;
313    CREATE TABLE t1(a);
314    INSERT INTO t1 VALUES(1);
315    INSERT INTO t1 VALUES(2);
316    INSERT INTO t1 VALUES(3);
317    INSERT INTO t1 VALUES(4);
318    SELECT * FROM t1;
319  }
320} {1 2 3 4}
321do_test alter2-7.2 {
322  set sql {CREATE TABLE t1(a, b DEFAULT '123', c INTEGER DEFAULT '123')}
323  alter_table t1 $sql 3
324  execsql {
325    SELECT * FROM t1 LIMIT 1;
326  }
327} {1 123 123}
328do_test alter2-7.3 {
329  execsql {
330    SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1;
331  }
332} {1 integer 123 text 123 integer}
333do_test alter2-7.4 {
334  execsql {
335    SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1;
336  }
337} {1 integer 123 text 123 integer}
338do_test alter2-7.5 {
339  set sql {CREATE TABLE t1(a, b DEFAULT -123.0, c VARCHAR(10) default 5)}
340  alter_table t1 $sql 3
341  execsql {
342    SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1;
343  }
344} {1 integer -123.0 real 5 text}
345
346#-----------------------------------------------------------------------
347# Test that UPDATE trigger tables work with default values, and that when
348# a row is updated the default values are correctly transfered to the
349# new row.
350#
351ifcapable trigger {
352db function set_val {set ::val}
353  do_test alter2-8.1 {
354    execsql {
355      CREATE TRIGGER trig1 BEFORE UPDATE ON t1 BEGIN
356      SELECT set_val(
357          old.b||' '||typeof(old.b)||' '||old.c||' '||typeof(old.c)||' '||
358          new.b||' '||typeof(new.b)||' '||new.c||' '||typeof(new.c)
359      );
360      END;
361    }
362    list
363  } {}
364}
365do_test alter2-8.2 {
366  execsql {
367    UPDATE t1 SET c = 10 WHERE a = 1;
368    SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM t1 LIMIT 1;
369  }
370} {1 integer -123.0 real 10 text}
371ifcapable trigger {
372  do_test alter2-8.3 {
373    set ::val
374  } {-123 real 5 text -123 real 10 text}
375}
376
377#-----------------------------------------------------------------------
378# Test that DELETE trigger tables work with default values, and that when
379# a row is updated the default values are correctly transfered to the
380# new row.
381#
382ifcapable trigger {
383  do_test alter2-9.1 {
384    execsql {
385      CREATE TRIGGER trig2 BEFORE DELETE ON t1 BEGIN
386      SELECT set_val(
387          old.b||' '||typeof(old.b)||' '||old.c||' '||typeof(old.c)
388      );
389      END;
390    }
391    list
392  } {}
393  do_test alter2-9.2 {
394    execsql {
395      DELETE FROM t1 WHERE a = 2;
396    }
397    set ::val
398  } {-123 real 5 text}
399}
400
401#-----------------------------------------------------------------------
402# Test creating an index on a column added with a default value.
403#
404do_test alter2-10.1 {
405  execsql {
406    CREATE TABLE t2(a);
407    INSERT INTO t2 VALUES('a');
408    INSERT INTO t2 VALUES('b');
409    INSERT INTO t2 VALUES('c');
410    INSERT INTO t2 VALUES('d');
411  }
412  alter_table t2 {CREATE TABLE t2(a, b DEFAULT X'ABCD', c DEFAULT NULL);} 3
413  catchsql {
414    SELECT * FROM sqlite_master;
415  }
416  execsql {
417    SELECT quote(a), quote(b), quote(c) FROM t2 LIMIT 1;
418  }
419} {'a' X'ABCD' NULL}
420do_test alter2-10.2 {
421  execsql {
422    CREATE INDEX i1 ON t2(b);
423    SELECT a FROM t2 WHERE b = X'ABCD';
424  }
425} {a b c d}
426do_test alter2-10.3 {
427  execsql {
428    DELETE FROM t2 WHERE a = 'c';
429    SELECT a FROM t2 WHERE b = X'ABCD';
430  }
431} {a b d}
432do_test alter2-10.4 {
433  execsql {
434    SELECT count(b) FROM t2 WHERE b = X'ABCD';
435  }
436} {3}
437
438finish_test
439