/**
* 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.qp.operator;
import com.foundationdb.ais.model.AkibanInformationSchema;
import com.foundationdb.qp.row.Row;
import com.foundationdb.qp.rowtype.Schema;
import com.foundationdb.qp.rowtype.RowType;
import com.foundationdb.server.error.SetWrongTypeColumns;
import com.foundationdb.server.types.mcompat.mtypes.MNumeric;
import com.foundationdb.server.types.mcompat.mtypes.MString;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
public class UnionAll_DefaultTest {
protected boolean openBoth() {
return false;
}
private Schema newSchema() {
return new Schema(new AkibanInformationSchema());
}
@Test
public void unionTwoNormal() {
Schema schema = newSchema();
RowsBuilder first = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar(), MString.varchar())
.row(1L, "one", null)
.row(2L, "two", null)
.row(1L, "one", null);
RowsBuilder second = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar(), MString.varchar())
.row(3L, "three", null)
.row(1L, "one", null)
.row(2L, "deux", null);
RowsBuilder expected = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar(), MString.varchar())
.row(1L, "one", null)
.row(2L, "two", null)
.row(1L, "one", null)
.row(3L, "three", null)
.row(1L, "one", null)
.row(2L, "deux", null);
check(first, second, expected);
}
@Test
public void firstInputEmpty() {
Schema schema = newSchema();
RowsBuilder first = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
RowsBuilder second = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar())
.row(1L, "one")
.row(2L, "two")
.row(1L, "one");
RowsBuilder expected = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar())
.row(1L, "one")
.row(2L, "two")
.row(1L, "one");
check(first, second, expected);
}
@Test
public void secondInputEmpty() {
Schema schema = newSchema();
RowsBuilder first = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar())
.row(1L, "one")
.row(2L, "two")
.row(1L, "one");
RowsBuilder second = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
RowsBuilder expected = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar())
.row(1L, "one")
.row(2L, "two")
.row(1L, "one");
check(first, second, expected);
}
@Test
public void nullPromotedInSecondRowType() {
Schema schema = newSchema();
RowsBuilder first = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar())
.row(1, "one");
RowsBuilder second = new RowsBuilder(schema,MNumeric.INT.instance(false), MString.varchar())
.row(2, null);
RowsBuilder expected = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar())
.row(1, "one")
.row(2, null);
check(first, second, expected);
}
@Test
public void nullPromotedInFirstRowType() {
Schema schema = newSchema();
RowsBuilder first = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar())
.row(1, null);
RowsBuilder second = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar())
.row(2, "two");
RowsBuilder expected = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar())
.row(1, null)
.row(2, "two");
check(first, second, expected);
}
@Test
public void twoOpens() {
Schema schema = newSchema();
RowsBuilder first = new RowsBuilder(schema, MNumeric.INT.instance(false))
.row(1L);
RowsBuilder second = new RowsBuilder(schema,MNumeric.INT.instance(false))
.row(2L);
Operator union = union(first, second);
Cursor cursor = OperatorTestHelper.open(union);
int count = 0;
while(cursor.next() != null) {
++count;
}
assertEquals("count", 2, count);
cursor.close();
count = 0;
OperatorTestHelper.reopen(cursor);
while(cursor.next() != null) {
++count;
}
assertEquals("count", 2, count);
}
@Test
public void bothInputsEmpty() {
Schema schema = newSchema();
RowsBuilder first = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
RowsBuilder second = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
RowsBuilder expected = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
check(first, second, expected);
}
@Test
public void bothInputsSameRowType() {
Schema schema = newSchema();
RowsBuilder first = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar())
.row(1L, "one");
RowsBuilder second = new RowsBuilder(first.rowType())
.row(2L, "two");
RowsBuilder expected = new RowsBuilder(first.rowType())
.row(1L, "one")
.row(2L, "two");
Operator union = union(first, second);
assertSame("rowType", first.rowType(), union.rowType());
check(first, second, expected);
}
@Test(expected = SetWrongTypeColumns.class)
public void inputsNotOfRightShape() {
Schema schema = newSchema();
RowsBuilder first = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
RowsBuilder second = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.TEXT.instance(false));
union(first, second);
}
@Test(expected = IllegalArgumentException.class)
public void firstOperatorIsNull() {
Schema schema = newSchema();
RowsBuilder first = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
RowsBuilder second = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
new UnionAll_Default(null, first.rowType(), new TestOperator(second), second.rowType(), openBoth());
}
@Test(expected = IllegalArgumentException.class)
public void firstRowTypeIsNull() {
Schema schema = newSchema();
RowsBuilder first = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
RowsBuilder second = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
new UnionAll_Default(new TestOperator(first), null, new TestOperator(second), second.rowType(), openBoth());
}
@Test(expected = IllegalArgumentException.class)
public void secondOperatorIsNull() {
Schema schema = newSchema();
RowsBuilder first = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
RowsBuilder second = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
new UnionAll_Default(new TestOperator(first), first.rowType(), null, second.rowType(), openBoth());
}
@Test(expected = IllegalArgumentException.class)
public void secondRowTypeIsNull() {
Schema schema = newSchema();
RowsBuilder first = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
RowsBuilder second = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
new UnionAll_Default(new TestOperator(first), first.rowType(), new TestOperator(second), null, openBoth());
}
/**
* Tests what happens when one of the input streams outputs a rowType other than what we promised it would.
* To make this test a bit more interesting, the outputted row is actually of the same shape as the expected
* results: it just has a different rowTypeId.
*/
@Test(expected = UnionAll_Default.WrongRowTypeException.class)
public void inputsContainUnspecifiedRows() {
Schema schema = newSchema();
RowsBuilder first = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
RowsBuilder second = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar());
RowsBuilder anotherStream = new RowsBuilder(schema, MNumeric.INT.instance(false), MString.varchar())
.row(3, "three");
first.rows().push(anotherStream.rows().pop());
Operator union = union(first, second);
OperatorTestHelper.execute(union);
}
private void check(Operator union, RowsBuilder expected) {
final RowType outputRowType = union.rowType();
checkRowTypes(expected.rowType(), outputRowType);
OperatorTestHelper.check(union, expected.rows(), new OperatorTestHelper.RowCheck() {
@Override
public void check(Row row) {
assertEquals("row types", outputRowType, row.rowType());
}
});
}
private void check(RowsBuilder rb1, RowsBuilder rb2, RowsBuilder expected) {
check(union(rb1, rb2), expected);
}
private static void checkRowTypes(RowType expected, RowType actual) {
assertEquals("number of fields", expected.nFields(), actual.nFields());
for (int i=0; i < expected.nFields(); ++i) {
assertEquals("field " + i, expected.typeAt(i), actual.typeAt(i));
}
}
private Operator union(RowsBuilder rb1, RowsBuilder rb2) {
return new UnionAll_Default(
new TestOperator(rb1),
rb1.rowType(),
new TestOperator(rb2),
rb2.rowType(),
openBoth()
);
}
}