eab7f3fe8d
identifer because no valid UTF-8 character can begin with those bytes. If we allowed an identifier to begin with one of those bytes, then the substr() function in ALTER TABLE will not work correctly. (CVS 4003) FossilOrigin-Name: 252810424d8c4dcd19b369d62027094df7cf0bcc
720 lines
18 KiB
Plaintext
720 lines
18 KiB
Plaintext
# 2004 November 10
|
|
#
|
|
# 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 script is testing the ALTER TABLE statement.
|
|
#
|
|
# $Id: alter.test,v 1.23 2007/05/15 09:00:16 drh Exp $
|
|
#
|
|
|
|
set testdir [file dirname $argv0]
|
|
source $testdir/tester.tcl
|
|
|
|
# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
|
|
ifcapable !altertable {
|
|
finish_test
|
|
return
|
|
}
|
|
|
|
#----------------------------------------------------------------------
|
|
# Test organization:
|
|
#
|
|
# alter-1.1.* - alter-1.7.*: Basic tests of ALTER TABLE, including tables
|
|
# with implicit and explicit indices. These tests came from an earlier
|
|
# fork of SQLite that also supported ALTER TABLE.
|
|
# alter-1.8.*: Tests for ALTER TABLE when the table resides in an
|
|
# attached database.
|
|
# alter-1.9.*: Tests for ALTER TABLE when their is whitespace between the
|
|
# table name and left parenthesis token. i.e:
|
|
# "CREATE TABLE abc (a, b, c);"
|
|
# alter-2.*: Test error conditions and messages.
|
|
# alter-3.*: Test ALTER TABLE on tables that have TRIGGERs attached to them.
|
|
# alter-4.*: Test ALTER TABLE on tables that have AUTOINCREMENT fields.
|
|
#
|
|
|
|
# Create some tables to rename. Be sure to include some TEMP tables
|
|
# and some tables with odd names.
|
|
#
|
|
do_test alter-1.1 {
|
|
ifcapable tempdb {
|
|
set ::temp TEMP
|
|
} else {
|
|
set ::temp {}
|
|
}
|
|
execsql [subst -nocommands {
|
|
CREATE TABLE t1(a,b);
|
|
INSERT INTO t1 VALUES(1,2);
|
|
CREATE TABLE [t1'x1](c UNIQUE, b PRIMARY KEY);
|
|
INSERT INTO [t1'x1] VALUES(3,4);
|
|
CREATE INDEX t1i1 ON T1(B);
|
|
CREATE INDEX t1i2 ON t1(a,b);
|
|
CREATE INDEX i3 ON [t1'x1](b,c);
|
|
CREATE $::temp TABLE "temp table"(e,f,g UNIQUE);
|
|
CREATE INDEX i2 ON [temp table](f);
|
|
INSERT INTO [temp table] VALUES(5,6,7);
|
|
}]
|
|
execsql {
|
|
SELECT 't1', * FROM t1;
|
|
SELECT 't1''x1', * FROM "t1'x1";
|
|
SELECT * FROM [temp table];
|
|
}
|
|
} {t1 1 2 t1'x1 3 4 5 6 7}
|
|
do_test alter-1.2 {
|
|
execsql [subst {
|
|
CREATE $::temp TABLE objlist(type, name, tbl_name);
|
|
INSERT INTO objlist SELECT type, name, tbl_name
|
|
FROM sqlite_master WHERE NAME!='objlist';
|
|
}]
|
|
ifcapable tempdb {
|
|
execsql {
|
|
INSERT INTO objlist SELECT type, name, tbl_name
|
|
FROM sqlite_temp_master WHERE NAME!='objlist';
|
|
}
|
|
}
|
|
|
|
execsql {
|
|
SELECT type, name, tbl_name FROM objlist ORDER BY tbl_name, type desc, name;
|
|
}
|
|
} [list \
|
|
table t1 t1 \
|
|
index t1i1 t1 \
|
|
index t1i2 t1 \
|
|
table t1'x1 t1'x1 \
|
|
index i3 t1'x1 \
|
|
index {sqlite_autoindex_t1'x1_1} t1'x1 \
|
|
index {sqlite_autoindex_t1'x1_2} t1'x1 \
|
|
table {temp table} {temp table} \
|
|
index i2 {temp table} \
|
|
index {sqlite_autoindex_temp table_1} {temp table} \
|
|
]
|
|
|
|
# Make some changes
|
|
#
|
|
integrity_check alter-1.3.0
|
|
do_test alter-1.3 {
|
|
execsql {
|
|
ALTER TABLE [T1] RENAME to [-t1-];
|
|
ALTER TABLE "t1'x1" RENAME TO T2;
|
|
ALTER TABLE [temp table] RENAME to TempTab;
|
|
}
|
|
} {}
|
|
integrity_check alter-1.3.1
|
|
do_test alter-1.4 {
|
|
execsql {
|
|
SELECT 't1', * FROM [-t1-];
|
|
SELECT 't2', * FROM t2;
|
|
SELECT * FROM temptab;
|
|
}
|
|
} {t1 1 2 t2 3 4 5 6 7}
|
|
do_test alter-1.5 {
|
|
execsql {
|
|
DELETE FROM objlist;
|
|
INSERT INTO objlist SELECT type, name, tbl_name
|
|
FROM sqlite_master WHERE NAME!='objlist';
|
|
}
|
|
catchsql {
|
|
INSERT INTO objlist SELECT type, name, tbl_name
|
|
FROM sqlite_temp_master WHERE NAME!='objlist';
|
|
}
|
|
execsql {
|
|
SELECT type, name, tbl_name FROM objlist ORDER BY tbl_name, type desc, name;
|
|
}
|
|
} [list \
|
|
table -t1- -t1- \
|
|
index t1i1 -t1- \
|
|
index t1i2 -t1- \
|
|
table T2 T2 \
|
|
index i3 T2 \
|
|
index {sqlite_autoindex_T2_1} T2 \
|
|
index {sqlite_autoindex_T2_2} T2 \
|
|
table {TempTab} {TempTab} \
|
|
index i2 {TempTab} \
|
|
index {sqlite_autoindex_TempTab_1} {TempTab} \
|
|
]
|
|
|
|
# Make sure the changes persist after restarting the database.
|
|
# (The TEMP table will not persist, of course.)
|
|
#
|
|
ifcapable tempdb {
|
|
do_test alter-1.6 {
|
|
db close
|
|
sqlite3 db test.db
|
|
set DB [sqlite3_connection_pointer db]
|
|
execsql {
|
|
CREATE TEMP TABLE objlist(type, name, tbl_name);
|
|
INSERT INTO objlist SELECT type, name, tbl_name FROM sqlite_master;
|
|
INSERT INTO objlist
|
|
SELECT type, name, tbl_name FROM sqlite_temp_master
|
|
WHERE NAME!='objlist';
|
|
SELECT type, name, tbl_name FROM objlist
|
|
ORDER BY tbl_name, type desc, name;
|
|
}
|
|
} [list \
|
|
table -t1- -t1- \
|
|
index t1i1 -t1- \
|
|
index t1i2 -t1- \
|
|
table T2 T2 \
|
|
index i3 T2 \
|
|
index {sqlite_autoindex_T2_1} T2 \
|
|
index {sqlite_autoindex_T2_2} T2 \
|
|
]
|
|
} else {
|
|
execsql {
|
|
DROP TABLE TempTab;
|
|
}
|
|
}
|
|
|
|
# Make sure the ALTER TABLE statements work with the
|
|
# non-callback API
|
|
#
|
|
do_test alter-1.7 {
|
|
stepsql $DB {
|
|
ALTER TABLE [-t1-] RENAME to [*t1*];
|
|
ALTER TABLE T2 RENAME TO [<t2>];
|
|
}
|
|
execsql {
|
|
DELETE FROM objlist;
|
|
INSERT INTO objlist SELECT type, name, tbl_name
|
|
FROM sqlite_master WHERE NAME!='objlist';
|
|
}
|
|
catchsql {
|
|
INSERT INTO objlist SELECT type, name, tbl_name
|
|
FROM sqlite_temp_master WHERE NAME!='objlist';
|
|
}
|
|
execsql {
|
|
SELECT type, name, tbl_name FROM objlist ORDER BY tbl_name, type desc, name;
|
|
}
|
|
} [list \
|
|
table *t1* *t1* \
|
|
index t1i1 *t1* \
|
|
index t1i2 *t1* \
|
|
table <t2> <t2> \
|
|
index i3 <t2> \
|
|
index {sqlite_autoindex_<t2>_1} <t2> \
|
|
index {sqlite_autoindex_<t2>_2} <t2> \
|
|
]
|
|
|
|
# Check that ALTER TABLE works on attached databases.
|
|
#
|
|
do_test alter-1.8.1 {
|
|
file delete -force test2.db
|
|
file delete -force test2.db-journal
|
|
execsql {
|
|
ATTACH 'test2.db' AS aux;
|
|
}
|
|
} {}
|
|
do_test alter-1.8.2 {
|
|
execsql {
|
|
CREATE TABLE t4(a PRIMARY KEY, b, c);
|
|
CREATE TABLE aux.t4(a PRIMARY KEY, b, c);
|
|
CREATE INDEX i4 ON t4(b);
|
|
CREATE INDEX aux.i4 ON t4(b);
|
|
}
|
|
} {}
|
|
do_test alter-1.8.3 {
|
|
execsql {
|
|
INSERT INTO t4 VALUES('main', 'main', 'main');
|
|
INSERT INTO aux.t4 VALUES('aux', 'aux', 'aux');
|
|
SELECT * FROM t4 WHERE a = 'main';
|
|
}
|
|
} {main main main}
|
|
do_test alter-1.8.4 {
|
|
execsql {
|
|
ALTER TABLE t4 RENAME TO t5;
|
|
SELECT * FROM t4 WHERE a = 'aux';
|
|
}
|
|
} {aux aux aux}
|
|
do_test alter-1.8.5 {
|
|
execsql {
|
|
SELECT * FROM t5;
|
|
}
|
|
} {main main main}
|
|
do_test alter-1.8.6 {
|
|
execsql {
|
|
SELECT * FROM t5 WHERE b = 'main';
|
|
}
|
|
} {main main main}
|
|
do_test alter-1.8.7 {
|
|
execsql {
|
|
ALTER TABLE aux.t4 RENAME TO t5;
|
|
SELECT * FROM aux.t5 WHERE b = 'aux';
|
|
}
|
|
} {aux aux aux}
|
|
|
|
do_test alter-1.9.1 {
|
|
execsql {
|
|
CREATE TABLE tbl1 (a, b, c);
|
|
INSERT INTO tbl1 VALUES(1, 2, 3);
|
|
}
|
|
} {}
|
|
do_test alter-1.9.2 {
|
|
execsql {
|
|
SELECT * FROM tbl1;
|
|
}
|
|
} {1 2 3}
|
|
do_test alter-1.9.3 {
|
|
execsql {
|
|
ALTER TABLE tbl1 RENAME TO tbl2;
|
|
SELECT * FROM tbl2;
|
|
}
|
|
} {1 2 3}
|
|
do_test alter-1.9.4 {
|
|
execsql {
|
|
DROP TABLE tbl2;
|
|
}
|
|
} {}
|
|
|
|
# Test error messages
|
|
#
|
|
do_test alter-2.1 {
|
|
catchsql {
|
|
ALTER TABLE none RENAME TO hi;
|
|
}
|
|
} {1 {no such table: none}}
|
|
do_test alter-2.2 {
|
|
execsql {
|
|
CREATE TABLE t3(p,q,r);
|
|
}
|
|
catchsql {
|
|
ALTER TABLE [<t2>] RENAME TO t3;
|
|
}
|
|
} {1 {there is already another table or index with this name: t3}}
|
|
do_test alter-2.3 {
|
|
catchsql {
|
|
ALTER TABLE [<t2>] RENAME TO i3;
|
|
}
|
|
} {1 {there is already another table or index with this name: i3}}
|
|
do_test alter-2.4 {
|
|
catchsql {
|
|
ALTER TABLE SqLiTe_master RENAME TO master;
|
|
}
|
|
} {1 {table sqlite_master may not be altered}}
|
|
do_test alter-2.5 {
|
|
catchsql {
|
|
ALTER TABLE t3 RENAME TO sqlite_t3;
|
|
}
|
|
} {1 {object name reserved for internal use: sqlite_t3}}
|
|
do_test alter-2.6 {
|
|
catchsql {
|
|
ALTER TABLE t3 ADD COLUMN (ALTER TABLE t3 ADD COLUMN);
|
|
}
|
|
} {1 {near "(": syntax error}}
|
|
|
|
# If this compilation does not include triggers, omit the alter-3.* tests.
|
|
ifcapable trigger {
|
|
|
|
#-----------------------------------------------------------------------
|
|
# Tests alter-3.* test ALTER TABLE on tables that have triggers.
|
|
#
|
|
# alter-3.1.*: ALTER TABLE with triggers.
|
|
# alter-3.2.*: Test that the ON keyword cannot be used as a database,
|
|
# table or column name unquoted. This is done because part of the
|
|
# ALTER TABLE code (specifically the implementation of SQL function
|
|
# "sqlite_alter_trigger") will break in this case.
|
|
# alter-3.3.*: ALTER TABLE with TEMP triggers (todo).
|
|
#
|
|
|
|
# An SQL user-function for triggers to fire, so that we know they
|
|
# are working.
|
|
proc trigfunc {args} {
|
|
set ::TRIGGER $args
|
|
}
|
|
db func trigfunc trigfunc
|
|
|
|
do_test alter-3.1.0 {
|
|
execsql {
|
|
CREATE TABLE t6(a, b, c);
|
|
CREATE TRIGGER trig1 AFTER INSERT ON t6 BEGIN
|
|
SELECT trigfunc('trig1', new.a, new.b, new.c);
|
|
END;
|
|
}
|
|
} {}
|
|
do_test alter-3.1.1 {
|
|
execsql {
|
|
INSERT INTO t6 VALUES(1, 2, 3);
|
|
}
|
|
set ::TRIGGER
|
|
} {trig1 1 2 3}
|
|
do_test alter-3.1.2 {
|
|
execsql {
|
|
ALTER TABLE t6 RENAME TO t7;
|
|
INSERT INTO t7 VALUES(4, 5, 6);
|
|
}
|
|
set ::TRIGGER
|
|
} {trig1 4 5 6}
|
|
do_test alter-3.1.3 {
|
|
execsql {
|
|
DROP TRIGGER trig1;
|
|
}
|
|
} {}
|
|
do_test alter-3.1.4 {
|
|
execsql {
|
|
CREATE TRIGGER trig2 AFTER INSERT ON main.t7 BEGIN
|
|
SELECT trigfunc('trig2', new.a, new.b, new.c);
|
|
END;
|
|
INSERT INTO t7 VALUES(1, 2, 3);
|
|
}
|
|
set ::TRIGGER
|
|
} {trig2 1 2 3}
|
|
do_test alter-3.1.5 {
|
|
execsql {
|
|
ALTER TABLE t7 RENAME TO t8;
|
|
INSERT INTO t8 VALUES(4, 5, 6);
|
|
}
|
|
set ::TRIGGER
|
|
} {trig2 4 5 6}
|
|
do_test alter-3.1.6 {
|
|
execsql {
|
|
DROP TRIGGER trig2;
|
|
}
|
|
} {}
|
|
do_test alter-3.1.7 {
|
|
execsql {
|
|
CREATE TRIGGER trig3 AFTER INSERT ON main.'t8'BEGIN
|
|
SELECT trigfunc('trig3', new.a, new.b, new.c);
|
|
END;
|
|
INSERT INTO t8 VALUES(1, 2, 3);
|
|
}
|
|
set ::TRIGGER
|
|
} {trig3 1 2 3}
|
|
do_test alter-3.1.8 {
|
|
execsql {
|
|
ALTER TABLE t8 RENAME TO t9;
|
|
INSERT INTO t9 VALUES(4, 5, 6);
|
|
}
|
|
set ::TRIGGER
|
|
} {trig3 4 5 6}
|
|
|
|
# Make sure "ON" cannot be used as a database, table or column name without
|
|
# quoting. Otherwise the sqlite_alter_trigger() function might not work.
|
|
file delete -force test3.db
|
|
file delete -force test3.db-journal
|
|
do_test alter-3.2.1 {
|
|
catchsql {
|
|
ATTACH 'test3.db' AS ON;
|
|
}
|
|
} {1 {near "ON": syntax error}}
|
|
do_test alter-3.2.2 {
|
|
catchsql {
|
|
ATTACH 'test3.db' AS 'ON';
|
|
}
|
|
} {0 {}}
|
|
do_test alter-3.2.3 {
|
|
catchsql {
|
|
CREATE TABLE ON.t1(a, b, c);
|
|
}
|
|
} {1 {near "ON": syntax error}}
|
|
do_test alter-3.2.4 {
|
|
catchsql {
|
|
CREATE TABLE 'ON'.t1(a, b, c);
|
|
}
|
|
} {0 {}}
|
|
do_test alter-3.2.4 {
|
|
catchsql {
|
|
CREATE TABLE 'ON'.ON(a, b, c);
|
|
}
|
|
} {1 {near "ON": syntax error}}
|
|
do_test alter-3.2.5 {
|
|
catchsql {
|
|
CREATE TABLE 'ON'.'ON'(a, b, c);
|
|
}
|
|
} {0 {}}
|
|
do_test alter-3.2.6 {
|
|
catchsql {
|
|
CREATE TABLE t10(a, ON, c);
|
|
}
|
|
} {1 {near "ON": syntax error}}
|
|
do_test alter-3.2.7 {
|
|
catchsql {
|
|
CREATE TABLE t10(a, 'ON', c);
|
|
}
|
|
} {0 {}}
|
|
do_test alter-3.2.8 {
|
|
catchsql {
|
|
CREATE TRIGGER trig4 AFTER INSERT ON ON BEGIN SELECT 1; END;
|
|
}
|
|
} {1 {near "ON": syntax error}}
|
|
do_test alter-3.2.9 {
|
|
catchsql {
|
|
CREATE TRIGGER 'on'.trig4 AFTER INSERT ON 'ON' BEGIN SELECT 1; END;
|
|
}
|
|
} {0 {}}
|
|
do_test alter-3.2.10 {
|
|
execsql {
|
|
DROP TABLE t10;
|
|
}
|
|
} {}
|
|
|
|
do_test alter-3.3.1 {
|
|
execsql [subst {
|
|
CREATE TABLE tbl1(a, b, c);
|
|
CREATE $::temp TRIGGER trig1 AFTER INSERT ON tbl1 BEGIN
|
|
SELECT trigfunc('trig1', new.a, new.b, new.c);
|
|
END;
|
|
}]
|
|
} {}
|
|
do_test alter-3.3.2 {
|
|
execsql {
|
|
INSERT INTO tbl1 VALUES('a', 'b', 'c');
|
|
}
|
|
set ::TRIGGER
|
|
} {trig1 a b c}
|
|
do_test alter-3.3.3 {
|
|
execsql {
|
|
ALTER TABLE tbl1 RENAME TO tbl2;
|
|
INSERT INTO tbl2 VALUES('d', 'e', 'f');
|
|
}
|
|
set ::TRIGGER
|
|
} {trig1 d e f}
|
|
do_test alter-3.3.4 {
|
|
execsql [subst {
|
|
CREATE $::temp TRIGGER trig2 AFTER UPDATE ON tbl2 BEGIN
|
|
SELECT trigfunc('trig2', new.a, new.b, new.c);
|
|
END;
|
|
}]
|
|
} {}
|
|
do_test alter-3.3.5 {
|
|
execsql {
|
|
ALTER TABLE tbl2 RENAME TO tbl3;
|
|
INSERT INTO tbl3 VALUES('g', 'h', 'i');
|
|
}
|
|
set ::TRIGGER
|
|
} {trig1 g h i}
|
|
do_test alter-3.3.6 {
|
|
execsql {
|
|
UPDATE tbl3 SET a = 'G' where a = 'g';
|
|
}
|
|
set ::TRIGGER
|
|
} {trig2 G h i}
|
|
do_test alter-3.3.7 {
|
|
execsql {
|
|
DROP TABLE tbl3;
|
|
}
|
|
} {}
|
|
ifcapable tempdb {
|
|
do_test alter-3.3.8 {
|
|
execsql {
|
|
SELECT * FROM sqlite_temp_master WHERE type = 'trigger';
|
|
}
|
|
} {}
|
|
}
|
|
|
|
} ;# ifcapable trigger
|
|
|
|
# If the build does not include AUTOINCREMENT fields, omit alter-4.*.
|
|
ifcapable autoinc {
|
|
|
|
do_test alter-4.1 {
|
|
execsql {
|
|
CREATE TABLE tbl1(a INTEGER PRIMARY KEY AUTOINCREMENT);
|
|
INSERT INTO tbl1 VALUES(10);
|
|
}
|
|
} {}
|
|
do_test alter-4.2 {
|
|
execsql {
|
|
INSERT INTO tbl1 VALUES(NULL);
|
|
SELECT a FROM tbl1;
|
|
}
|
|
} {10 11}
|
|
do_test alter-4.3 {
|
|
execsql {
|
|
ALTER TABLE tbl1 RENAME TO tbl2;
|
|
DELETE FROM tbl2;
|
|
INSERT INTO tbl2 VALUES(NULL);
|
|
SELECT a FROM tbl2;
|
|
}
|
|
} {12}
|
|
do_test alter-4.4 {
|
|
execsql {
|
|
DROP TABLE tbl2;
|
|
}
|
|
} {}
|
|
|
|
} ;# ifcapable autoinc
|
|
|
|
# Test that it is Ok to execute an ALTER TABLE immediately after
|
|
# opening a database.
|
|
do_test alter-5.1 {
|
|
execsql {
|
|
CREATE TABLE tbl1(a, b, c);
|
|
INSERT INTO tbl1 VALUES('x', 'y', 'z');
|
|
}
|
|
} {}
|
|
do_test alter-5.2 {
|
|
sqlite3 db2 test.db
|
|
execsql {
|
|
ALTER TABLE tbl1 RENAME TO tbl2;
|
|
SELECT * FROM tbl2;
|
|
} db2
|
|
} {x y z}
|
|
do_test alter-5.3 {
|
|
db2 close
|
|
} {}
|
|
|
|
foreach tblname [execsql {
|
|
SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite%'
|
|
}] {
|
|
execsql "DROP TABLE \"$tblname\""
|
|
}
|
|
|
|
set ::tbl_name "abc\uABCDdef"
|
|
do_test alter-6.1 {
|
|
string length $::tbl_name
|
|
} {7}
|
|
do_test alter-6.2 {
|
|
execsql "
|
|
CREATE TABLE ${tbl_name}(a, b, c);
|
|
"
|
|
set ::oid [execsql {SELECT max(oid) FROM sqlite_master}]
|
|
execsql "
|
|
SELECT sql FROM sqlite_master WHERE oid = $::oid;
|
|
"
|
|
} "{CREATE TABLE ${::tbl_name}(a, b, c)}"
|
|
execsql "
|
|
SELECT * FROM ${::tbl_name}
|
|
"
|
|
set ::tbl_name2 "abcXdef"
|
|
do_test alter-6.3 {
|
|
execsql "
|
|
ALTER TABLE $::tbl_name RENAME TO $::tbl_name2
|
|
"
|
|
execsql "
|
|
SELECT sql FROM sqlite_master WHERE oid = $::oid
|
|
"
|
|
} "{CREATE TABLE '${::tbl_name2}'(a, b, c)}"
|
|
do_test alter-6.4 {
|
|
execsql "
|
|
ALTER TABLE $::tbl_name2 RENAME TO $::tbl_name
|
|
"
|
|
execsql "
|
|
SELECT sql FROM sqlite_master WHERE oid = $::oid
|
|
"
|
|
} "{CREATE TABLE '${::tbl_name}'(a, b, c)}"
|
|
set ::col_name ghi\1234\jkl
|
|
do_test alter-6.5 {
|
|
execsql "
|
|
ALTER TABLE $::tbl_name ADD COLUMN $::col_name VARCHAR
|
|
"
|
|
execsql "
|
|
SELECT sql FROM sqlite_master WHERE oid = $::oid
|
|
"
|
|
} "{CREATE TABLE '${::tbl_name}'(a, b, c, $::col_name VARCHAR)}"
|
|
set ::col_name2 B\3421\A
|
|
do_test alter-6.6 {
|
|
db close
|
|
sqlite3 db test.db
|
|
execsql "
|
|
ALTER TABLE $::tbl_name ADD COLUMN $::col_name2
|
|
"
|
|
execsql "
|
|
SELECT sql FROM sqlite_master WHERE oid = $::oid
|
|
"
|
|
} "{CREATE TABLE '${::tbl_name}'(a, b, c, $::col_name VARCHAR, $::col_name2)}"
|
|
do_test alter-6.7 {
|
|
execsql "
|
|
INSERT INTO ${::tbl_name} VALUES(1, 2, 3, 4, 5);
|
|
SELECT $::col_name, $::col_name2 FROM $::tbl_name;
|
|
"
|
|
} {4 5}
|
|
|
|
# Ticket #1665: Make sure ALTER TABLE ADD COLUMN works on a table
|
|
# that includes a COLLATE clause.
|
|
#
|
|
do_test alter-7.1 {
|
|
execsql {
|
|
CREATE TABLE t1(a TEXT COLLATE BINARY);
|
|
ALTER TABLE t1 ADD COLUMN b INTEGER COLLATE NOCASE;
|
|
INSERT INTO t1 VALUES(1,'-2');
|
|
INSERT INTO t1 VALUES(5.4e-8,'5.4e-8');
|
|
SELECT typeof(a), a, typeof(b), b FROM t1;
|
|
}
|
|
} {text 1 integer -2 text 5.4e-8 real 5.4e-08}
|
|
|
|
# Make sure that when a column is added by ALTER TABLE ADD COLUMN and has
|
|
# a default value that the default value is used by aggregate functions.
|
|
#
|
|
do_test alter-8.1 {
|
|
execsql {
|
|
CREATE TABLE t2(a INTEGER);
|
|
INSERT INTO t2 VALUES(1);
|
|
INSERT INTO t2 VALUES(1);
|
|
INSERT INTO t2 VALUES(2);
|
|
ALTER TABLE t2 ADD COLUMN b INTEGER DEFAULT 9;
|
|
SELECT sum(b) FROM t2;
|
|
}
|
|
} {27}
|
|
do_test alter-8.2 {
|
|
execsql {
|
|
SELECT a, sum(b) FROM t2 GROUP BY a;
|
|
}
|
|
} {1 18 2 9}
|
|
|
|
#--------------------------------------------------------------------------
|
|
# alter-9.X - Special test: Make sure the sqlite_rename_trigger() and
|
|
# rename_table() functions do not crash when handed bad input.
|
|
#
|
|
ifcapable trigger {
|
|
do_test alter-9.1 {
|
|
execsql {SELECT SQLITE_RENAME_TRIGGER(0,0)}
|
|
} {{}}
|
|
}
|
|
do_test alter-9.2 {
|
|
execsql {
|
|
SELECT SQLITE_RENAME_TABLE(0,0);
|
|
SELECT SQLITE_RENAME_TABLE(10,20);
|
|
SELECT SQLITE_RENAME_TABLE("foo", "foo");
|
|
}
|
|
} {{} {} {}}
|
|
|
|
#------------------------------------------------------------------------
|
|
# alter-10.X - Make sure ALTER TABLE works with multi-byte UTF-8 characters
|
|
# in the names.
|
|
#
|
|
do_test alter-10.1 {
|
|
execsql "CREATE TABLE xyz(x UNIQUE)"
|
|
execsql "ALTER TABLE xyz RENAME TO xyz\u1234abc"
|
|
execsql {SELECT name FROM sqlite_master WHERE name LIKE 'xyz%'}
|
|
} [list xyz\u1234abc]
|
|
do_test alter-10.2 {
|
|
execsql {SELECT name FROM sqlite_master WHERE name LIKE 'sqlite_autoindex%'}
|
|
} [list sqlite_autoindex_xyz\u1234abc_1]
|
|
do_test alter-10.3 {
|
|
execsql "ALTER TABLE xyz\u1234abc RENAME TO xyzabc"
|
|
execsql {SELECT name FROM sqlite_master WHERE name LIKE 'xyz%'}
|
|
} [list xyzabc]
|
|
do_test alter-10.4 {
|
|
execsql {SELECT name FROM sqlite_master WHERE name LIKE 'sqlite_autoindex%'}
|
|
} [list sqlite_autoindex_xyzabc_1]
|
|
|
|
do_test alter-11.1 {
|
|
sqlite3_exec db {CREATE TABLE t11(%c6%c6)}
|
|
execsql {
|
|
ALTER TABLE t11 ADD COLUMN abc;
|
|
}
|
|
catchsql {
|
|
ALTER TABLE t11 ADD COLUMN abc;
|
|
}
|
|
} {1 {duplicate column name: abc}}
|
|
do_test alter-11.2 {
|
|
sqlite3_exec db {CREATE TABLE t11b("%81%82%83" text)}
|
|
execsql {
|
|
ALTER TABLE t11b ADD COLUMN abc;
|
|
}
|
|
catchsql {
|
|
ALTER TABLE t11b ADD COLUMN abc;
|
|
}
|
|
} {1 {duplicate column name: abc}}
|
|
do_test alter-11.3 {
|
|
set v [sqlite3_exec db {CREATE TABLE t11c(%81%82%83 text)}]
|
|
set v [string range $v 0 20]\175
|
|
} {1 {unrecognized token}}
|
|
|
|
finish_test
|