/**
* 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.error.DuplicateKeyException;
import com.foundationdb.server.error.InvalidOperationException;
import com.foundationdb.server.test.it.ITBase;
import org.junit.Test;
import java.util.List;
import static org.junit.Assert.*;
public final class UniqueKeyUpdateIT extends ITBase {
@Test
public void oneColumn() throws InvalidOperationException {
final String tableName = "t1";
final String schemaName = "s1";
final int tableId;
try {
tableId = createTable(schemaName, tableName, "cid int not null primary key", "u1 int", "UNIQUE(u1)");
writeRows(
row(tableId, 11, 21),
row(tableId, 12, 22)
);
} catch (InvalidOperationException e) {
throw new TestException(e);
}
Row original = row(tableId, 12, 22);
Row updated = row(tableId, 12, 21);
try {
updateRow(original, updated);
fail("expected DuplicateKeyException");
} catch (DuplicateKeyException e) {
// expected
}
expectRows(
tableId,
row(tableId, 11, 21),
row(tableId, 12, 22)
);
Index index = getTable(tableId).getIndex("u1");
expectRows(
index,
row(index, 21, 11),
row(index, 22, 12)
);
}
@Test
public void oneColumnHKeyEquivalent() throws InvalidOperationException {
final String tableName = "t1";
final String schemaName = "s1";
final int tableId;
try {
tableId = createTable(schemaName, tableName, "cid int not null primary key", "UNIQUE(cid)");
writeRows(
row(tableId, 11),
row(tableId, 12)
);
} catch (InvalidOperationException e) {
throw new TestException(e);
}
Row original = row(tableId, 12);
Row updated = row(tableId, 11);
try {
updateRow(original, updated);
fail("expected DuplicateKeyException");
} catch (DuplicateKeyException e) {
// expected
}
expectRows(
tableId,
row(tableId, 11),
row(tableId, 12)
);
Index index = getTable(tableId).getIndex("cid");
expectRows(
index,
row(index, 11),
row(index, 12)
);
}
@Test
public void oneColumnNoPK() throws InvalidOperationException {
final String tableName = "t1";
final String schemaName = "s1";
final int tableId;
final Index index;
final Row original;
final Row updated;
try {
tableId = createTable(schemaName, tableName, "cid int", "UNIQUE(cid)");
writeRows(
row(tableId, 1),
row(tableId, 2)
);
index = getTable(tableId).getIndex("cid");
List<Row> scan = scanAllIndex(index);
assertEquals("scan size", 2, scan.size());
assertEquals("scan[0] size", 2, scan.get(0).rowType().nFields());
assertEquals("scan[0][0]", 1, scan.get(0).value(0).getInt32());
assertEquals("scan[1] size", 2, scan.get(1).rowType().nFields());
assertEquals("scan[1][0]", 2, scan.get(1).value(0).getInt32());
Row irow = scan.get(0);
original = row(tableId, 1, irow.value(1).getInt64());
updated = row(tableId, 2, irow.value(1).getInt64());
} catch (InvalidOperationException e) {
throw new TestException(e);
}
try {
updateRow(original, updated);
fail("expected DuplicateKeyException");
} catch (DuplicateKeyException e) {
// expected
}
expectRowsSkipInternal(
index,
row(index, 1),
row(index, 2)
);
}
@Test
public void twoColumns() throws InvalidOperationException{
final String tableName = "t1";
final String schemaName = "s1";
final int tableId;
final Index index;
try {
tableId = createTable(schemaName, tableName, "cid int not null primary key", "u1 int", "u2 int", "UNIQUE(u1,u2)");
index = getTable(tableId).getIndex("u1");
writeRows(
row(tableId, 11, 21, 31),
row(tableId, 12, 22, 32),
row(tableId, 13, 20, 33)
);
expectRows(
index,
row(index, 20, 33, 13),
row(index, 21, 31, 11),
row(index, 22, 32, 12)
);
// update such that there's a similarity in u1
updateRow(
row(tableId, 12, 22, 32),
row(tableId, 12, 21, 32)
);
expectRows(
tableId,
row(tableId, 11, 21, 31),
row(tableId, 12, 21, 32),
row(tableId, 13, 20, 33)
);
expectRows(
index,
row(index, 20, 33, 13),
row(index, 21, 31, 11),
row(index, 21, 32, 12)
);
// update such that there's a similarity in u2
updateRow(
row(tableId, 12, 21, 32),
row(tableId, 12, 21, 33)
);
expectRows(
tableId,
row(tableId, 11, 21, 31),
row(tableId, 12, 21, 33),
row(tableId, 13, 20, 33)
);
expectRows(
index,
row(index, 20, 33, 13),
row(index, 21, 31, 11),
row(index, 21, 33, 12)
);
} catch (InvalidOperationException e) {
throw new TestException(e);
}
try {
updateRow(
row(tableId, 12, 21, 33),
row(tableId, 12, 21, 31)
);
fail("expected DuplicateKeyException");
} catch (DuplicateKeyException e) {
// expected
}
expectRows(
tableId,
row(tableId, 11, 21, 31),
row(tableId, 12, 21, 33),
row(tableId, 13, 20, 33)
);
expectRows(
index,
row(index, 20, 33, 13),
row(index, 21, 31, 11),
row(index, 21, 33, 12)
);
}
@Test
public void nullsAreNotDuplicates() throws InvalidOperationException {
final String tableName = "t1";
final String schemaName = "s1";
final int tableId;
try {
tableId = createTable(schemaName, tableName, "cid int not null primary key", "u1 int NULL", "UNIQUE(u1)");
writeRows(
row(tableId, 11, null),
row(tableId, 12, 22)
);
} catch (InvalidOperationException e) {
throw new TestException(e);
}
Row original = row(tableId, 12, 22);
Row updated = row(tableId, 12, null);
updateRow(original, updated);
expectRows(
tableId,
row(tableId, 11, null),
row(tableId, 12, null)
);
Index index = getTable(tableId).getIndex("u1");
expectRows(
index,
row(index, null, 11),
row(index, null, 12)
);
}
@Test
public void pkEnforcement() {
String tableName = "t1";
String schemaName = "s1";
int tableId;
try {
tableId = createTable(schemaName, tableName, "cid int not null primary key, cx int");
writeRows(
row(tableId, 1, 1),
row(tableId, 1, 2));
fail();
} catch (DuplicateKeyException e) {
// Expected
}
}
}