xref: /sqlite-3.40.0/test/table.test (revision c4a64fac)
1# 2001 September 15
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 file is testing the CREATE TABLE statement.
13#
14# $Id: table.test,v 1.52 2009/05/11 20:53:29 drh Exp $
15
16set testdir [file dirname $argv0]
17source $testdir/tester.tcl
18
19# Create a basic table and verify it is added to sqlite_master
20#
21do_test table-1.1 {
22  execsql {
23    CREATE TABLE test1 (
24      one varchar(10),
25      two text
26    )
27  }
28  execsql {
29    SELECT sql FROM sqlite_master WHERE type!='meta'
30  }
31} {{CREATE TABLE test1 (
32      one varchar(10),
33      two text
34    )}}
35
36
37# Verify the other fields of the sqlite_master file.
38#
39do_test table-1.3 {
40  execsql {SELECT name, tbl_name, type FROM sqlite_master WHERE type!='meta'}
41} {test1 test1 table}
42
43# Close and reopen the database.  Verify that everything is
44# still the same.
45#
46do_test table-1.4 {
47  db close
48  sqlite3 db test.db
49  execsql {SELECT name, tbl_name, type from sqlite_master WHERE type!='meta'}
50} {test1 test1 table}
51
52# Drop the database and make sure it disappears.
53#
54do_test table-1.5 {
55  execsql {DROP TABLE test1}
56  execsql {SELECT * FROM sqlite_master WHERE type!='meta'}
57} {}
58
59# Close and reopen the database.  Verify that the table is
60# still gone.
61#
62do_test table-1.6 {
63  db close
64  sqlite3 db test.db
65  execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
66} {}
67
68# Repeat the above steps, but this time quote the table name.
69#
70do_test table-1.10 {
71  execsql {CREATE TABLE "create" (f1 int)}
72  execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
73} {create}
74do_test table-1.11 {
75  execsql {DROP TABLE "create"}
76  execsql {SELECT name FROM "sqlite_master" WHERE type!='meta'}
77} {}
78do_test table-1.12 {
79  execsql {CREATE TABLE test1("f1 ho" int)}
80  execsql {SELECT name as "X" FROM sqlite_master WHERE type!='meta'}
81} {test1}
82do_test table-1.13 {
83  execsql {DROP TABLE "TEST1"}
84  execsql {SELECT name FROM "sqlite_master" WHERE type!='meta'}
85} {}
86
87
88
89# Verify that we cannot make two tables with the same name
90#
91do_test table-2.1 {
92  execsql {CREATE TABLE TEST2(one text)}
93  catchsql {CREATE TABLE test2(two text default 'hi')}
94} {1 {table test2 already exists}}
95do_test table-2.1.1 {
96  catchsql {CREATE TABLE "test2" (two)}
97} {1 {table "test2" already exists}}
98do_test table-2.1b {
99  set v [catch {execsql {CREATE TABLE sqlite_master(two text)}} msg]
100  lappend v $msg
101} {1 {object name reserved for internal use: sqlite_master}}
102do_test table-2.1c {
103  db close
104  sqlite3 db test.db
105  set v [catch {execsql {CREATE TABLE sqlite_master(two text)}} msg]
106  lappend v $msg
107} {1 {object name reserved for internal use: sqlite_master}}
108do_test table-2.1d {
109  catchsql {CREATE TABLE IF NOT EXISTS test2(x,y)}
110} {0 {}}
111do_test table-2.1e {
112  catchsql {CREATE TABLE IF NOT EXISTS test2(x UNIQUE, y TEXT PRIMARY KEY)}
113} {0 {}}
114do_test table-2.1f {
115breakpoint
116  execsql {DROP TABLE test2; SELECT name FROM sqlite_master WHERE type!='meta'}
117} {}
118
119# Verify that we cannot make a table with the same name as an index
120#
121do_test table-2.2a {
122  execsql {CREATE TABLE test2(one text)}
123  execsql {CREATE INDEX test3 ON test2(one)}
124  catchsql {CREATE TABLE test3(two text)}
125} {1 {there is already an index named test3}}
126do_test table-2.2b {
127  db close
128  sqlite3 db test.db
129  set v [catch {execsql {CREATE TABLE test3(two text)}} msg]
130  lappend v $msg
131} {1 {there is already an index named test3}}
132do_test table-2.2c {
133  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
134} {test2 test3}
135do_test table-2.2d {
136  execsql {DROP INDEX test3}
137  set v [catch {execsql {CREATE TABLE test3(two text)}} msg]
138  lappend v $msg
139} {0 {}}
140do_test table-2.2e {
141  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
142} {test2 test3}
143do_test table-2.2f {
144  execsql {DROP TABLE test2; DROP TABLE test3}
145  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
146} {}
147
148# Create a table with many field names
149#
150set big_table \
151{CREATE TABLE big(
152  f1 varchar(20),
153  f2 char(10),
154  f3 varchar(30) primary key,
155  f4 text,
156  f5 text,
157  f6 text,
158  f7 text,
159  f8 text,
160  f9 text,
161  f10 text,
162  f11 text,
163  f12 text,
164  f13 text,
165  f14 text,
166  f15 text,
167  f16 text,
168  f17 text,
169  f18 text,
170  f19 text,
171  f20 text
172)}
173do_test table-3.1 {
174  execsql $big_table
175  execsql {SELECT sql FROM sqlite_master WHERE type=='table'}
176} \{$big_table\}
177do_test table-3.2 {
178  set v [catch {execsql {CREATE TABLE BIG(xyz foo)}} msg]
179  lappend v $msg
180} {1 {table BIG already exists}}
181do_test table-3.3 {
182  set v [catch {execsql {CREATE TABLE biG(xyz foo)}} msg]
183  lappend v $msg
184} {1 {table biG already exists}}
185do_test table-3.4 {
186  set v [catch {execsql {CREATE TABLE bIg(xyz foo)}} msg]
187  lappend v $msg
188} {1 {table bIg already exists}}
189do_test table-3.5 {
190  db close
191  sqlite3 db test.db
192  set v [catch {execsql {CREATE TABLE Big(xyz foo)}} msg]
193  lappend v $msg
194} {1 {table Big already exists}}
195do_test table-3.6 {
196  execsql {DROP TABLE big}
197  execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
198} {}
199
200# Try creating large numbers of tables
201#
202set r {}
203for {set i 1} {$i<=100} {incr i} {
204  lappend r [format test%03d $i]
205}
206do_test table-4.1 {
207  for {set i 1} {$i<=100} {incr i} {
208    set sql "CREATE TABLE [format test%03d $i] ("
209    for {set k 1} {$k<$i} {incr k} {
210      append sql "field$k text,"
211    }
212    append sql "last_field text)"
213    execsql $sql
214  }
215  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
216} $r
217do_test table-4.1b {
218  db close
219  sqlite3 db test.db
220  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
221} $r
222
223# Drop the even numbered tables
224#
225set r {}
226for {set i 1} {$i<=100} {incr i 2} {
227  lappend r [format test%03d $i]
228}
229do_test table-4.2 {
230  for {set i 2} {$i<=100} {incr i 2} {
231    # if {$i==38} {execsql {pragma vdbe_trace=on}}
232    set sql "DROP TABLE [format TEST%03d $i]"
233    execsql $sql
234  }
235  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
236} $r
237#exit
238
239# Drop the odd number tables
240#
241do_test table-4.3 {
242  for {set i 1} {$i<=100} {incr i 2} {
243    set sql "DROP TABLE [format test%03d $i]"
244    execsql $sql
245  }
246  execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
247} {}
248
249# Try to drop a table that does not exist
250#
251do_test table-5.1.1 {
252  catchsql {DROP TABLE test009}
253} {1 {no such table: test009}}
254do_test table-5.1.2 {
255  catchsql {DROP TABLE IF EXISTS test009}
256} {0 {}}
257
258# Try to drop sqlite_master
259#
260do_test table-5.2 {
261  catchsql {DROP TABLE IF EXISTS sqlite_master}
262} {1 {table sqlite_master may not be dropped}}
263
264# Make sure an EXPLAIN does not really create a new table
265#
266do_test table-5.3 {
267  ifcapable {explain} {
268    execsql {EXPLAIN CREATE TABLE test1(f1 int)}
269  }
270  execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
271} {}
272
273# Make sure an EXPLAIN does not really drop an existing table
274#
275do_test table-5.4 {
276  execsql {CREATE TABLE test1(f1 int)}
277  ifcapable {explain} {
278    execsql {EXPLAIN DROP TABLE test1}
279  }
280  execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
281} {test1}
282
283# Create a table with a goofy name
284#
285#do_test table-6.1 {
286#  execsql {CREATE TABLE 'Spaces In This Name!'(x int)}
287#  execsql {INSERT INTO 'spaces in this name!' VALUES(1)}
288#  set list [glob -nocomplain testdb/spaces*.tbl]
289#} {testdb/spaces+in+this+name+.tbl}
290
291# Try using keywords as table names or column names.
292#
293do_test table-7.1 {
294  set v [catch {execsql {
295    CREATE TABLE weird(
296      desc text,
297      asc text,
298      key int,
299      [14_vac] boolean,
300      fuzzy_dog_12 varchar(10),
301      begin blob,
302      end clob
303    )
304  }} msg]
305  lappend v $msg
306} {0 {}}
307do_test table-7.2 {
308  execsql {
309    INSERT INTO weird VALUES('a','b',9,0,'xyz','hi','y''all');
310    SELECT * FROM weird;
311  }
312} {a b 9 0 xyz hi y'all}
313do_test table-7.3 {
314  execsql2 {
315    SELECT * FROM weird;
316  }
317} {desc a asc b key 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}
318do_test table-7.3 {
319  execsql {
320    CREATE TABLE savepoint(release);
321    INSERT INTO savepoint(release) VALUES(10);
322    UPDATE savepoint SET release = 5;
323    SELECT release FROM savepoint;
324  }
325} {5}
326
327# Try out the CREATE TABLE AS syntax
328#
329do_test table-8.1 {
330  execsql2 {
331    CREATE TABLE t2 AS SELECT * FROM weird;
332    SELECT * FROM t2;
333  }
334} {desc a asc b key 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}
335do_test table-8.1.1 {
336  execsql {
337    SELECT sql FROM sqlite_master WHERE name='t2';
338  }
339} {{CREATE TABLE t2(
340  "desc" TEXT,
341  "asc" TEXT,
342  "key" INT,
343  "14_vac" NUM,
344  fuzzy_dog_12 TEXT,
345  "begin",
346  "end" TEXT
347)}}
348do_test table-8.2 {
349  execsql {
350    CREATE TABLE "t3""xyz"(a,b,c);
351    INSERT INTO [t3"xyz] VALUES(1,2,3);
352    SELECT * FROM [t3"xyz];
353  }
354} {1 2 3}
355do_test table-8.3 {
356  execsql2 {
357    CREATE TABLE [t4"abc] AS SELECT count(*) as cnt, max(b+c) FROM [t3"xyz];
358    SELECT * FROM [t4"abc];
359  }
360} {cnt 1 max(b+c) 5}
361
362# Update for v3: The declaration type of anything except a column is now a
363# NULL pointer, so the created table has no column types. (Changed result
364# from {{CREATE TABLE 't4"abc'(cnt NUMERIC,"max(b+c)" NUMERIC)}}).
365do_test table-8.3.1 {
366  execsql {
367    SELECT sql FROM sqlite_master WHERE name='t4"abc'
368  }
369} {{CREATE TABLE "t4""abc"(cnt,"max(b+c)")}}
370
371ifcapable tempdb {
372  do_test table-8.4 {
373    execsql2 {
374      CREATE TEMPORARY TABLE t5 AS SELECT count(*) AS [y'all] FROM [t3"xyz];
375      SELECT * FROM t5;
376    }
377  } {y'all 1}
378}
379
380do_test table-8.5 {
381  db close
382  sqlite3 db test.db
383  execsql2 {
384    SELECT * FROM [t4"abc];
385  }
386} {cnt 1 max(b+c) 5}
387do_test table-8.6 {
388  execsql2 {
389    SELECT * FROM t2;
390  }
391} {desc a asc b key 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}
392do_test table-8.7 {
393  catchsql {
394    SELECT * FROM t5;
395  }
396} {1 {no such table: t5}}
397do_test table-8.8 {
398  catchsql {
399    CREATE TABLE t5 AS SELECT * FROM no_such_table;
400  }
401} {1 {no such table: no_such_table}}
402
403do_test table-8.9 {
404  execsql {
405    CREATE TABLE t10("col.1" [char.3]);
406    CREATE TABLE t11 AS SELECT * FROM t10;
407    SELECT sql FROM sqlite_master WHERE name = 't11';
408  }
409} {{CREATE TABLE t11("col.1" TEXT)}}
410do_test table-8.10 {
411  execsql {
412    CREATE TABLE t12(
413      a INTEGER,
414      b VARCHAR(10),
415      c VARCHAR(1,10),
416      d VARCHAR(+1,-10),
417      e VARCHAR (+1,-10),
418      f "VARCHAR (+1,-10, 5)",
419      g BIG INTEGER
420    );
421    CREATE TABLE t13 AS SELECT * FROM t12;
422    SELECT sql FROM sqlite_master WHERE name = 't13';
423  }
424} {{CREATE TABLE t13(
425  a INT,
426  b TEXT,
427  c TEXT,
428  d TEXT,
429  e TEXT,
430  f TEXT,
431  g INT
432)}}
433
434# Make sure we cannot have duplicate column names within a table.
435#
436do_test table-9.1 {
437  catchsql {
438    CREATE TABLE t6(a,b,a);
439  }
440} {1 {duplicate column name: a}}
441do_test table-9.2 {
442  catchsql {
443    CREATE TABLE t6(a varchar(100), b blob, a integer);
444  }
445} {1 {duplicate column name: a}}
446
447# Check the foreign key syntax.
448#
449ifcapable {foreignkey} {
450do_test table-10.1 {
451  catchsql {
452    CREATE TABLE t6(a REFERENCES t4(a) NOT NULL);
453    INSERT INTO t6 VALUES(NULL);
454  }
455} {1 {t6.a may not be NULL}}
456do_test table-10.2 {
457  catchsql {
458    DROP TABLE t6;
459    CREATE TABLE t6(a REFERENCES t4(a) MATCH PARTIAL);
460  }
461} {0 {}}
462do_test table-10.3 {
463  catchsql {
464    DROP TABLE t6;
465    CREATE TABLE t6(a REFERENCES t4 MATCH FULL ON DELETE SET NULL NOT NULL);
466  }
467} {0 {}}
468do_test table-10.4 {
469  catchsql {
470    DROP TABLE t6;
471    CREATE TABLE t6(a REFERENCES t4 MATCH FULL ON UPDATE SET DEFAULT DEFAULT 1);
472  }
473} {0 {}}
474do_test table-10.5 {
475  catchsql {
476    DROP TABLE t6;
477    CREATE TABLE t6(a NOT NULL NOT DEFERRABLE INITIALLY IMMEDIATE);
478  }
479} {0 {}}
480do_test table-10.6 {
481  catchsql {
482    DROP TABLE t6;
483    CREATE TABLE t6(a NOT NULL DEFERRABLE INITIALLY DEFERRED);
484  }
485} {0 {}}
486do_test table-10.7 {
487  catchsql {
488    DROP TABLE t6;
489    CREATE TABLE t6(a,
490      FOREIGN KEY (a) REFERENCES t4(b) DEFERRABLE INITIALLY DEFERRED
491    );
492  }
493} {0 {}}
494do_test table-10.8 {
495  catchsql {
496    DROP TABLE t6;
497    CREATE TABLE t6(a,b,c,
498      FOREIGN KEY (b,c) REFERENCES t4(x,y) MATCH PARTIAL
499        ON UPDATE SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
500    );
501  }
502} {0 {}}
503do_test table-10.9 {
504  catchsql {
505    DROP TABLE t6;
506    CREATE TABLE t6(a,b,c,
507      FOREIGN KEY (b,c) REFERENCES t4(x)
508    );
509  }
510} {1 {number of columns in foreign key does not match the number of columns in the referenced table}}
511do_test table-10.10 {
512  catchsql {DROP TABLE t6}
513  catchsql {
514    CREATE TABLE t6(a,b,c,
515      FOREIGN KEY (b,c) REFERENCES t4(x,y,z)
516    );
517  }
518} {1 {number of columns in foreign key does not match the number of columns in the referenced table}}
519do_test table-10.11 {
520  catchsql {DROP TABLE t6}
521  catchsql {
522    CREATE TABLE t6(a,b, c REFERENCES t4(x,y));
523  }
524} {1 {foreign key on c should reference only one column of table t4}}
525do_test table-10.12 {
526  catchsql {DROP TABLE t6}
527  catchsql {
528    CREATE TABLE t6(a,b,c,
529      FOREIGN KEY (b,x) REFERENCES t4(x,y)
530    );
531  }
532} {1 {unknown column "x" in foreign key definition}}
533do_test table-10.13 {
534  catchsql {DROP TABLE t6}
535  catchsql {
536    CREATE TABLE t6(a,b,c,
537      FOREIGN KEY (x,b) REFERENCES t4(x,y)
538    );
539  }
540} {1 {unknown column "x" in foreign key definition}}
541} ;# endif foreignkey
542
543# Test for the "typeof" function. More tests for the
544# typeof() function are found in bind.test and types.test.
545#
546do_test table-11.1 {
547  execsql {
548    CREATE TABLE t7(
549       a integer primary key,
550       b number(5,10),
551       c character varying (8),
552       d VARCHAR(9),
553       e clob,
554       f BLOB,
555       g Text,
556       h
557    );
558    INSERT INTO t7(a) VALUES(1);
559    SELECT typeof(a), typeof(b), typeof(c), typeof(d),
560           typeof(e), typeof(f), typeof(g), typeof(h)
561    FROM t7 LIMIT 1;
562  }
563} {integer null null null null null null null}
564do_test table-11.2 {
565  execsql {
566    SELECT typeof(a+b), typeof(a||b), typeof(c+d), typeof(c||d)
567    FROM t7 LIMIT 1;
568  }
569} {null null null null}
570
571# Test that when creating a table using CREATE TABLE AS, column types are
572# assigned correctly for (SELECT ...) and 'x AS y' expressions.
573do_test table-12.1 {
574  ifcapable subquery {
575    execsql {
576      CREATE TABLE t8 AS SELECT b, h, a as i, (SELECT f FROM t7) as j FROM t7;
577    }
578  } else {
579    execsql {
580      CREATE TABLE t8 AS SELECT b, h, a as i, f as j FROM t7;
581    }
582  }
583} {}
584do_test table-12.2 {
585  execsql {
586    SELECT sql FROM sqlite_master WHERE tbl_name = 't8'
587  }
588} {{CREATE TABLE t8(b NUM,h,i INT,j)}}
589
590#--------------------------------------------------------------------
591# Test cases table-13.*
592#
593# Test the ability to have default values of CURRENT_TIME, CURRENT_DATE
594# and CURRENT_TIMESTAMP.
595#
596do_test table-13.1 {
597  execsql {
598    CREATE TABLE tablet8(
599       a integer primary key,
600       tm text DEFAULT CURRENT_TIME,
601       dt text DEFAULT CURRENT_DATE,
602       dttm text DEFAULT CURRENT_TIMESTAMP
603    );
604    SELECT * FROM tablet8;
605  }
606} {}
607set i 0
608foreach {date time seconds} {
609  1976-07-04 12:00:00 205329600
610  1994-04-16 14:00:00 766504800
611  2000-01-01 00:00:00 946684800
612  2003-12-31 12:34:56 1072874096
613} {
614  incr i
615  set sqlite_current_time $seconds
616  do_test table-13.2.$i {
617    execsql "
618      INSERT INTO tablet8(a) VALUES($i);
619      SELECT tm, dt, dttm FROM tablet8 WHERE a=$i;
620    "
621  } [list $time $date [list $date $time]]
622}
623set sqlite_current_time 0
624
625#--------------------------------------------------------------------
626# Test cases table-14.*
627#
628# Test that a table cannot be created or dropped while other virtual
629# machines are active. This is required because otherwise when in
630# auto-vacuum mode the btree-layer may need to move the root-pages of
631# a table for which there is an open cursor.
632#
633# 2007-05-02:  A open btree cursor no longer blocks CREATE TABLE.
634# But DROP TABLE is still prohibited because we do not want to
635# delete a table out from under a running query.
636#
637
638# db eval {
639#   pragma vdbe_trace = 0;
640# }
641# Try to create a table from within a callback:
642unset -nocomplain result
643do_test table-14.1 {
644  set rc [
645    catch {
646      db eval {SELECT * FROM tablet8 LIMIT 1} {} {
647        db eval {CREATE TABLE t9(a, b, c)}
648      }
649    } msg
650  ]
651  set result [list $rc $msg]
652} {0 {}}
653
654# Try to drop a table from within a callback:
655do_test table-14.2 {
656  set rc [
657    catch {
658      db eval {SELECT * FROM tablet8 LIMIT 1} {} {
659        db eval {DROP TABLE t9;}
660      }
661    } msg
662  ]
663  set result [list $rc $msg]
664} {1 {database table is locked}}
665
666ifcapable attach {
667  # Now attach a database and ensure that a table can be created in the
668  # attached database whilst in a callback from a query on the main database.
669  do_test table-14.3 {
670    file delete -force test2.db
671    file delete -force test2.db-journal
672    execsql {
673      ATTACH 'test2.db' as aux;
674    }
675    db eval {SELECT * FROM tablet8 LIMIT 1} {} {
676      db eval {CREATE TABLE aux.t1(a, b, c)}
677    }
678  } {}
679
680  # On the other hand, it should be impossible to drop a table when any VMs
681  # are active. This is because VerifyCookie instructions may have already
682  # been executed, and btree root-pages may not move after this (which a
683  # delete table might do).
684  do_test table-14.4 {
685    set rc [
686      catch {
687        db eval {SELECT * FROM tablet8 LIMIT 1} {} {
688          db eval {DROP TABLE aux.t1;}
689        }
690      } msg
691    ]
692    set result [list $rc $msg]
693  } {1 {database table is locked}}
694}
695
696# Create and drop 2000 tables. This is to check that the balance_shallow()
697# routine works correctly on the sqlite_master table. At one point it
698# contained a bug that would prevent the right-child pointer of the
699# child page from being copied to the root page.
700#
701do_test table-15.1 {
702  execsql {BEGIN}
703  for {set i 0} {$i<2000} {incr i} {
704    execsql "CREATE TABLE tbl$i (a, b, c)"
705  }
706  execsql {COMMIT}
707} {}
708do_test table-15.2 {
709  execsql {BEGIN}
710  for {set i 0} {$i<2000} {incr i} {
711    execsql "DROP TABLE tbl$i"
712  }
713  execsql {COMMIT}
714} {}
715
716finish_test
717