/** * 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.qp; import com.foundationdb.qp.operator.RowCursor; import com.foundationdb.qp.row.ValuesHolderRow; import com.foundationdb.qp.row.Row; import com.foundationdb.qp.rowtype.Schema; import com.foundationdb.qp.rowtype.TableRowType; import com.foundationdb.qp.util.MultiCursor; import com.foundationdb.server.api.dml.ColumnSelector; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; public class MultiCursorIT extends OperatorITBase { @Override protected void setupCreateSchema() { t = createTable( "schema", "t", "id int not null primary key"); } @Override protected void setupPostCreateSchema() { tRowType = schema.tableRowType(table(t)); queryContext = queryContext(adapter); queryBindings = queryContext.createBindings(); } @Test(expected=IllegalStateException.class) public void testSealed() { MultiCursor multiCursor = multiCursor(); multiCursor.open(); multiCursor.addCursor(new TestCursor(new int[]{})); } @Test public void testNoCursors() { RowCursor multiCursor = multiCursor(); multiCursor.open(); assertTrue(multiCursor.isIdle()); assertNull(multiCursor.next()); } @Test public void testOneCursor() { for (int n = 0; n < 10; n++) { int[] a = new int[n]; for (int i = 0; i < n; i++) { a[i] = i; } RowCursor multiCursor = multiCursor(new TestCursor(a)); multiCursor.open(); assertTrue(multiCursor.isActive()); Row row; long expected = 0; while ((row = multiCursor.next()) != null) { assertEquals(expected, unwrap(row)); expected++; } assertEquals(n, expected); assertTrue(multiCursor.isIdle()); } } @Test public void testMultipleCursors() { testMultipleCursors(false); } @Test public void testOpenAll() { testMultipleCursors(true); } private void testMultipleCursors(boolean openAll) { RowCursor multiCursor = multiCursor(openAll, new TestCursor(new int[]{}), new TestCursor(new int[]{0, 1, 2}), new TestCursor(new int[]{}), new TestCursor(new int[]{}), new TestCursor(new int[]{3}), new TestCursor(new int[]{}), new TestCursor(new int[]{})); multiCursor.open(); Row row; long expected = 0; while ((row = multiCursor.next()) != null) { assertEquals(expected, unwrap(row)); expected++; } assertEquals(4, expected); assertTrue(multiCursor.isIdle()); } private MultiCursor multiCursor(TestCursor ... cursors) { return multiCursor(false, cursors); } private MultiCursor multiCursor(boolean openAll, TestCursor ... cursors) { MultiCursor multiCursor = new MultiCursor(openAll); for (TestCursor cursor : cursors) { multiCursor.addCursor(cursor); } return multiCursor; } private int unwrap(Row row) { return getLong(row, 0).intValue(); } private int t; private TableRowType tRowType; private class TestCursor implements RowCursor { @Override public void open() { position = 0; } @Override public Row next() { Row row = null; if (position < items.length) { row = row(); position++; } return row; } @Override public void jump(Row row, ColumnSelector columnSelector) { throw new UnsupportedOperationException(); } @Override public void close() { position = items == null ? 0 : items.length; } @Override public boolean isIdle() { return position == items.length; } @Override public boolean isActive() { return position < items.length; } // TestCursor interface public TestCursor(int[] items) { this.items = items; } // For use by this class public Row row() { return new ValuesHolderRow(tRowType, items[position]); } // Object state private int[] items; private int position; @Override public boolean isClosed() { return items == null || position == items.length; } @Override public void setIdle() { } } }