-C Disallow\sstatements\sof\sthe\sform\s"CREATE\sTEMP\sTABLE\smain.t1\s...".
-D 2010-09-28T15:55:48
+C Add\stests\sto\se_createtable.test.\sAllow\sa\stable\sto\sbe\screated\sif\sthere\sis\san\sindex\sof\sthe\ssame\sname\sin\sa\sdifferent\sattached\sdatabase.
+D 2010-09-28T17:37:28
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in c599a15d268b1db2aeadea19df2adc3bf2eb6bee
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/btree.c d878577184112d982d00ea05afcc7487cd9f06f5
F src/btree.h 2d1a83ad509047e8cc314fda7e054f99ff52414d
F src/btreeInt.h c424f2f131cc61ddf130f9bd736b3df12c8a51f0
-F src/build.c 907385634c73be72acabfd902dfa6f65a429d8c0
+F src/build.c 0451673aeae6606d349c8760a0606ab9523a6fb4
F src/callback.c a1d1b1c9c85415dff013af033e2fed9c8382d33b
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 4f3aadad62c6c9f0d4e5a96718516ac4e3c598df
F test/descidx3.test fe720e8b37d59f4cef808b0bf4e1b391c2e56b6f
F test/diskfull.test 0cede7ef9d8f415d9d3944005c76be7589bb5ebb
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
-F test/e_createtable.test 2b3257a5b74a4993574f321fb85f063ce1d38241
+F test/e_createtable.test 089acf08bb2ecae3858f1ecdc2fe1705e906a408
F test/e_delete.test 55d868b647acc091c261a10b9b0cb0ab660a6acb
F test/e_expr.test 164e87c1d7b40ceb47c57c3bffa384c81d009aa7
F test/e_fkey.test 6721a741c6499b3ab7e5385923233343c8f1ad05
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a
F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05
-F test/tester.tcl 5a9b8727747f76c18e3a1bf3f0ed16f57a546265
+F test/tester.tcl 74d64ca2730b512b2adaa5e74a07533f7ac6ad9e
F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f
F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db
F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 890816c52d688f01be9a8abd8b4c9375eed4de7e
-R bb6d7614396bfdf34c844eda2125719d
+P dd1b34bab7edaaedd985882f6e16b16940a46d38
+R 9a005e09da83e134e84a9a0916725a2c
U dan
-Z 79640b932b15b5e171373f446f6cc41b
+Z d38832569685f81301ba56b0f91fcdf4
set testdir [file dirname $argv0]
source $testdir/tester.tcl
+# Test organization:
+#
+# e_createtable-0.*: Test that the syntax diagrams are correct.
+#
+# e_createtable-1.*: Test statements related to table and database names,
+# the TEMP and TEMPORARY keywords, and the IF NOT EXISTS clause.
+#
+#
+#
+
proc do_createtable_tests {nm args} {
uplevel do_select_tests [list e_createtable-$nm] $args
}
)} {}
}
+#-------------------------------------------------------------------------
+# Test cases e_createtable-1.* - test statements related to table and
+# database names, the TEMP and TEMPORARY keywords, and the IF NOT EXISTS
+# clause.
+#
+drop_all_tables
+forcedelete test.db2 test.db3
+
+do_execsql_test e_createtable-1.0 {
+ ATTACH 'test.db2' AS auxa;
+ ATTACH 'test.db3' AS auxb;
+} {}
+
+# EVIDENCE-OF: R-17899-04554 Table names that begin with "sqlite_" are
+# reserved for internal use. It is an error to attempt to create a table
+# with a name that starts with "sqlite_".
+#
+do_createtable_tests 1.1.1 -error {
+ object name reserved for internal use: %s
+} {
+ 1 "CREATE TABLE sqlite_abc(a, b, c)" sqlite_abc
+ 2 "CREATE TABLE temp.sqlite_helloworld(x)" sqlite_helloworld
+ 3 {CREATE TABLE auxa."sqlite__"(x, y)} sqlite__
+ 4 {CREATE TABLE auxb."sqlite_"(z)} sqlite_
+ 5 {CREATE TABLE "SQLITE_TBL"(z)} SQLITE_TBL
+}
+do_createtable_tests 1.1.2 {
+ 1 "CREATE TABLE sqlit_abc(a, b, c)" {}
+ 2 "CREATE TABLE temp.sqlitehelloworld(x)" {}
+ 3 {CREATE TABLE auxa."sqlite"(x, y)} {}
+ 4 {CREATE TABLE auxb."sqlite-"(z)} {}
+ 5 {CREATE TABLE "SQLITE-TBL"(z)} {}
+}
+
+
+proc table_list {} {
+ set res [list]
+ db eval { pragma database_list } a {
+ set dbname $a(name)
+ set master $a(name).sqlite_master
+ if {$dbname == "temp"} { set master sqlite_temp_master }
+ lappend res $dbname [
+ db eval "SELECT DISTINCT tbl_name FROM $master ORDER BY tbl_name"
+ ]
+ }
+ set res
+}
+
+# EVIDENCE-OF: R-10195-31023 If a <database-name> is specified, it
+# must be either "main", "temp", or the name of an attached database.
+#
+# EVIDENCE-OF: R-39822-07822 In this case the new table is created in
+# the named database.
+#
+# Test cases 1.2.* test the first of the two requirements above. The
+# second is verified by cases 1.3.*.
+#
+do_createtable_tests 1.2.1 -error {
+ unknown database %s
+} {
+ 1 "CREATE TABLE george.t1(a, b)" george
+ 2 "CREATE TABLE _.t1(a, b)" _
+}
+do_createtable_tests 1.2.2 {
+ 1 "CREATE TABLE main.abc(a, b, c)" {}
+ 2 "CREATE TABLE temp.helloworld(x)" {}
+ 3 {CREATE TABLE auxa."t 1"(x, y)} {}
+ 4 {CREATE TABLE auxb.xyz(z)} {}
+}
+drop_all_tables
+do_createtable_tests 1.3 -tclquery {
+ unset -nocomplain X
+ array set X [table_list]
+ list $X(main) $X(temp) $X(auxa) $X(auxb)
+} {
+ 1 "CREATE TABLE main.abc(a, b, c)" {abc {} {} {}}
+ 2 "CREATE TABLE main.t1(a, b, c)" {{abc t1} {} {} {}}
+ 3 "CREATE TABLE temp.tmp(a, b, c)" {{abc t1} tmp {} {}}
+ 4 "CREATE TABLE auxb.tbl(x, y)" {{abc t1} tmp {} tbl}
+ 5 "CREATE TABLE auxb.t1(k, v)" {{abc t1} tmp {} {t1 tbl}}
+ 6 "CREATE TABLE auxa.next(c, d)" {{abc t1} tmp next {t1 tbl}}
+}
+
+# EVIDENCE-OF: R-18895-27365 If the "TEMP" or "TEMPORARY" keyword occurs
+# between the "CREATE" and "TABLE" then the new table is created in the
+# temp database.
+#
+drop_all_tables
+do_createtable_tests 1.4 -tclquery {
+ unset -nocomplain X
+ array set X [table_list]
+ list $X(main) $X(temp) $X(auxa) $X(auxb)
+} {
+ 1 "CREATE TEMP TABLE t1(a, b)" {{} t1 {} {}}
+ 2 "CREATE TEMPORARY TABLE t2(a, b)" {{} {t1 t2} {} {}}
+}
+
+# EVIDENCE-OF: R-49439-47561 It is an error to specify both a
+# <database-name> and the TEMP or TEMPORARY keyword, unless the
+# <database-name> is "temp".
+#
+drop_all_tables
+do_createtable_tests 1.5.1 -error {
+ temporary table name must be unqualified
+} {
+ 1 "CREATE TEMP TABLE main.t1(a, b)" {}
+ 2 "CREATE TEMPORARY TABLE auxa.t2(a, b)" {}
+ 3 "CREATE TEMP TABLE auxb.t3(a, b)" {}
+ 4 "CREATE TEMPORARY TABLE main.xxx(x)" {}
+}
+drop_all_tables
+do_createtable_tests 1.5.2 -tclquery {
+ unset -nocomplain X
+ array set X [table_list]
+ list $X(main) $X(temp) $X(auxa) $X(auxb)
+} {
+ 1 "CREATE TEMP TABLE temp.t1(a, b)" {{} t1 {} {}}
+ 2 "CREATE TEMPORARY TABLE temp.t2(a, b)" {{} {t1 t2} {} {}}
+ 3 "CREATE TEMP TABLE TEMP.t3(a, b)" {{} {t1 t2 t3} {} {}}
+ 4 "CREATE TEMPORARY TABLE TEMP.xxx(x)" {{} {t1 t2 t3 xxx} {} {}}
+}
+
+# EVIDENCE-OF: R-00917-09393 If no database name is specified and the
+# TEMP keyword is not present then the table is created in the main
+# database.
+#
+drop_all_tables
+do_createtable_tests 1.6 -tclquery {
+ unset -nocomplain X
+ array set X [table_list]
+ list $X(main) $X(temp) $X(auxa) $X(auxb)
+} {
+ 1 "CREATE TABLE t1(a, b)" {t1 {} {} {}}
+ 2 "CREATE TABLE t2(a, b)" {{t1 t2} {} {} {}}
+ 3 "CREATE TABLE t3(a, b)" {{t1 t2 t3} {} {} {}}
+ 4 "CREATE TABLE xxx(x)" {{t1 t2 t3 xxx} {} {} {}}
+}
+
+drop_all_tables
+do_execsql_test e_createtable-1.7.0 {
+ CREATE TABLE t1(x, y);
+ CREATE INDEX i1 ON t1(x);
+ CREATE VIEW v1 AS SELECT * FROM t1;
+
+ CREATE TABLE auxa.tbl1(x, y);
+ CREATE INDEX auxa.idx1 ON tbl1(x);
+ CREATE VIEW auxa.view1 AS SELECT * FROM tbl1;
+} {}
+
+# EVIDENCE-OF: R-01232-54838 It is usually an error to attempt to create
+# a new table in a database that already contains a table, index or view
+# of the same name.
+#
+# Test cases 1.7.1.* verify that creating a table in a database with a
+# table/index/view of the same name does fail. 1.7.2.* tests that creating
+# a table with the same name as a table/index/view in a different database
+# is Ok.
+#
+do_createtable_tests 1.7.1 -error { %s } {
+ 1 "CREATE TABLE t1(a, b)" {{table t1 already exists}}
+ 2 "CREATE TABLE i1(a, b)" {{there is already an index named i1}}
+ 3 "CREATE TABLE v1(a, b)" {{table v1 already exists}}
+ 4 "CREATE TABLE auxa.tbl1(a, b)" {{table tbl1 already exists}}
+ 5 "CREATE TABLE auxa.idx1(a, b)" {{there is already an index named idx1}}
+ 6 "CREATE TABLE auxa.view1(a, b)" {{table view1 already exists}}
+}
+do_createtable_tests 1.7.2 {
+ 1 "CREATE TABLE auxa.t1(a, b)" {}
+ 2 "CREATE TABLE auxa.i1(a, b)" {}
+ 3 "CREATE TABLE auxa.v1(a, b)" {}
+ 4 "CREATE TABLE tbl1(a, b)" {}
+ 5 "CREATE TABLE idx1(a, b)" {}
+ 6 "CREATE TABLE view1(a, b)" {}
+}
+
+# EVIDENCE-OF: R-33917-24086 However, if the "IF NOT EXISTS" clause is
+# specified as part of the CREATE TABLE statement and a table or view of
+# the same name already exists, the CREATE TABLE command simply has no
+# effect (and no error message is returned).
+#
+drop_all_tables
+do_execsql_test e_createtable-1.8.0 {
+ CREATE TABLE t1(x, y);
+ CREATE INDEX i1 ON t1(x);
+ CREATE VIEW v1 AS SELECT * FROM t1;
+ CREATE TABLE auxa.tbl1(x, y);
+ CREATE INDEX auxa.idx1 ON tbl1(x);
+ CREATE VIEW auxa.view1 AS SELECT * FROM tbl1;
+} {}
+do_createtable_tests 1.8 {
+ 1 "CREATE TABLE IF NOT EXISTS t1(a, b)" {}
+ 2 "CREATE TABLE IF NOT EXISTS auxa.tbl1(a, b)" {}
+ 3 "CREATE TABLE IF NOT EXISTS v1(a, b)" {}
+ 4 "CREATE TABLE IF NOT EXISTS auxa.view1(a, b)" {}
+}
+
+# EVIDENCE-OF: R-16465-40078 An error is still returned if the table
+# cannot be created because of an existing index, even if the "IF NOT
+# EXISTS" clause is specified.
+#
+do_createtable_tests 1.9 -error { %s } {
+ 1 "CREATE TABLE IF NOT EXISTS i1(a, b)"
+ {{there is already an index named i1}}
+ 2 "CREATE TABLE IF NOT EXISTS auxa.idx1(a, b)"
+ {{there is already an index named idx1}}
+}
+
+# EVIDENCE-OF: R-05513-33819 It is not an error to create a table that
+# has the same name as an existing trigger.
+#
+drop_all_tables
+do_execsql_test e_createtable-1.10.0 {
+ CREATE TABLE t1(x, y);
+ CREATE TABLE auxb.t2(x, y);
+
+ CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
+ SELECT 1;
+ END;
+ CREATE TRIGGER auxb.tr2 AFTER INSERT ON t2 BEGIN
+ SELECT 1;
+ END;
+} {}
+do_createtable_tests 1.10 {
+ 1 "CREATE TABLE tr1(a, b)" {}
+ 2 "CREATE TABLE tr2(a, b)" {}
+ 3 "CREATE TABLE auxb.tr1(a, b)" {}
+ 4 "CREATE TABLE auxb.tr2(a, b)" {}
+}
+
+# EVIDENCE-OF: R-22283-14179 Tables are removed using the DROP TABLE
+# statement.
+#
+drop_all_tables
+do_execsql_test e_createtable-1.11.0 {
+ CREATE TABLE t1(a, b);
+ CREATE TABLE t2(a, b);
+ CREATE TABLE auxa.t3(a, b);
+ CREATE TABLE auxa.t4(a, b);
+} {}
+
+do_execsql_test e_createtable-1.11.1.1 {
+ SELECT * FROM t1;
+ SELECT * FROM t2;
+ SELECT * FROM t3;
+ SELECT * FROM t4;
+} {}
+do_execsql_test e_createtable-1.11.1.2 { DROP TABLE t1 } {}
+do_catchsql_test e_createtable-1.11.1.3 {
+ SELECT * FROM t1
+} {1 {no such table: t1}}
+do_execsql_test e_createtable-1.11.1.4 { DROP TABLE t3 } {}
+do_catchsql_test e_createtable-1.11.1.5 {
+ SELECT * FROM t3
+} {1 {no such table: t3}}
+
+do_execsql_test e_createtable-1.11.2.1 {
+ SELECT name FROM sqlite_master;
+ SELECT name FROM auxa.sqlite_master;
+} {t2 t4}
+do_execsql_test e_createtable-1.11.2.2 { DROP TABLE t2 } {}
+do_execsql_test e_createtable-1.11.2.3 { DROP TABLE t4 } {}
+do_execsql_test e_createtable-1.11.2.4 {
+ SELECT name FROM sqlite_master;
+ SELECT name FROM auxa.sqlite_master;
+} {}
+
+
finish_test
+
# -errorformat FMTSTRING
# -count
# -query SQL
+# -tclquery TCL
# -repair TCL
#
proc do_select_tests {prefix args} {
set errfmt ""
set countonly 0
- set query ""
+ set tclquery ""
set repair ""
for {set i 0} {$i < [llength $switches]} {incr i} {
set s [lindex $switches $i]
set n [string length $s]
if {$n>=2 && [string equal -length $n $s "-query"]} {
- set query [lindex $switches [incr i]]
+ set tclquery [list execsql [lindex $switches [incr i]]]
+ } elseif {$n>=2 && [string equal -length $n $s "-tclquery"]} {
+ set tclquery [lindex $switches [incr i]]
} elseif {$n>=2 && [string equal -length $n $s "-errorformat"]} {
set errfmt [lindex $switches [incr i]]
} elseif {$n>=2 && [string equal -length $n $s "-repair"]} {
eval $repair
foreach {tn sql res} $testlist {
- if {$query != ""} {
+ if {$tclquery != ""} {
execsql $sql
- set sql $query
- }
-
- if {$countonly} {
+ uplevel do_test ${prefix}.$tn [list $tclquery] [list [list {*}$res]]
+ } elseif {$countonly} {
set nRow 0
db eval $sql {incr nRow}
uplevel do_test ${prefix}.$tn [list [list set {} $nRow]] [list $res]
# Delete a file or directory
#
-proc forcedelete {filename} {
- # On windows, sometimes even a [file delete -force] can fail just after
- # a file is closed. The cause is usually "tag-alongs" - programs like
- # anti-virus software, automatic backup tools and various explorer
- # extensions that keep a file open a little longer than we expect, causing
- # the delete to fail.
- #
- # The solution is to wait a short amount of time before retrying the delete.
- #
- set nRetry 50 ;# Maximum number of retries.
- set nDelay 100 ;# Delay in ms before retrying.
- for {set i 0} {$i<$nRetry} {incr i} {
- set rc [catch {file delete -force $filename} msg]
- if {$rc==0} break
- after $nDelay
+proc forcedelete {args} {
+ foreach filename $args {
+ # On windows, sometimes even a [file delete -force] can fail just after
+ # a file is closed. The cause is usually "tag-alongs" - programs like
+ # anti-virus software, automatic backup tools and various explorer
+ # extensions that keep a file open a little longer than we expect, causing
+ # the delete to fail.
+ #
+ # The solution is to wait a short amount of time before retrying the
+ # delete.
+ #
+ set nRetry 50 ;# Maximum number of retries.
+ set nDelay 100 ;# Delay in ms before retrying.
+ for {set i 0} {$i<$nRetry} {incr i} {
+ set rc [catch {file delete -force $filename} msg]
+ if {$rc==0} break
+ after $nDelay
+ }
+ if {$rc} { error $msg }
}
- if {$rc} { error $msg }
}
# Do an integrity check of the entire database
}
foreach {t type} [$db eval "
SELECT name, type FROM $master
- WHERE type IN('table', 'view') AND name NOT like 'sqlite_%'
+ WHERE type IN('table', 'view') AND name NOT LIKE 'sqliteX_%' ESCAPE 'X'
"] {
- $db eval "DROP $type $t"
+ $db eval "DROP $type \"$t\""
}
}
ifcapable trigger&&foreignkey {