/**
* 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.keyupdate;
import com.foundationdb.ais.model.Index;
import com.foundationdb.qp.row.Row;
import com.foundationdb.server.api.dml.scan.NewRow;
import org.junit.Test;
public final class GroupIndexRjUpdateIT extends GIUpdateITBase {
@Test
public void placeholderNoOrphan() {
final Row r1, r2;
groupIndex("c.name", "o.when");
writeAndCheck(
r1 = row(c, 1L, "Bergy")
);
writeAndCheck(
r2 = row(o, 10L, 1L, "01-01-2001"),
"Bergy, 01-01-2001, 1, 10 => " + containing(c, o)
);
deleteAndCheck(r2);
deleteAndCheck(r1);
}
@Test
public void placeholderWithOrphan() {
final Row r1, r2;
groupIndex("c.name", "o.when");
writeAndCheck(
r1 = row(o, 10L, 1L, "01-01-2001"),
"null, 01-01-2001, 1, 10 => " + containing(o)
);
writeAndCheck(
r2 = row(c, 1L, "Bergy"),
"Bergy, 01-01-2001, 1, 10 => " + containing(c, o)
);
deleteAndCheck(
r2,
"null, 01-01-2001, 1, 10 => " + containing(o)
);
deleteAndCheck(r1);
}
@Test
public void coiNoOrphan() {
groupIndex("c.name", "o.when", "i.sku");
writeAndCheck(
row(c, 1L, "Horton")
);
writeAndCheck(
row(o, 11L, 1L, "01-01-2001")
);
writeAndCheck(
row(i, 101L, 11L, 1111),
"Horton, 01-01-2001, 1111, 1, 11, 101 => " + containing(c, o, i)
);
writeAndCheck(
row(i, 102L, 11L, 2222),
"Horton, 01-01-2001, 1111, 1, 11, 101 => " + containing(c, o, i),
"Horton, 01-01-2001, 2222, 1, 11, 102 => " + containing(c, o, i)
);
writeAndCheck(
row(i, 103L, 11L, 3333),
"Horton, 01-01-2001, 1111, 1, 11, 101 => " + containing(c, o, i),
"Horton, 01-01-2001, 2222, 1, 11, 102 => " + containing(c, o, i),
"Horton, 01-01-2001, 3333, 1, 11, 103 => " + containing(c, o, i)
);
writeAndCheck(
row(o, 12L, 1L, "02-02-2002"),
"Horton, 01-01-2001, 1111, 1, 11, 101 => " + containing(c, o, i),
"Horton, 01-01-2001, 2222, 1, 11, 102 => " + containing(c, o, i),
"Horton, 01-01-2001, 3333, 1, 11, 103 => " + containing(c, o, i)
);
writeAndCheck(row(a, 10001L, 1L, "Causeway"),
"Horton, 01-01-2001, 1111, 1, 11, 101 => " + containing(c, o, i),
"Horton, 01-01-2001, 2222, 1, 11, 102 => " + containing(c, o, i),
"Horton, 01-01-2001, 3333, 1, 11, 103 => " + containing(c, o, i)
);
// update parent
updateAndCheck(
row(o, 11L, 1L, "01-01-2001"),
row(o, 11L, 1L, "01-01-1999"), // party!
"Horton, 01-01-1999, 1111, 1, 11, 101 => " + containing(c, o, i),
"Horton, 01-01-1999, 2222, 1, 11, 102 => " + containing(c, o, i),
"Horton, 01-01-1999, 3333, 1, 11, 103 => " + containing(c, o, i)
);
// update child
updateAndCheck(
row(i, 102L, 11L, 2222),
row(i, 102L, 11L, 2442),
"Horton, 01-01-1999, 1111, 1, 11, 101 => " + containing(c, o, i),
"Horton, 01-01-1999, 2442, 1, 11, 102 => " + containing(c, o, i),
"Horton, 01-01-1999, 3333, 1, 11, 103 => " + containing(c, o, i)
);
// delete order
deleteAndCheck(
row(o, 11L, 1L, "01-01-1999"),
"null, null, 1111, null, 11, 101 => " + containing(i),
"null, null, 2442, null, 11, 102 => " + containing(i),
"null, null, 3333, null, 11, 103 => " + containing(i)
);
// delete item
deleteAndCheck(
row(i, 102L, 11L, 222211),
"null, null, 1111, null, 11, 101 => " + containing(i),
"null, null, 3333, null, 11, 103 => " + containing(i)
);
}
@Test
public void createGIOnFullyPopulatedTables() {
writeRows(
row(c, 1L, "Horton"),
row(o, 11L, 1L, "01-01-2001"),
row(i, 101L, 11L, 1111)
);
groupIndexNamed("name_when_sku", "c.name", "o.when", "i.sku");
checkIndex("name_when_sku",
"Horton, 01-01-2001, 1111, 1, 11, 101 => " + containing("name_when_sku", c, o, i)
);
}
@Test
public void createGIOnPartiallyPopulatedTablesFromLeaf() {
writeRows(
row(i, 101L, 11L, 1111)
);
groupIndexNamed("name_when_sku", "c.name", "o.when", "i.sku");
checkIndex("name_when_sku",
"null, null, 1111, null, 11, 101 => " + containing("name_when_sku", i)
);
}
@Test
public void createGiOnPartiallyPopulatedTablesFromMiddle() {
writeRows(
row(o, 11L, 1L, "01-01-2001"),
row(i, 101L, 11L, 1111)
);
groupIndexNamed("when_sku", "o.when", "i.sku");
checkIndex("when_sku",
"01-01-2001, 1111, 1, 11, 101 => " + containing("when_sku", o, i)
);
}
@Test
public void ihIndexNoOrphans() {
String indexName = groupIndex("i.sku", "h.handling_instructions");
writeRows(
row(c, 1L, "Horton"),
row(o, 11L, 1L, "01-01-2001"),
row(i, 101L, 11L, 1111),
row(h, 1001L, 101L, "handle with care")
);
checkIndex(indexName, "1111, handle with care, 1, 11, 101, 1001 => " + containing(i, h));
// delete from root on up
deleteRow(c, 1L, "Horton");
checkIndex(indexName, "1111, handle with care, 1, 11, 101, 1001 => " + containing(i, h));
deleteRow(o, 11L, 1L, "01-01-2001 => " + containing(i, h));
checkIndex(indexName, "1111, handle with care, null, 11, 101, 1001 => " + containing(i, h));
deleteRow(i, 101L, 11L, 1111);
checkIndex(indexName, "null, handle with care, null, null, 101, 1001 => " + containing(h));
deleteRow(h, 1001L, 101L, "handle with care");
checkIndex(indexName);
}
@Test
public void adoptionChangesHKeyNoCustomer() {
String indexName = groupIndex("i.sku", "h.handling_instructions");
writeRows(
row(i, 101L, 11L, 1111),
row(h, 1001L, 101L, "handle with care")
);
checkIndex(indexName,
"1111, handle with care, null, 11, 101, 1001 => " + containing(i, h)
);
// bring an o that adopts the i
final Row oRow;
writeAndCheck(
oRow = row(o, 11L, 1L, "01-01-2001"),
"1111, handle with care, 1, 11, 101, 1001 => " + containing(i, h)
);
deleteAndCheck(
oRow,
"1111, handle with care, null, 11, 101, 1001 => " + containing(i, h)
);
}
@Test
public void adoptionChangesHKeyWithC() {
String indexName = groupIndex("i.sku", "h.handling_instructions");
writeRows(
row(c, 1L, "Horton"),
row(i, 101L, 11L, 1111),
row(h, 1001L, 101L, "handle with care")
);
checkIndex(indexName,
"1111, handle with care, null, 11, 101, 1001 => " + containing(i, h)
);
// bring an o that adopts the i
writeRow(o, 11L, 1L, "01-01-2001");
checkIndex(indexName,
"1111, handle with care, 1, 11, 101, 1001 => " + containing(i, h)
);
}
@Test
public void updateModifiesHKeyWithinBranch() {
// branch is I-H, we're modifying the hkey of an H
groupIndex("i.sku", "h.handling_instructions");
writeAndCheck(row(c, 1L, "Horton"));
writeAndCheck(row(o, 11L, 1L, "01-01-2001"));
writeAndCheck(row(i, 101L, 11L, "1111"));
writeAndCheck(
row(h, 1001L, 101L, "don't break"),
"1111, don't break, 1, 11, 101, 1001 => " + containing(i, h)
);
writeAndCheck(
row(c, 2L, "David"),
"1111, don't break, 1, 11, 101, 1001 => " + containing(i, h)
);
writeAndCheck(
row(o, 12L, 2L, "02-02-2002"),
"1111, don't break, 1, 11, 101, 1001 => " + containing(i, h)
);
writeAndCheck(
row(h, 1002L, 102L, "do break"),
"null, do break, null, null, 102, 1002 => " + containing(h),
"1111, don't break, 1, 11, 101, 1001 => " + containing(i, h)
);
updateAndCheck(
row(i, 101L, 11L, "1111"),
row(i, 102L, 12L, "2222"),
"null, don't break, null, null, 101, 1001 => " + containing(h),
"2222, do break, 2, 12, 102, 1002 => " + containing(i, h)
);
}
public GroupIndexRjUpdateIT() {
super(Index.JoinType.RIGHT);
}
}