package net.sourceforge.mayfly;
import junit.framework.TestCase;
import net.sourceforge.mayfly.acceptance.SqlTestCase;
import net.sourceforge.mayfly.datastore.DataStore;
import net.sourceforge.mayfly.dump.SqlDumper;
import java.io.Reader;
import java.io.StringReader;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
public class DatabaseTest extends TestCase {
private Database database;
@Override
public void setUp() throws Exception {
database = new Database();
}
public void testCreateAndDrop() throws Exception {
database.execute("CREATE TABLE FOO (A integer)");
assertEquals(Collections.singleton("FOO"), database.tables());
database.execute("DROP TABLE Foo");
assertEquals(Collections.EMPTY_SET, database.tables());
}
public void testCreateWithOneColumn() throws Exception {
database.execute("CREATE TABLE Foo (A integer)");
assertEquals(Collections.singleton("Foo"), database.tables());
assertEquals(Collections.singletonList("A"), database.columnNames("fOo"));
}
public void testInsert() throws Exception {
database.execute("CREATE TABLE FOO (A integer)");
assertEquals(0, database.rowCount("foo"));
database.execute("INSERT INTO FOO (A) values (5)");
assertEquals(1, database.rowCount("foo"));
}
public void testSnapshot() throws Exception {
Database original = new Database();
original.execute("create table foo (a integer)");
original.execute("insert into foo(a) values(6)");
DataStore dataStore = original.dataStore();
Database snapshot = new Database(dataStore);
snapshot.execute("insert into foo (a) values (70)");
snapshot.execute("create table bar (b integer)");
original.execute("create table foo2 (c integer)");
assertEquals(new TreeSet(Arrays.asList(new String[] {"foo", "bar"})), snapshot.tables());
assertEquals(2, snapshot.rowCount("Foo"));
assertEquals(new TreeSet(Arrays.asList(new String[] {"foo", "foo2"})), original.tables());
assertEquals(1, original.rowCount("Foo"));
}
public void testTables() throws Exception {
database.execute("create table inAnonymousSchema (x integer)");
database.execute("create schema mars authorization dba create table foo (x integer)");
assertEquals(Collections.singleton("inAnonymousSchema"), database.tables());
database.execute("set schema mars");
assertEquals(Collections.singleton("foo"), database.tables());
}
public void testColumnNames() throws Exception {
database.execute("create table inAnonymousSchema (x integer)");
database.execute("create schema mars authorization dba create table foo (y integer)");
assertEquals(Collections.singletonList("x"), database.columnNames("inAnonymousSchema"));
database.execute("set schema mars");
assertEquals(Collections.singletonList("y"), database.columnNames("foo"));
try {
database.columnNames("nosuch");
fail();
}
catch (MayflyException e) {
assertEquals("no table nosuch", e.getMessage());
}
}
public void testIndexesOnNonexistentTable() throws Exception {
try {
database.indexes("nosuch");
fail();
}
catch (MayflyException e) {
assertEquals("no table nosuch", e.getMessage());
}
}
public void testNoIndexes() throws Exception {
database.execute("create table foo(x integer)");
assertEquals(0, database.indexes("foo").size());
}
public void testReturnIndexes() throws Exception {
database.execute("create table foo(x integer)");
database.execute("create index an_index_name on foo(x)");
List<String> indexes = database.indexes("foo");
assertEquals(1, indexes.size());
assertEquals("an_index_name", indexes.get(0));
}
public void testQueryAndSchema() throws Exception {
database.execute("create table inAnonymousSchema (x integer)");
database.execute("create schema mars authorization dba create table foo (y integer)");
String fooQuery = "select * from foo";
try {
database.query(fooQuery);
fail();
} catch (MayflyException e) {
assertEquals("no table foo", e.getMessage());
}
database.execute("set schema mars");
SqlTestCase.assertResultSet(new String[] { }, database.query(fooQuery));
}
public void testSchemas() throws Exception {
database.execute("create schema MARS authorization dba create table foo (x integer)");
database.execute("create schema Venus authorization dba create table foo (x integer)");
Set expected = new TreeSet();
expected.add("MARS");
expected.add("Venus");
assertEquals(expected, database.schemas());
}
public void testScript() throws Exception {
Reader script = new StringReader(
"create table foo (x integer); insert into foo(x) values(5)" +
";insert into foo(x)values(7)"
);
database.executeScript(script);
SqlTestCase.assertResultSet(
new String[] { "5", "7" },
database.query("select x from foo")
);
}
public void testScriptError() throws Exception {
String command = "create table foo\n" +
" (x integer,\n" +
" y not)";
Reader script = new StringReader(
command + ";" +
"create table otherTable(a integer);");
try {
database.executeScript(script);
fail();
}
catch (MayflyException e) {
assertEquals("expected data type but got NOT", e.getMessage());
assertEquals(3, e.startLineNumber());
assertEquals(7, e.startColumn());
assertEquals(3, e.endLineNumber());
assertEquals(10, e.endColumn());
assertEquals(command, e.failingCommand());
}
}
public void testFailingCommandFromDatabase() throws Exception {
database.execute("create table foo(x integer not null)");
try {
database.execute("insert into foo(x) values(null)");
fail();
}
catch (MayflyException e) {
assertEquals("column x cannot be null", e.getMessage());
assertEquals("insert into foo(x) values(null)", e.failingCommand());
}
}
public void testRenameColumn() throws Exception {
Database database = new Database();
database.execute(
"create table foo(a integer, b integer, c integer, " +
"primary key(a, b))");
database.execute("create index an_index on foo(c)");
database.execute("alter table foo change column a aa integer");
database.execute("alter table foo change column c cc integer");
String dump = new SqlDumper().dump(database.dataStore());
assertEquals("CREATE TABLE foo(\n" +
" aa INTEGER,\n" +
" b INTEGER,\n" +
" cc INTEGER,\n" +
" PRIMARY KEY(aa, b)\n" +
");\n" +
"CREATE INDEX an_index ON foo(cc);\n\n",
dump);
}
public void testRenameForeignKeyTarget() throws Exception {
Database database = new Database();
database.execute("create table foo(id integer primary key)");
database.execute("create table bar(foo_id integer," +
"foreign key(foo_id) references foo(id))");
String rename =
"alter table foo change column id identifier integer";
if (false) {
database.execute(rename);
String dump = new SqlDumper().dump(database.dataStore());
assertEquals("CREATE TABLE foo(\n" +
" identifier INTEGER,\n" +
" PRIMARY KEY(identifier)\n" +
");\n\n" +
"CREATE TABLE bar(\n" +
" foo_id INTEGER,\n" +
" FOREIGN KEY(foo_id) REFERENCES foo(identifier)\n" +
");\n\n",
dump);
}
else {
/* We wish we were able to just rename the identifier
in the foreign key. But at a minimum, throw an
exception rather than leave the foreign key dangling
and pointing at a nonexistent column. */
try {
database.execute(rename);
fail();
}
catch (MayflyException e) {
assertEquals(
"the column id is referenced by " +
"a foreign key in table bar, column foo_id",
e.getMessage());
}
}
}
}