package net.sourceforge.mayfly.acceptance.definition;
import net.sourceforge.mayfly.acceptance.SqlTestCase;
import java.sql.SQLException;
public class AddUniqueTest extends SqlTestCase {
public void testBasics() throws Exception {
execute("create table foo(id integer" +
(dialect.uniqueColumnMayBeNullable() ? "" : " not null") +
", x integer)");
execute("insert into foo values(3, 10)");
execute("insert into foo values(5, 10)");
execute("insert into foo values(5, 20)");
if (dialect.uniqueColumnMayBeNullable()) {
execute("insert into foo values(null, 40)");
}
String add = "alter table foo add unique(id)";
/* Perhaps "unique column id has duplicate value 5" would be
nicer wording in that we aren't adding a 5 and conflicting
with one there; there are two there. But is this really
confusing or only inaccurate in a nit-picky way?
*/
expectExecuteFailure(add, "unique constraint in table foo, column id: duplicate value 5");
execute("delete from foo where x = 20");
execute(add);
expectExecuteFailure("insert into foo values(5, 30)",
"unique constraint in table foo, column id: duplicate value 5");
if (dialect.uniqueColumnMayBeNullable()) {
String secondNull = "insert into foo values(null, 50)";
if (dialect.allowMultipleNullsInUniqueColumn()) {
execute(secondNull);
}
else {
expectExecuteFailure(secondNull,
"unique constraint in table foo, column id: duplicate value null");
}
}
}
public void testConstraintNames() throws Exception {
execute("create table foo(id integer not null, x integer not null)");
execute("alter table foo add constraint foo_unique unique(id)");
expectExecuteFailure(
"alter table foo add constraint foo_unique unique(x)",
"duplicate constraint name foo_unique");
String addPrimaryKey = "alter table foo add constraint foo_unique primary key(x)";
if (dialect.duplicateConstraintNamesOk()) {
execute(addPrimaryKey);
}
else {
expectExecuteFailure(
addPrimaryKey,
"duplicate constraint name foo_unique");
execute("alter table foo add constraint foo_x unique(x)");
}
}
public void testPrimaryKey() throws Exception {
execute("create table foo(id integer, x integer)");
execute("insert into foo values(3, 10)");
execute("insert into foo values(5, 10)");
execute("insert into foo values(5, 20)");
String add = "alter table foo add primary key(id)";
expectExecuteFailure(add, "primary key in table foo, column id: duplicate value 5");
execute("update foo set id = null where x = 20");
if (dialect.notNullImpliesDefaults()) {
try {
execute(add);
failForMissingException(add,
"Data truncated for column 'id' at row 3");
} catch (SQLException expected) {
assertEquals("Data truncation: Data truncated for column 'id' at row 3",
expected.getMessage());
}
expectExecuteFailure("insert into foo values(5, 30)",
"primary key in table foo, column id: duplicate value 5");
}
else {
expectExecuteFailure(add, "primary key id cannot be null");
execute("update foo set id = 7 where x = 20");
if (dialect.canTurnNullableColumnIntoPrimaryKey()) {
execute(add);
expectExecuteFailure("insert into foo values(5, 30)",
"primary key in table foo, column id: duplicate value 5");
}
else {
/* I'm not sure there is a way out other than copying
the table. Derby doesn't have MODIFY COLUMN to add
the NOT NULL with... */
expectExecuteFailure(add, "missing NOT NULL");
}
}
}
public void testTwoPrimaryKeys() throws Exception {
execute("create table foo(id integer primary key, x integer not null)");
expectExecuteFailure("alter table foo add primary key(x)",
"attempt to define more than one primary key for table foo");
}
}