| # 2001 September 15 | |
| # | |
| # The author disclaims copyright to this source code. In place of | |
| # a legal notice, here is a blessing: | |
| # | |
| # May you do good and not evil. | |
| # May you find forgiveness for yourself and forgive others. | |
| # May you share freely, never taking more than you give. | |
| # | |
| #*********************************************************************** | |
| # This file implements regression tests for SQLite library. The | |
| # focus of this file is testing the CREATE TABLE statement. | |
| # | |
| set testdir [file dirname $argv0] | |
| source $testdir/tester.tcl | |
| # Create a basic table and verify it is added to sqlite_master | |
| # | |
| do_test table-1.1 { | |
| execsql { | |
| CREATE TABLE test1 ( | |
| one varchar(10), | |
| two text | |
| ) | |
| } | |
| execsql { | |
| SELECT sql FROM sqlite_master WHERE type!='meta' | |
| } | |
| } {{CREATE TABLE test1 ( | |
| one varchar(10), | |
| two text | |
| )}} | |
| # Verify the other fields of the sqlite_master file. | |
| # | |
| do_test table-1.3 { | |
| execsql {SELECT name, tbl_name, type FROM sqlite_master WHERE type!='meta'} | |
| } {test1 test1 table} | |
| # Close and reopen the database. Verify that everything is | |
| # still the same. | |
| # | |
| do_test table-1.4 { | |
| db close | |
| sqlite3 db test.db | |
| execsql {SELECT name, tbl_name, type from sqlite_master WHERE type!='meta'} | |
| } {test1 test1 table} | |
| # Drop the database and make sure it disappears. | |
| # | |
| do_test table-1.5 { | |
| execsql {DROP TABLE test1} | |
| execsql {SELECT * FROM sqlite_master WHERE type!='meta'} | |
| } {} | |
| # Close and reopen the database. Verify that the table is | |
| # still gone. | |
| # | |
| do_test table-1.6 { | |
| db close | |
| sqlite3 db test.db | |
| execsql {SELECT name FROM sqlite_master WHERE type!='meta'} | |
| } {} | |
| # Repeat the above steps, but this time quote the table name. | |
| # | |
| do_test table-1.10 { | |
| execsql {CREATE TABLE "create" (f1 int)} | |
| execsql {SELECT name FROM sqlite_master WHERE type!='meta'} | |
| } {create} | |
| do_test table-1.11 { | |
| execsql {DROP TABLE "create"} | |
| execsql {SELECT name FROM "sqlite_master" WHERE type!='meta'} | |
| } {} | |
| do_test table-1.12 { | |
| execsql {CREATE TABLE test1("f1 ho" int)} | |
| execsql {SELECT name as "X" FROM sqlite_master WHERE type!='meta'} | |
| } {test1} | |
| do_test table-1.13 { | |
| execsql {DROP TABLE "TEST1"} | |
| execsql {SELECT name FROM "sqlite_master" WHERE type!='meta'} | |
| } {} | |
| # Verify that we cannot make two tables with the same name | |
| # | |
| do_test table-2.1 { | |
| execsql {CREATE TABLE TEST2(one text)} | |
| catchsql {CREATE TABLE test2(two text default 'hi')} | |
| } {1 {table test2 already exists}} | |
| do_test table-2.1.1 { | |
| catchsql {CREATE TABLE "test2" (two)} | |
| } {1 {table "test2" already exists}} | |
| do_test table-2.1b { | |
| set v [catch {execsql {CREATE TABLE sqlite_master(two text)}} msg] | |
| lappend v $msg | |
| } {1 {object name reserved for internal use: sqlite_master}} | |
| do_test table-2.1c { | |
| db close | |
| sqlite3 db test.db | |
| set v [catch {execsql {CREATE TABLE sqlite_master(two text)}} msg] | |
| lappend v $msg | |
| } {1 {object name reserved for internal use: sqlite_master}} | |
| do_test table-2.1d { | |
| catchsql {CREATE TABLE IF NOT EXISTS test2(x,y)} | |
| } {0 {}} | |
| do_test table-2.1e { | |
| catchsql {CREATE TABLE IF NOT EXISTS test2(x UNIQUE, y TEXT PRIMARY KEY)} | |
| } {0 {}} | |
| do_test table-2.1f { | |
| execsql {DROP TABLE test2; SELECT name FROM sqlite_master WHERE type!='meta'} | |
| } {} | |
| # Verify that we cannot make a table with the same name as an index | |
| # | |
| do_test table-2.2a { | |
| execsql {CREATE TABLE test2(one text)} | |
| execsql {CREATE INDEX test3 ON test2(one)} | |
| catchsql {CREATE TABLE test3(two text)} | |
| } {1 {there is already an index named test3}} | |
| do_test table-2.2b { | |
| db close | |
| sqlite3 db test.db | |
| set v [catch {execsql {CREATE TABLE test3(two text)}} msg] | |
| lappend v $msg | |
| } {1 {there is already an index named test3}} | |
| do_test table-2.2c { | |
| execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name} | |
| } {test2 test3} | |
| do_test table-2.2d { | |
| execsql {DROP INDEX test3} | |
| set v [catch {execsql {CREATE TABLE test3(two text)}} msg] | |
| lappend v $msg | |
| } {0 {}} | |
| do_test table-2.2e { | |
| execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name} | |
| } {test2 test3} | |
| do_test table-2.2f { | |
| execsql {DROP TABLE test2; DROP TABLE test3} | |
| execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name} | |
| } {} | |
| # Create a table with many field names | |
| # | |
| set big_table \ | |
| {CREATE TABLE big( | |
| f1 varchar(20), | |
| f2 char(10), | |
| f3 varchar(30) primary key, | |
| f4 text, | |
| f5 text, | |
| f6 text, | |
| f7 text, | |
| f8 text, | |
| f9 text, | |
| f10 text, | |
| f11 text, | |
| f12 text, | |
| f13 text, | |
| f14 text, | |
| f15 text, | |
| f16 text, | |
| f17 text, | |
| f18 text, | |
| f19 text, | |
| f20 text | |
| )} | |
| do_test table-3.1 { | |
| execsql $big_table | |
| execsql {SELECT sql FROM sqlite_master WHERE type=='table'} | |
| } \{$big_table\} | |
| do_test table-3.2 { | |
| set v [catch {execsql {CREATE TABLE BIG(xyz foo)}} msg] | |
| lappend v $msg | |
| } {1 {table BIG already exists}} | |
| do_test table-3.3 { | |
| set v [catch {execsql {CREATE TABLE biG(xyz foo)}} msg] | |
| lappend v $msg | |
| } {1 {table biG already exists}} | |
| do_test table-3.4 { | |
| set v [catch {execsql {CREATE TABLE bIg(xyz foo)}} msg] | |
| lappend v $msg | |
| } {1 {table bIg already exists}} | |
| do_test table-3.5 { | |
| db close | |
| sqlite3 db test.db | |
| set v [catch {execsql {CREATE TABLE Big(xyz foo)}} msg] | |
| lappend v $msg | |
| } {1 {table Big already exists}} | |
| do_test table-3.6 { | |
| execsql {DROP TABLE big} | |
| execsql {SELECT name FROM sqlite_master WHERE type!='meta'} | |
| } {} | |
| # Try creating large numbers of tables | |
| # | |
| set r {} | |
| for {set i 1} {$i<=100} {incr i} { | |
| lappend r [format test%03d $i] | |
| } | |
| do_test table-4.1 { | |
| for {set i 1} {$i<=100} {incr i} { | |
| set sql "CREATE TABLE [format test%03d $i] (" | |
| for {set k 1} {$k<$i} {incr k} { | |
| append sql "field$k text," | |
| } | |
| append sql "last_field text)" | |
| execsql $sql | |
| } | |
| execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name} | |
| } $r | |
| do_test table-4.1b { | |
| db close | |
| sqlite3 db test.db | |
| execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name} | |
| } $r | |
| # Drop the even numbered tables | |
| # | |
| set r {} | |
| for {set i 1} {$i<=100} {incr i 2} { | |
| lappend r [format test%03d $i] | |
| } | |
| do_test table-4.2 { | |
| for {set i 2} {$i<=100} {incr i 2} { | |
| # if {$i==38} {execsql {pragma vdbe_trace=on}} | |
| set sql "DROP TABLE [format TEST%03d $i]" | |
| execsql $sql | |
| } | |
| execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name} | |
| } $r | |
| #exit | |
| # Drop the odd number tables | |
| # | |
| do_test table-4.3 { | |
| for {set i 1} {$i<=100} {incr i 2} { | |
| set sql "DROP TABLE [format test%03d $i]" | |
| execsql $sql | |
| } | |
| execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name} | |
| } {} | |
| # Try to drop a table that does not exist | |
| # | |
| do_test table-5.1.1 { | |
| catchsql {DROP TABLE test009} | |
| } {1 {no such table: test009}} | |
| do_test table-5.1.2 { | |
| catchsql {DROP TABLE IF EXISTS test009} | |
| } {0 {}} | |
| # Try to drop sqlite_master | |
| # | |
| do_test table-5.2 { | |
| catchsql {DROP TABLE IF EXISTS sqlite_master} | |
| } {1 {table sqlite_master may not be dropped}} | |
| # Dropping sqlite_statN tables is OK. | |
| # | |
| do_test table-5.2.1 { | |
| db eval { | |
| ANALYZE; | |
| DROP TABLE IF EXISTS sqlite_stat1; | |
| DROP TABLE IF EXISTS sqlite_stat2; | |
| DROP TABLE IF EXISTS sqlite_stat3; | |
| DROP TABLE IF EXISTS sqlite_stat4; | |
| SELECT name FROM sqlite_master WHERE name GLOB 'sqlite_stat*'; | |
| } | |
| } {} | |
| do_test table-5.2.2 { | |
| db close | |
| forcedelete test.db | |
| sqlite3 db test.db | |
| db eval { | |
| CREATE TABLE t0(a,b); | |
| CREATE INDEX t ON t0(a); | |
| PRAGMA writable_schema=ON; | |
| UPDATE sqlite_master SET sql='CREATE TABLE a.b(a UNIQUE'; | |
| BEGIN; | |
| CREATE TABLE t1(x); | |
| ROLLBACK; | |
| DROP TABLE IF EXISTS t99; | |
| } | |
| } {} | |
| db close | |
| forcedelete test.db | |
| sqlite3 db test.db | |
| # Make sure an EXPLAIN does not really create a new table | |
| # | |
| do_test table-5.3 { | |
| ifcapable {explain} { | |
| execsql {EXPLAIN CREATE TABLE test1(f1 int)} | |
| } | |
| execsql {SELECT name FROM sqlite_master WHERE type!='meta'} | |
| } {} | |
| # Make sure an EXPLAIN does not really drop an existing table | |
| # | |
| do_test table-5.4 { | |
| execsql {CREATE TABLE test1(f1 int)} | |
| ifcapable {explain} { | |
| execsql {EXPLAIN DROP TABLE test1} | |
| } | |
| execsql {SELECT name FROM sqlite_master WHERE type!='meta'} | |
| } {test1} | |
| # Create a table with a goofy name | |
| # | |
| #do_test table-6.1 { | |
| # execsql {CREATE TABLE 'Spaces In This Name!'(x int)} | |
| # execsql {INSERT INTO 'spaces in this name!' VALUES(1)} | |
| # set list [glob -nocomplain testdb/spaces*.tbl] | |
| #} {testdb/spaces+in+this+name+.tbl} | |
| # Try using keywords as table names or column names. | |
| # | |
| do_test table-7.1 { | |
| set v [catch {execsql { | |
| CREATE TABLE weird( | |
| desc text, | |
| asc text, | |
| key int, | |
| [14_vac] boolean, | |
| fuzzy_dog_12 varchar(10), | |
| begin blob, | |
| end clob | |
| ) | |
| }} msg] | |
| lappend v $msg | |
| } {0 {}} | |
| do_test table-7.2 { | |
| execsql { | |
| INSERT INTO weird VALUES('a','b',9,0,'xyz','hi','y''all'); | |
| SELECT * FROM weird; | |
| } | |
| } {a b 9 0 xyz hi y'all} | |
| do_test table-7.3 { | |
| execsql2 { | |
| SELECT * FROM weird; | |
| } | |
| } {desc a asc b key 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all} | |
| do_test table-7.3 { | |
| execsql { | |
| CREATE TABLE savepoint(release); | |
| INSERT INTO savepoint(release) VALUES(10); | |
| UPDATE savepoint SET release = 5; | |
| SELECT release FROM savepoint; | |
| } | |
| } {5} | |
| # Try out the CREATE TABLE AS syntax | |
| # | |
| do_test table-8.1 { | |
| execsql2 { | |
| CREATE TABLE t2 AS SELECT * FROM weird; | |
| SELECT * FROM t2; | |
| } | |
| } {desc a asc b key 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all} | |
| do_test table-8.1.1 { | |
| execsql { | |
| SELECT sql FROM sqlite_master WHERE name='t2'; | |
| } | |
| } {{CREATE TABLE t2( | |
| "desc" TEXT, | |
| "asc" TEXT, | |
| "key" INT, | |
| "14_vac" NUM, | |
| fuzzy_dog_12 TEXT, | |
| "begin", | |
| "end" TEXT | |
| )}} | |
| do_test table-8.2 { | |
| execsql { | |
| CREATE TABLE "t3""xyz"(a,b,c); | |
| INSERT INTO [t3"xyz] VALUES(1,2,3); | |
| SELECT * FROM [t3"xyz]; | |
| } | |
| } {1 2 3} | |
| do_test table-8.3 { | |
| execsql2 { | |
| CREATE TABLE [t4"abc] AS SELECT count(*) as cnt, max(b+c) FROM [t3"xyz]; | |
| SELECT * FROM [t4"abc]; | |
| } | |
| } {cnt 1 max(b+c) 5} | |
| # Update for v3: The declaration type of anything except a column is now a | |
| # NULL pointer, so the created table has no column types. (Changed result | |
| # from {{CREATE TABLE 't4"abc'(cnt NUMERIC,"max(b+c)" NUMERIC)}}). | |
| do_test table-8.3.1 { | |
| execsql { | |
| SELECT sql FROM sqlite_master WHERE name='t4"abc' | |
| } | |
| } {{CREATE TABLE "t4""abc"(cnt,"max(b+c)")}} | |
| ifcapable tempdb { | |
| do_test table-8.4 { | |
| execsql2 { | |
| CREATE TEMPORARY TABLE t5 AS SELECT count(*) AS [y'all] FROM [t3"xyz]; | |
| SELECT * FROM t5; | |
| } | |
| } {y'all 1} | |
| } | |
| do_test table-8.5 { | |
| db close | |
| sqlite3 db test.db | |
| execsql2 { | |
| SELECT * FROM [t4"abc]; | |
| } | |
| } {cnt 1 max(b+c) 5} | |
| do_test table-8.6 { | |
| execsql2 { | |
| SELECT * FROM t2; | |
| } | |
| } {desc a asc b key 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all} | |
| do_test table-8.7 { | |
| catchsql { | |
| SELECT * FROM t5; | |
| } | |
| } {1 {no such table: t5}} | |
| do_test table-8.8 { | |
| catchsql { | |
| CREATE TABLE t5 AS SELECT * FROM no_such_table; | |
| } | |
| } {1 {no such table: no_such_table}} | |
| do_test table-8.9 { | |
| execsql { | |
| CREATE TABLE t10("col.1" [char.3]); | |
| CREATE TABLE t11 AS SELECT * FROM t10; | |
| SELECT sql FROM sqlite_master WHERE name = 't11'; | |
| } | |
| } {{CREATE TABLE t11("col.1" TEXT)}} | |
| do_test table-8.10 { | |
| execsql { | |
| CREATE TABLE t12( | |
| a INTEGER, | |
| b VARCHAR(10), | |
| c VARCHAR(1,10), | |
| d VARCHAR(+1,-10), | |
| e VARCHAR (+1,-10), | |
| f "VARCHAR (+1,-10, 5)", | |
| g BIG INTEGER | |
| ); | |
| CREATE TABLE t13 AS SELECT * FROM t12; | |
| SELECT sql FROM sqlite_master WHERE name = 't13'; | |
| } | |
| } {{CREATE TABLE t13( | |
| a INT, | |
| b TEXT, | |
| c TEXT, | |
| d TEXT, | |
| e TEXT, | |
| f TEXT, | |
| g INT | |
| )}} | |
| # Make sure we cannot have duplicate column names within a table. | |
| # | |
| do_test table-9.1 { | |
| catchsql { | |
| CREATE TABLE t6(a,b,a); | |
| } | |
| } {1 {duplicate column name: a}} | |
| do_test table-9.2 { | |
| catchsql { | |
| CREATE TABLE t6(a varchar(100), b blob, a integer); | |
| } | |
| } {1 {duplicate column name: a}} | |
| # Check the foreign key syntax. | |
| # | |
| ifcapable {foreignkey} { | |
| do_test table-10.1 { | |
| catchsql { | |
| CREATE TABLE t6(a REFERENCES t4(a) NOT NULL); | |
| INSERT INTO t6 VALUES(NULL); | |
| } | |
| } {1 {NOT NULL constraint failed: t6.a}} | |
| do_test table-10.2 { | |
| catchsql { | |
| DROP TABLE t6; | |
| CREATE TABLE t6(a REFERENCES t4(a) MATCH PARTIAL); | |
| } | |
| } {0 {}} | |
| do_test table-10.3 { | |
| catchsql { | |
| DROP TABLE t6; | |
| CREATE TABLE t6(a REFERENCES t4 MATCH FULL ON DELETE SET NULL NOT NULL); | |
| } | |
| } {0 {}} | |
| do_test table-10.4 { | |
| catchsql { | |
| DROP TABLE t6; | |
| CREATE TABLE t6(a REFERENCES t4 MATCH FULL ON UPDATE SET DEFAULT DEFAULT 1); | |
| } | |
| } {0 {}} | |
| do_test table-10.5 { | |
| catchsql { | |
| DROP TABLE t6; | |
| CREATE TABLE t6(a NOT NULL NOT DEFERRABLE INITIALLY IMMEDIATE); | |
| } | |
| } {0 {}} | |
| do_test table-10.6 { | |
| catchsql { | |
| DROP TABLE t6; | |
| CREATE TABLE t6(a NOT NULL DEFERRABLE INITIALLY DEFERRED); | |
| } | |
| } {0 {}} | |
| do_test table-10.7 { | |
| catchsql { | |
| DROP TABLE t6; | |
| CREATE TABLE t6(a, | |
| FOREIGN KEY (a) REFERENCES t4(b) DEFERRABLE INITIALLY DEFERRED | |
| ); | |
| } | |
| } {0 {}} | |
| do_test table-10.8 { | |
| catchsql { | |
| DROP TABLE t6; | |
| CREATE TABLE t6(a,b,c, | |
| FOREIGN KEY (b,c) REFERENCES t4(x,y) MATCH PARTIAL | |
| ON UPDATE SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED | |
| ); | |
| } | |
| } {0 {}} | |
| do_test table-10.9 { | |
| catchsql { | |
| DROP TABLE t6; | |
| CREATE TABLE t6(a,b,c, | |
| FOREIGN KEY (b,c) REFERENCES t4(x) | |
| ); | |
| } | |
| } {1 {number of columns in foreign key does not match the number of columns in the referenced table}} | |
| do_test table-10.10 { | |
| catchsql {DROP TABLE t6} | |
| catchsql { | |
| CREATE TABLE t6(a,b,c, | |
| FOREIGN KEY (b,c) REFERENCES t4(x,y,z) | |
| ); | |
| } | |
| } {1 {number of columns in foreign key does not match the number of columns in the referenced table}} | |
| do_test table-10.11 { | |
| catchsql {DROP TABLE t6} | |
| catchsql { | |
| CREATE TABLE t6(a,b, c REFERENCES t4(x,y)); | |
| } | |
| } {1 {foreign key on c should reference only one column of table t4}} | |
| do_test table-10.12 { | |
| catchsql {DROP TABLE t6} | |
| catchsql { | |
| CREATE TABLE t6(a,b,c, | |
| FOREIGN KEY (b,x) REFERENCES t4(x,y) | |
| ); | |
| } | |
| } {1 {unknown column "x" in foreign key definition}} | |
| do_test table-10.13 { | |
| catchsql {DROP TABLE t6} | |
| catchsql { | |
| CREATE TABLE t6(a,b,c, | |
| FOREIGN KEY (x,b) REFERENCES t4(x,y) | |
| ); | |
| } | |
| } {1 {unknown column "x" in foreign key definition}} | |
| } ;# endif foreignkey | |
| # Test for the "typeof" function. More tests for the | |
| # typeof() function are found in bind.test and types.test. | |
| # | |
| do_test table-11.1 { | |
| execsql { | |
| CREATE TABLE t7( | |
| a integer primary key, | |
| b number(5,10), | |
| c character varying (8), | |
| d VARCHAR(9), | |
| e clob, | |
| f BLOB, | |
| g Text, | |
| h | |
| ); | |
| INSERT INTO t7(a) VALUES(1); | |
| SELECT typeof(a), typeof(b), typeof(c), typeof(d), | |
| typeof(e), typeof(f), typeof(g), typeof(h) | |
| FROM t7 LIMIT 1; | |
| } | |
| } {integer null null null null null null null} | |
| do_test table-11.2 { | |
| execsql { | |
| SELECT typeof(a+b), typeof(a||b), typeof(c+d), typeof(c||d) | |
| FROM t7 LIMIT 1; | |
| } | |
| } {null null null null} | |
| # Test that when creating a table using CREATE TABLE AS, column types are | |
| # assigned correctly for (SELECT ...) and 'x AS y' expressions. | |
| do_test table-12.1 { | |
| ifcapable subquery { | |
| execsql { | |
| CREATE TABLE t8 AS SELECT b, h, a as i, (SELECT f FROM t7) as j FROM t7; | |
| } | |
| } else { | |
| execsql { | |
| CREATE TABLE t8 AS SELECT b, h, a as i, f as j FROM t7; | |
| } | |
| } | |
| } {} | |
| do_test table-12.2 { | |
| execsql { | |
| SELECT sql FROM sqlite_master WHERE tbl_name = 't8' | |
| } | |
| } {{CREATE TABLE t8(b NUM,h,i INT,j)}} | |
| #-------------------------------------------------------------------- | |
| # Test cases table-13.* | |
| # | |
| # Test the ability to have default values of CURRENT_TIME, CURRENT_DATE | |
| # and CURRENT_TIMESTAMP. | |
| # | |
| do_test table-13.1 { | |
| execsql { | |
| CREATE TABLE tablet8( | |
| a integer primary key, | |
| tm text DEFAULT CURRENT_TIME, | |
| dt text DEFAULT CURRENT_DATE, | |
| dttm text DEFAULT CURRENT_TIMESTAMP | |
| ); | |
| SELECT * FROM tablet8; | |
| } | |
| } {} | |
| set i 0 | |
| unset -nocomplain date time seconds | |
| foreach {date time seconds} { | |
| 1976-07-04 12:00:00 205329600 | |
| 1994-04-16 14:00:00 766504800 | |
| 2000-01-01 00:00:00 946684800 | |
| 2003-12-31 12:34:56 1072874096 | |
| } { | |
| incr i | |
| set sqlite_current_time $seconds | |
| do_test table-13.2.$i { | |
| execsql " | |
| INSERT INTO tablet8(a) VALUES($i); | |
| SELECT tm, dt, dttm FROM tablet8 WHERE a=$i; | |
| " | |
| } [list $time $date [list $date $time]] | |
| } | |
| set sqlite_current_time 0 | |
| #-------------------------------------------------------------------- | |
| # Test cases table-14.* | |
| # | |
| # Test that a table cannot be created or dropped while other virtual | |
| # machines are active. This is required because otherwise when in | |
| # auto-vacuum mode the btree-layer may need to move the root-pages of | |
| # a table for which there is an open cursor. | |
| # | |
| # 2007-05-02: A open btree cursor no longer blocks CREATE TABLE. | |
| # But DROP TABLE is still prohibited because we do not want to | |
| # delete a table out from under a running query. | |
| # | |
| # db eval { | |
| # pragma vdbe_trace = 0; | |
| # } | |
| # Try to create a table from within a callback: | |
| unset -nocomplain result | |
| do_test table-14.1 { | |
| set rc [ | |
| catch { | |
| db eval {SELECT * FROM tablet8 LIMIT 1} {} { | |
| db eval {CREATE TABLE t9(a, b, c)} | |
| } | |
| } msg | |
| ] | |
| set result [list $rc $msg] | |
| } {0 {}} | |
| # Try to drop a table from within a callback: | |
| do_test table-14.2 { | |
| set rc [ | |
| catch { | |
| db eval {SELECT * FROM tablet8 LIMIT 1} {} { | |
| db eval {DROP TABLE t9;} | |
| } | |
| } msg | |
| ] | |
| set result [list $rc $msg] | |
| } {1 {database table is locked}} | |
| ifcapable attach { | |
| # Now attach a database and ensure that a table can be created in the | |
| # attached database whilst in a callback from a query on the main database. | |
| do_test table-14.3 { | |
| forcedelete test2.db | |
| forcedelete test2.db-journal | |
| execsql { | |
| ATTACH 'test2.db' as aux; | |
| } | |
| db eval {SELECT * FROM tablet8 LIMIT 1} {} { | |
| db eval {CREATE TABLE aux.t1(a, b, c)} | |
| } | |
| } {} | |
| # On the other hand, it should be impossible to drop a table when any VMs | |
| # are active. This is because VerifyCookie instructions may have already | |
| # been executed, and btree root-pages may not move after this (which a | |
| # delete table might do). | |
| do_test table-14.4 { | |
| set rc [ | |
| catch { | |
| db eval {SELECT * FROM tablet8 LIMIT 1} {} { | |
| db eval {DROP TABLE aux.t1;} | |
| } | |
| } msg | |
| ] | |
| set result [list $rc $msg] | |
| } {1 {database table is locked}} | |
| } | |
| # Create and drop 2000 tables. This is to check that the balance_shallow() | |
| # routine works correctly on the sqlite_master table. At one point it | |
| # contained a bug that would prevent the right-child pointer of the | |
| # child page from being copied to the root page. | |
| # | |
| do_test table-15.1 { | |
| execsql {BEGIN} | |
| for {set i 0} {$i<2000} {incr i} { | |
| execsql "CREATE TABLE tbl$i (a, b, c)" | |
| } | |
| execsql {COMMIT} | |
| } {} | |
| do_test table-15.2 { | |
| execsql {BEGIN} | |
| for {set i 0} {$i<2000} {incr i} { | |
| execsql "DROP TABLE tbl$i" | |
| } | |
| execsql {COMMIT} | |
| } {} | |
| # Ticket 3a88d85f36704eebe134f7f48aebf00cd6438c1a (2014-08-05) | |
| # The following SQL script segfaults while running the INSERT statement: | |
| # | |
| # CREATE TABLE t1(x DEFAULT(max(1))); | |
| # INSERT INTO t1(rowid) VALUES(1); | |
| # | |
| # The problem appears to be the use of an aggregate function as part of | |
| # the default value for a column. This problem has been in the code since | |
| # at least 2006-01-01 and probably before that. This problem was detected | |
| # and reported on the sqlite-users@sqlite.org mailing list by Zsbán Ambrus. | |
| # | |
| do_execsql_test table-16.1 { | |
| CREATE TABLE t16(x DEFAULT(max(1))); | |
| INSERT INTO t16(x) VALUES(123); | |
| SELECT rowid, x FROM t16; | |
| } {1 123} | |
| do_catchsql_test table-16.2 { | |
| INSERT INTO t16(rowid) VALUES(4); | |
| } {1 {unknown function: max()}} | |
| do_execsql_test table-16.3 { | |
| DROP TABLE t16; | |
| CREATE TABLE t16(x DEFAULT(abs(1))); | |
| INSERT INTO t16(rowid) VALUES(4); | |
| SELECT rowid, x FROM t16; | |
| } {4 1} | |
| do_catchsql_test table-16.4 { | |
| DROP TABLE t16; | |
| CREATE TABLE t16(x DEFAULT(avg(1))); | |
| INSERT INTO t16(rowid) VALUES(123); | |
| SELECT rowid, x FROM t16; | |
| } {1 {unknown function: avg()}} | |
| do_catchsql_test table-16.5 { | |
| DROP TABLE t16; | |
| CREATE TABLE t16(x DEFAULT(count())); | |
| INSERT INTO t16(rowid) VALUES(123); | |
| SELECT rowid, x FROM t16; | |
| } {1 {unknown function: count()}} | |
| do_catchsql_test table-16.6 { | |
| DROP TABLE t16; | |
| CREATE TABLE t16(x DEFAULT(group_concat('x',','))); | |
| INSERT INTO t16(rowid) VALUES(123); | |
| SELECT rowid, x FROM t16; | |
| } {1 {unknown function: group_concat()}} | |
| do_catchsql_test table-16.7 { | |
| INSERT INTO t16 DEFAULT VALUES; | |
| } {1 {unknown function: group_concat()}} | |
| # Ticket [https://www.sqlite.org/src/info/094d39a4c95ee4abbc417f04214617675ba15c63] | |
| # describes a assertion fault that occurs on a CREATE TABLE .. AS SELECT statement. | |
| # the following test verifies that the problem has been fixed. | |
| # | |
| do_execsql_test table-17.1 { | |
| DROP TABLE IF EXISTS t1; | |
| CREATE TABLE t1(a TEXT); | |
| INSERT INTO t1(a) VALUES(1),(2); | |
| DROP TABLE IF EXISTS t2; | |
| CREATE TABLE t2(x TEXT, y TEXT); | |
| INSERT INTO t2(x,y) VALUES(3,4); | |
| DROP TABLE IF EXISTS t3; | |
| CREATE TABLE t3 AS | |
| SELECT a AS p, coalesce(y,a) AS q FROM t1 LEFT JOIN t2 ON a=x; | |
| SELECT p, q, '|' FROM t3 ORDER BY p; | |
| } {1 1 | 2 2 |} | |
| # 2015-06-16 | |
| # Ticket [https://www.sqlite.org/src/tktview/873cae2b6e25b1991ce5e9b782f9cd0409b96063] | |
| # Make sure a CREATE TABLE AS statement correctly rolls back partial changes to the | |
| # sqlite_master table when the SELECT on the right-hand side aborts. | |
| # | |
| do_catchsql_test table-18.1 { | |
| DROP TABLE IF EXISTS t1; | |
| BEGIN; | |
| CREATE TABLE t1 AS SELECT zeroblob(2e20); | |
| } {1 {string or blob too big}} | |
| do_execsql_test table-18.2 { | |
| COMMIT; | |
| PRAGMA integrity_check; | |
| } {ok} | |
| # 2015-09-09 | |
| # Ticket [https://www.sqlite.org/src/info/acd12990885d9276] | |
| # "CREATE TABLE ... AS SELECT ... FROM sqlite_master" fails because the row | |
| # in the sqlite_master table for the next table is initially populated | |
| # with a NULL instead of a record created by OP_Record. | |
| # | |
| do_execsql_test table-19.1 { | |
| CREATE TABLE t19 AS SELECT * FROM sqlite_master; | |
| SELECT name FROM t19 ORDER BY name; | |
| } {{} savepoint t10 t11 t12 t13 t16 t2 t3 t3\"xyz t4\"abc t7 t8 t9 tablet8 test1 weird} | |
| finish_test |