/** * 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.server.test.it.dxl; import com.foundationdb.ais.model.Table; import com.foundationdb.ais.model.TableName; import org.junit.After; import org.junit.Test; import java.util.Arrays; import com.foundationdb.ais.util.TableChangeValidator.ChangeLevel; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; /** * Group altering actions on CAOI schema with conflated pk/fk all the way down. * Highly unlikely, but good test none-the-less. */ public class AlterTableCAOIConflatedKeysIT extends AlterTableITBase { private static final String A_TABLE = "a"; private static final TableName A_NAME = new TableName(SCHEMA, A_TABLE); private int cid; private int aid; private int oid; private int iid; @After public void clearTableIDs() { cid = aid = oid = iid = -1; } @Override protected ChangeLevel getDefaultChangeLevel() { return ChangeLevel.GROUP; } @Override protected void createAndLoadCAOI_PK_FK(boolean cPK, boolean aPK, boolean aFK, boolean oPK, boolean oFK, boolean iPK, boolean iFK) { cid = createTable(C_NAME, "id int not null "+(cPK ? "primary key" : "")+", cc varchar(5)" ); aid = createTable(A_NAME, "id int not null "+(aPK ? "primary key" : "")+", aa varchar(5)"+ (aFK ? "," + akibanFK("id", C_TABLE, "id") : "")); oid = createTable(O_NAME, "id int not null "+(oPK ? "primary key" : "")+", oo varchar(5)"+ (oFK ? "," + akibanFK("id", C_TABLE, "id") : "")); iid = createTable(I_NAME, "id int not null "+(iPK ? "primary key" : "")+", ii varchar(5)"+ (iFK ? "," + akibanFK("id", O_TABLE, "id") : "")); // Index on non-pk, non-fk column createIndex(SCHEMA, C_TABLE, "cc", "cc"); createIndex(SCHEMA, A_TABLE, "aa", "aa"); createIndex(SCHEMA, O_TABLE, "oo", "oo"); createIndex(SCHEMA, I_TABLE, "ii", "ii"); // Default post indexes presence checking checkedIndexes.put(cid, Arrays.asList("PRIMARY", "cc")); checkedIndexes.put(aid, Arrays.asList("PRIMARY", "aa")); checkedIndexes.put(oid, Arrays.asList("PRIMARY", "oo")); checkedIndexes.put(iid, Arrays.asList("PRIMARY", "ii")); txnService().beginTransaction(session()); // Data writeRows( row(cid, 1L, "1"), row(aid, 1L, "11"), row(iid, 10L, "110"), row(cid, 2L, "2"), // No children // No cust(3L) row(oid, 3L, "33"), // Level 1 orphan row(iid, 3L, "330"), row(cid, 4L, "4"), row(aid, 4L, "44"), // No 40 order row(iid, 40L, "440"), // Level 2 orphan // No cust(5L) row(aid, 5L, "55") // Level 1 orphan ); txnService().commitTransaction(session()); } private void groupsMatch(TableName name1, TableName... names) { Table t1 = getTable(name1); for(TableName name : names) { Table t2 = getTable(name); assertSame("Groups match for " + name1 + " and " + name, t1.getGroup(), t2.getGroup()); } } private void groupsDiffer(TableName name1, TableName... names) { Table t1 = getTable(name1); for(TableName name : names) { Table t2 = getTable(name); assertNotSame("Groups differ for " + name1 + " and " + name, t1.getGroup(), t2.getGroup()); } } // // SET DATA TYPE, parent/child column // @Test public void setDataType_C_id() { createAndLoadCAOI(); runAlter("ALTER TABLE " + C_TABLE + " ALTER COLUMN id SET DATA TYPE varchar(32)"); groupsDiffer(C_NAME, A_NAME, O_NAME, I_NAME); groupsDiffer(A_NAME, O_NAME, I_NAME); groupsMatch(O_NAME, I_NAME); } @Test public void setDataType_A_id() { createAndLoadCAOI(); runAlter("ALTER TABLE " + A_TABLE + " ALTER COLUMN id SET DATA TYPE varchar(32)"); groupsDiffer(C_NAME, A_NAME); groupsMatch(C_NAME, O_NAME, I_NAME); } @Test public void setDataType_O_id() { createAndLoadCAOI(); runAlter("ALTER TABLE " + O_TABLE + " ALTER COLUMN id SET DATA TYPE varchar(32)"); groupsDiffer(C_NAME, O_NAME); groupsDiffer(O_NAME, I_NAME); groupsMatch(C_NAME, A_NAME); } @Test public void setDataType_I_id() { createAndLoadCAOI(); runAlter("ALTER TABLE " + I_TABLE + " ALTER COLUMN id SET DATA TYPE varchar(32)"); groupsDiffer(O_NAME, I_NAME); groupsMatch(C_NAME, A_NAME, O_NAME); } // // DROP COLUMN <pk and fk column> // @Test public void dropColumn_C_id() { createAndLoadCAOI(); runAlter("ALTER TABLE "+C_TABLE+" DROP COLUMN id"); groupsDiffer(C_NAME, A_NAME, O_NAME, I_NAME); groupsDiffer(A_NAME, O_NAME, I_NAME); groupsMatch(O_NAME, I_NAME); checkIndexesInstead(C_NAME, "cc"); } @Test public void dropColumn_A_id() { createAndLoadCAOI(); runAlter("ALTER TABLE "+A_TABLE+" DROP COLUMN id"); groupsDiffer(C_NAME, A_NAME); groupsMatch(C_NAME, O_NAME, I_NAME); checkIndexesInstead(A_NAME, "aa"); } @Test public void dropColumn_O_id() { createAndLoadCAOI(); runAlter("ALTER TABLE "+O_TABLE+" DROP COLUMN id"); groupsDiffer(C_NAME, O_NAME); groupsDiffer(O_NAME, I_NAME); groupsMatch(C_NAME, A_NAME); checkIndexesInstead(O_NAME, "oo"); } @Test public void dropColumn_I_id() { createAndLoadCAOI(); runAlter("ALTER TABLE "+I_TABLE+" DROP COLUMN id"); groupsDiffer(O_NAME, I_NAME); groupsMatch(C_NAME, A_NAME, O_NAME); checkIndexesInstead(I_NAME, "ii"); } // // ADD PRIMARY KEY // @Test public void addPrimaryKey_I() { createAndLoadCAOI_PK(true, true, true, false); runAlter("ALTER TABLE " + I_TABLE + " ADD PRIMARY KEY(id)"); groupsMatch(C_NAME, A_NAME, O_NAME, I_NAME); } // // DROP PRIMARY KEY // @Test public void dropPrimaryKey_C() { createAndLoadCAOI(); runAlter("ALTER TABLE "+C_TABLE+" DROP PRIMARY KEY"); groupsDiffer(C_NAME, A_NAME, O_NAME, I_NAME); groupsDiffer(A_NAME, O_NAME, I_NAME); groupsMatch(O_NAME, I_NAME); checkIndexesInstead(C_NAME, "cc"); } @Test public void dropPrimaryKey_A() { createAndLoadCAOI(); runAlter("ALTER TABLE "+A_TABLE+" DROP PRIMARY KEY"); groupsMatch(C_NAME, A_NAME, O_NAME, I_NAME); checkIndexesInstead(A_NAME, "aa"); } @Test public void dropPrimaryKey_O() { createAndLoadCAOI(); runAlter("ALTER TABLE "+O_TABLE+" DROP PRIMARY KEY"); groupsDiffer(I_NAME, C_NAME, A_NAME); groupsMatch(C_NAME, A_NAME, O_NAME); checkIndexesInstead(O_NAME, "oo"); } @Test public void dropPrimaryKey_I() { createAndLoadCAOI(); runAlter("ALTER TABLE "+I_TABLE+" DROP PRIMARY KEY"); groupsMatch(C_NAME, A_NAME, O_NAME, I_NAME); checkIndexesInstead(I_NAME, "ii"); } // // ADD GROUPING FOREIGN KEY // @Test public void addGroupingForeignKey_C() { String xTable = "x"; TableName xName = new TableName(SCHEMA, xTable); int xid = createTable(xName, "id varchar(5) not null primary key"); writeRows( row(xid, "1"), // Adopts 1 (well formed group) // Leave 2 orphan row(xid, "4"), // Adopts 2 (c has no children) row(xid, "5") // No Children ); createAndLoadCAOI_FK(true, true, true); runAlter("ALTER TABLE " + C_TABLE + " ADD GROUPING FOREIGN KEY(cc) REFERENCES x(id)"); groupsMatch(xName, C_NAME, A_NAME, O_NAME, I_NAME); } @Test public void addGroupingForeignKey_A() { createAndLoadCAOI_FK(false, true, true); runAlter("ALTER TABLE " + A_TABLE + " ADD GROUPING FOREIGN KEY(id) REFERENCES c(id)"); groupsMatch(C_NAME, A_NAME, O_NAME, I_NAME); } @Test public void addGroupingForeignKey_O() { createAndLoadCAOI_FK(true, false, true); runAlter("ALTER TABLE " + O_TABLE + " ADD GROUPING FOREIGN KEY(id) REFERENCES c(id)"); groupsMatch(C_NAME, A_NAME, O_NAME, I_NAME); } @Test public void addGroupingForeignKey_I() { createAndLoadCAOI_FK(true, true, false); runAlter("ALTER TABLE "+I_TABLE+" ADD GROUPING FOREIGN KEY(id) REFERENCES o(id)"); groupsMatch(C_NAME, A_NAME, O_NAME, I_NAME); } // // DROP GROUPING FOREIGN KEY // @Test public void dropGroupingForeignKey_A() { createAndLoadCAOI(); runAlter("ALTER TABLE "+A_TABLE+" DROP GROUPING FOREIGN KEY"); groupsDiffer(C_NAME, A_NAME); groupsMatch(C_NAME, O_NAME, I_NAME); } @Test public void dropGroupingForeignKey_O() { createAndLoadCAOI(); runAlter("ALTER TABLE "+O_TABLE+" DROP GROUPING FOREIGN KEY"); groupsDiffer(C_NAME, O_NAME); groupsMatch(O_NAME, I_NAME); groupsMatch(C_NAME, A_NAME); } @Test public void dropGroupingForeignKey_I() { createAndLoadCAOI(); runAlter("ALTER TABLE " + I_TABLE + " DROP GROUPING FOREIGN KEY"); groupsDiffer(O_NAME, I_NAME); groupsMatch(C_NAME, A_NAME, O_NAME); } // // RENAME TABLE // @Test public void renameTable_C_X() { createAndLoadCAOI(); runRenameTable(C_NAME, X_NAME); groupsMatch(X_NAME, A_NAME, O_NAME, I_NAME); } @Test public void renameTable_A_X() { createAndLoadCAOI(); runRenameTable(A_NAME, X_NAME); groupsMatch(C_NAME, X_NAME, O_NAME, I_NAME); } @Test public void renameTable_O_X() { createAndLoadCAOI(); runRenameTable(O_NAME, X_NAME); groupsMatch(C_NAME, A_NAME, X_NAME, I_NAME); } @Test public void renameTable_I_X() { createAndLoadCAOI(); runRenameTable(I_NAME, X_NAME); groupsMatch(C_NAME, A_NAME, O_NAME, X_NAME); } // // RENAME COLUMN <parent pk and fk> // @Test public void renameColumn_C_id() { createAndLoadCAOI(); runRenameColumn(C_NAME, "id", "di"); groupsMatch(C_NAME, A_NAME, O_NAME, I_NAME); } @Test public void renameColumn_A_id() { createAndLoadCAOI(); runRenameColumn(A_NAME, "id", "di"); groupsMatch(C_NAME, A_NAME, O_NAME, I_NAME); } @Test public void renameColumn_O_id() { createAndLoadCAOI(); runRenameColumn(O_NAME, "id", "di"); groupsMatch(C_NAME, A_NAME, O_NAME, I_NAME); } @Test public void renameColumn_I_id() { createAndLoadCAOI(); runRenameColumn(I_NAME, "id", "di"); groupsMatch(C_NAME, A_NAME, O_NAME, I_NAME); } }