/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.foundationdb.sql.aisddl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import com.foundationdb.ais.model.ForeignKey;
import com.foundationdb.server.error.UnsupportedSQLException;
import org.junit.Test;
import com.foundationdb.ais.model.Column;
import com.foundationdb.ais.model.Index;
import com.foundationdb.ais.model.Table;
import com.foundationdb.ais.model.TableIndex;
import com.foundationdb.server.error.DuplicateSequenceNameException;
import com.foundationdb.server.error.NoSuchTableException;
import com.foundationdb.server.service.servicemanager.GuicedServiceManager;
import java.util.Map;
public class TableDDLIT extends AISDDLITBase {
private static final String DROP_T1 = "DROP TABLE test.t1";
private static final String DROP_T2 = "DROP TABLE test.t2";
@Override
protected GuicedServiceManager.BindingsConfigurationProvider serviceBindingsProvider() {
return super.serviceBindingsProvider();
}
@Override
protected Map<String, String> startupConfigProperties() {
return uniqueStartupConfigProperties(TableDDLIT.class);
}
@Test (expected=NoSuchTableException.class)
public void testDropFail() throws Exception {
String sql = "DROP TABLE test.not_here";
executeDDL(sql);
}
@Test
public void testCreateSimple() throws Exception {
String sqlCreate = "CREATE TABLE test.T1 (c1 integer not null primary key)";
executeDDL(sqlCreate);
assertNotNull (ais().getTable ("test", "t1"));
executeDDL(DROP_T1);
assertNull (ais().getTable("test", "t1"));
}
@Test
public void testCreateIndexes() throws Exception {
String sql = "CREATE TABLE test.t1 (c1 integer not null primary key, " +
"c2 integer not null, " +
"constraint c2 unique (c2))";
executeDDL(sql);
Table table = ais().getTable("test", "t1");
assertNotNull (table);
assertNotNull (table.getPrimaryKey());
assertEquals ("PRIMARY", table.getPrimaryKey().getIndex().getIndexName().getName());
assertEquals (2, table.getIndexes().size());
assertNotNull (table.getIndex("PRIMARY"));
assertNotNull (table.getIndex("c2"));
executeDDL(DROP_T1);
}
@Test
public void testCreateJoin() throws Exception {
String sql1 = "CREATE TABLE test.t1 (c1 integer not null primary key)";
String sql2 = "CREATE TABLE test.t2 (c1 integer not null primary key, " +
"c2 integer not null, grouping foreign key (c2) references test.t1)";
executeDDL(sql1);
executeDDL(sql2);
Table table = ais().getTable("test", "t2");
assertNotNull (table);
assertEquals (2, ais().getJoins().size());
assertNotNull (table.getParentJoin());
executeDDL(DROP_T2);
executeDDL(DROP_T1);
}
@Test
public void testCreateAutoIncrement() throws Exception {
String sql = "CREATE TABLE test.t1 (c1 integer not null primary key generated by default as identity " +
"(start with 1000, increment by 1))";
executeDDL(sql);
Table table = ais().getTable("test", "t1");
assertNotNull(table);
assertEquals("INT", table.getColumn(0).getTypeName());
assertEquals(table.getPrimaryKey().getColumns().get(0), table.getColumn(0));
assertEquals(1000L, table.getColumn(0).getIdentityGenerator().getStartsWith());
}
@Test
public void testCreateInteger() throws Exception {
String sql1 = "CREATE TABLE test.t1 (col1 INTEGER NOT NULL, col2 INTEGER, col3 smallint NOT NULL, "+
"col4 smallint, col5 bigint NOT NULL, col6 bigint, " +
"col7 INTEGER UNSIGNED, col8 smallint unsigned)";
executeDDL(sql1);
Table table = ais().getTable("test", "t1");
assertNotNull (table);
assertEquals ("INT", table.getColumn(0).getTypeName());
assertFalse (table.getColumn(0).getNullable());
assertEquals ("INT", table.getColumn(1).getTypeName());
assertTrue (table.getColumn(1).getNullable());
assertEquals ("SMALLINT", table.getColumn(2).getTypeName());
assertFalse (table.getColumn(2).getNullable());
assertEquals ("SMALLINT", table.getColumn(3).getTypeName());
assertTrue (table.getColumn(3).getNullable());
assertEquals ("BIGINT", table.getColumn(4).getTypeName());
assertFalse (table.getColumn(4).getNullable());
assertEquals ("BIGINT", table.getColumn(5).getTypeName());
assertTrue (table.getColumn(5).getNullable());
assertEquals ("INT UNSIGNED", table.getColumn(6).getTypeName());
assertTrue (table.getColumn(6).getNullable());
assertEquals ("SMALLINT UNSIGNED", table.getColumn(7).getTypeName());
assertTrue (table.getColumn(7).getNullable());
}
@Test
public void testCreateChar() throws Exception {
String sql1 = "CREATE TABLE test.T1 (col10 CHAR(1) NOT NULL, col11 CHAR(1), " +
"col12 VARCHAR(1) NOT NULL, col13 VARCHAR(1), " +
" col14 LONG VARCHAR NOT NULL, col15 LONG VARCHAR) ";
executeDDL(sql1);
Table table = ais().getTable("test", "t1");
assertNotNull (table);
assertEquals ("CHAR", table.getColumn(0).getTypeName());
assertEquals (Long.valueOf(5), table.getColumn(0).getMaxStorageSize());
assertEquals (Long.valueOf(1), table.getColumn(0).getTypeParameter1());
assertEquals ("CHAR", table.getColumn(1).getTypeName());
assertEquals (Long.valueOf(5), table.getColumn(1).getMaxStorageSize());
assertEquals ("VARCHAR", table.getColumn(2).getTypeName());
assertEquals (Long.valueOf(5), table.getColumn(2).getMaxStorageSize());
assertEquals ("VARCHAR", table.getColumn(3).getTypeName());
assertEquals (Long.valueOf(5), table.getColumn(3).getMaxStorageSize());
assertEquals ("LONGTEXT", table.getColumn(4).getTypeName());
assertFalse (table.getColumn(4).getNullable());
assertEquals (Long.valueOf(1047556), table.getColumn(4).getMaxStorageSize());
assertEquals ("LONGTEXT", table.getColumn(5).getTypeName());
}
@Test
public void testCreateTime() throws Exception {
String sql1 = "CREATE TABLE test.t1 (col30 DATE NOT NULL, col31 DATE, "+
"col32 TIME NOT NULL, col33 time, col34 timestamp NOT NULL, " +
"col35 timestamp)";
executeDDL(sql1);
Table table = ais().getTable("test", "t1");
assertNotNull (table);
assertEquals ("DATE", table.getColumn(0).getTypeName());
assertFalse (table.getColumn(0).getNullable());
assertEquals ("DATE", table.getColumn(1).getTypeName());
assertEquals ("TIME", table.getColumn(2).getTypeName());
assertEquals ("TIME", table.getColumn(3).getTypeName());
assertEquals ("DATETIME", table.getColumn(4).getTypeName());
assertEquals ("DATETIME", table.getColumn(5).getTypeName());
}
@Test
public void testCreateLOB() throws Exception {
String sql1 = "CREATE TABLE test.t1 (col40 CLOB NOT NULL, col41 CLOB, col42 BLOB NOT NULL, col43 BLOB)";
executeDDL(sql1);
Table table = ais().getTable("test", "t1");
assertNotNull (table);
assertEquals ("LONGTEXT", table.getColumn(0).getTypeName());
assertEquals ("LONGTEXT", table.getColumn(1).getTypeName());
assertEquals ("BLOB", table.getColumn(2).getTypeName());
assertEquals ("BLOB", table.getColumn(3).getTypeName());
}
@Test
public void testCreateFloat() throws Exception {
String sql1 = "CREATE TABLE test.t1 (col20 FLOAT NOT NULL, col21 FLOAT, "+
"col22 REAL NOT NULL, col23 REAL, col24 DOUBLE NOT NULL, col25 DOUBLE," +
"col26 DOUBLE UNSIGNED, col27 REAL UNSIGNED, col28 NUMERIC)";
executeDDL(sql1);
Table table = ais().getTable("test", "t1");
assertNotNull (table);
assertEquals ("DOUBLE", table.getColumn(0).getTypeName());
assertEquals ("DOUBLE", table.getColumn(1).getTypeName());
assertEquals ("FLOAT", table.getColumn(2).getTypeName());
assertEquals ("FLOAT", table.getColumn(3).getTypeName());
assertEquals ("DOUBLE", table.getColumn(4).getTypeName());
assertEquals ("DOUBLE", table.getColumn(5).getTypeName());
assertEquals ("DOUBLE UNSIGNED", table.getColumn(6).getTypeName());
assertEquals ("FLOAT UNSIGNED", table.getColumn(7).getTypeName());
assertEquals ("DECIMAL", table.getColumn(8).getTypeName());
}
@Test
public void testCreateDecimal () throws Exception {
String sql1 = "CREATE TABLE test.t1 (col50 DECIMAL NOT NULL, col51 DECIMAL,"+
"col52 DECIMAL (1) NOT NULL, "+
"col54 DECIMAL (10) NOT NULL, " +
"col57 DECIMAL (1,1), col58 DECIMAL (10,1) NOT NULL, " +
"col60 DECIMAL (10,10) NOT NULL, " +
"col63 DECIMAL (30,10))";
executeDDL(sql1);
Table table = ais().getTable("test", "t1");
assertNotNull (table);
assertEquals ("DECIMAL", table.getColumn(0).getTypeName());
assertEquals (Long.valueOf(5), table.getColumn(0).getTypeParameter1());
assertEquals (Long.valueOf(0), table.getColumn(0).getTypeParameter2());
assertEquals ("DECIMAL", table.getColumn(1).getTypeName());
assertTrue (table.getColumn(1).getNullable());
assertEquals ("DECIMAL", table.getColumn(2).getTypeName());
assertEquals (Long.valueOf(1), table.getColumn(2).getTypeParameter1());
assertEquals (Long.valueOf(0), table.getColumn(2).getTypeParameter2());
assertEquals ("DECIMAL", table.getColumn(3).getTypeName());
assertEquals (Long.valueOf(10), table.getColumn(3).getTypeParameter1());
assertEquals (Long.valueOf(0), table.getColumn(3).getTypeParameter2());
assertEquals ("DECIMAL", table.getColumn(4).getTypeName());
assertEquals (Long.valueOf(1), table.getColumn(4).getTypeParameter1());
assertEquals (Long.valueOf(1), table.getColumn(4).getTypeParameter2());
assertEquals ("DECIMAL", table.getColumn(5).getTypeName());
assertEquals (Long.valueOf(10), table.getColumn(5).getTypeParameter1());
assertEquals (Long.valueOf(1), table.getColumn(5).getTypeParameter2());
assertEquals ("DECIMAL", table.getColumn(6).getTypeName());
assertEquals (Long.valueOf(10), table.getColumn(6).getTypeParameter1());
assertEquals (Long.valueOf(10), table.getColumn(6).getTypeParameter2());
assertEquals ("DECIMAL", table.getColumn(7).getTypeName());
assertEquals (Long.valueOf(30), table.getColumn(7).getTypeParameter1());
assertEquals (Long.valueOf(10), table.getColumn(7).getTypeParameter2());
}
@Test
public void createCustomers() throws Exception {
String sql1 = "create table test.customers (" +
"customer_id int not null primary key generated by default as identity," +
"customer_name varchar(255) not null,"+
"primary_payment_code char(1) not null default 'C', " +
"payment_status char(4) not null default 'ABCD', " +
"comment varchar(255))";
String sql2 = "create table test.addresses (" +
"customer_id int not null," +
"state varchar(2) not null," +
"zip_code varchar(5) not null," +
"phone varchar (15)," +
"primary key (customer_id, zip_code)," +
"grouping foreign key (customer_id) references customers)";
executeDDL(sql1);
Table table = ais().getTable("test", "customers");
assertNotNull(table);
assertEquals(5, table.getColumns().size());
executeDDL(sql2);
table = ais().getTable("test", "addresses");
assertNotNull(table);
assertEquals(4, table.getColumns().size());
}
@Test
public void createIdentity () throws Exception {
String sql = "CREATE TABLE test.t7 (c1 integer primary key generated by default as identity)";
executeDDL(sql);
Table table = ais().getTable("test", "t7");
assertNotNull(table);
Column column = table.getColumn(0);
assertNotNull(column.getIdentityGenerator());
assertEquals (1, column.getIdentityGenerator().getStartsWith());
assertEquals (1, column.getIdentityGenerator().getIncrement());
assertNotNull(column.getDefaultIdentity());
assertTrue(column.getDefaultIdentity().booleanValue());
}
@Test
public void createAlwaysIdentity() throws Exception {
String sql = "CREATE TABLE test.t9 (c1 integer primary key generated ALWAYS as identity)";
executeDDL(sql);
Table table = ais().getTable("test", "t9");
assertNotNull(table);
Column column = table.getColumn(0);
assertNotNull(column.getIdentityGenerator());
assertEquals (1, column.getIdentityGenerator().getStartsWith());
assertEquals (1, column.getIdentityGenerator().getIncrement());
assertNotNull(column.getDefaultIdentity());
assertFalse(column.getDefaultIdentity().booleanValue());
}
@Test
public void createIdentityValues() throws Exception {
String sql = "CREATE TABLE test.t10 (c1 integer primary key generated by default as identity (start with 11, increment by -1))";
executeDDL(sql);
Table table = ais().getTable("test", "t10");
assertNotNull(table);
Column column = table.getColumn(0);
assertNotNull(column.getIdentityGenerator());
assertEquals (11, column.getIdentityGenerator().getStartsWith());
assertEquals (-1, column.getIdentityGenerator().getIncrement());
assertNotNull(column.getDefaultIdentity());
assertTrue(column.getDefaultIdentity().booleanValue());
}
@Test
public void dropTableWithIdentity() throws Exception {
assertEquals (0, ais().getSequences().size());
String sql = "CREATE TABLE test.t11 (c1 integer primary key generated by default as identity)";
executeDDL(sql);
sql = "CREATE TABLE test.t12 (c1 integer primary key generated by default as identity)";
executeDDL(sql);
assertEquals (2, ais().getSequences().size());
sql = "DROP TABLE test.t11";
executeDDL(sql);
assertEquals (1, ais().getSequences().size());
sql = "DROP TABLE test.t12";
executeDDL(sql);
assertEquals (0, ais().getSequences().size());
}
@Test
public void createSerialTable() throws Exception {
String sql = "CREATE TABLE test.t12 (c1 SERIAL PRIMARY KEY)";
executeDDL(sql);
Table table = ais().getTable("test", "t12");
assertNotNull (table);
Column column = table.getColumn(0);
assertEquals ("INT", column.getTypeName());
assertEquals (column.getNullable(), false);
assertNotNull (column.getIdentityGenerator());
assertEquals (1, column.getIdentityGenerator().getStartsWith());
assertEquals (1, column.getIdentityGenerator().getIncrement());
assertNotNull(column.getDefaultIdentity());
assertTrue(column.getDefaultIdentity());
// No column index auto created
assertNull (table.getIndex("c1"));
// Primary key is
assertNotNull (table.getPrimaryKey());
Index index = table.getPrimaryKey().getIndex();
assertEquals (1, index.getKeyColumns().size());
}
@Test (expected=DuplicateSequenceNameException.class)
public void createDoubleSerialTable() throws Exception {
String sql = "CREATE TABLE test.t13 (c1 SERIAL PRIMARY KEY, c2 SERIAL)";
executeDDL(sql);
}
@Test
public void createIndexTable() throws Exception {
String sql = "CREATE TABLE test.t14 (c1 INT NOT NULL PRIMARY KEY, c2 INT NOT NULL, INDEX (c2))";
executeDDL(sql);
Table table = ais().getTable("test", "t14");
Index index = table.getIndex("c2");
assertNotNull(index);
assertFalse (index.isUnique());
assertEquals(1, index.getKeyColumns().size());
assertFalse(index.isGroupIndex());
assertFalse(index.isSpatial());
}
@Test
public void createNamedIndexTable() throws Exception {
String sql = "CREATE TABLE test.t15 (c1 int NOT NULL, c2 INT NOT NULL, INDEX idx_c2 (c2))";
executeDDL(sql);
Table table = ais().getTable("test", "t15");
Index index = table.getIndex("idx_c2");
assertNotNull(index);
assertFalse (index.isUnique());
assertEquals(1, index.getKeyColumns().size());
assertFalse(index.isGroupIndex());
assertFalse(index.isSpatial());
}
@Test
public void createSpatialIndexTable() throws Exception {
String sql = "CREATE TABLE test.t16 (c1 decimal(11,7), c2 decimal(11,7), INDEX idx1 (z_order_lat_lon(c1, c2)))";
executeDDL (sql);
Table table = ais().getTable("test", "t16");
TableIndex index = table.getIndex("idx1");
assertNotNull(index);
assertFalse (index.isUnique());
assertEquals(2, index.getKeyColumns().size());
assertTrue (index.isSpatial());
}
@Test
public void testCreateNationalChar() throws Exception {
String sql1 = "CREATE TABLE test.T1 (c1 NATIONAL CHAR(10), c2 NATIONAL CHARACTER VARYING(10), c3 LONG NVARCHAR) ";
executeDDL(sql1);
Table table = ais().getTable("test", "t1");
assertNotNull (table);
assertEquals ("CHAR", table.getColumn(0).getTypeName());
assertEquals ("VARCHAR", table.getColumn(1).getTypeName());
assertEquals ("LONGTEXT", table.getColumn(2).getTypeName());
}
@Test
public void overlappingFKAndGFK() throws Exception {
executeDDL("CREATE TABLE parent(pid INT NOT NULL PRIMARY KEY)");
executeDDL("CREATE TABLE child (cid INT NOT NULL PRIMARY KEY, pid INT," +
" FOREIGN KEY(pid) REFERENCES parent(pid)," +
" GROUPING FOREIGN KEY(pid) REFERENCES parent(pid))");
Table p = ais().getTable("test", "parent");
Table c = ais().getTable("test", "child");
assertNotNull(p);
assertNotNull(c);
assertEquals(p.getGroup(), c.getGroup());
assertEquals(1, p.getReferencedForeignKeys().size());
assertEquals(1, c.getReferencingForeignKeys().size());
}
@Test
public void selfFK() throws Exception {
executeDDL("CREATE TABLE t(id1 INT NOT NULL PRIMARY KEY, id2 INT, FOREIGN KEY(id2) REFERENCES t(id1))");
Table t = ais().getTable("test", "t");
assertNotNull(t);
assertEquals(1, t.getForeignKeys().size());
ForeignKey fk = t.getForeignKeys().iterator().next();
assertEquals(t, fk.getReferencedTable());
assertEquals(fk.getReferencedTable(), fk.getReferencingTable());
}
@Test(expected= UnsupportedSQLException.class)
public void inlineGroupIndex() throws Exception {
executeDDL("CREATE TABLE parent(pid INT PRIMARY KEY, x INT)");
executeDDL("CREATE TABLE child(cid INT PRIMARY KEY, pid INT, y INT, "+
" GROUPING FOREIGN KEY(pid) REFERENCES parent, "+
" INDEX g_i (parent.x, child.y) USING LEFT JOIN)");
}
}