/* * Licensed to Crate under one or more contributor license agreements. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership. Crate licenses this file * to you under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may * obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * However, if you have executed another commercial license agreement * with Crate these terms will supersede the license and you may use the * software solely pursuant to the terms of the relevant commercial * agreement. */ package io.crate.operation.projectors.fetch; import com.carrotsearch.hppc.*; import com.carrotsearch.hppc.cursors.IntCursor; import com.carrotsearch.hppc.cursors.IntObjectCursor; import io.crate.analyze.symbol.FetchReference; import io.crate.analyze.symbol.InputColumn; import io.crate.analyze.symbol.Symbol; import io.crate.data.Bucket; import io.crate.data.CollectionBucket; import io.crate.data.Row; import io.crate.data.Row1; import io.crate.metadata.Reference; import io.crate.metadata.ReferenceIdent; import io.crate.metadata.RowGranularity; import io.crate.metadata.TableIdent; import io.crate.planner.node.fetch.FetchSource; import io.crate.types.DataTypes; import org.junit.Test; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import static io.crate.analyze.TableDefinitions.USER_TABLE_IDENT; import static io.crate.testing.TestingHelpers.getFunctions; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; public class FetchBatchAccumulatorTest { private static final Reference ID = new Reference( new ReferenceIdent(USER_TABLE_IDENT, "id"), RowGranularity.DOC, DataTypes.LONG ); private DummyFetchOperation fetchOperation = new DummyFetchOperation(); @Test public void testFetchBatchAccumulatorMultipleFetches() throws Exception { FetchBatchAccumulator fetchBatchAccumulator = new FetchBatchAccumulator( fetchOperation, getFunctions(), buildOutputSymbols(), buildFetchProjectorContext(), 2 ); fetchBatchAccumulator.onItem(new Row1(1L)); fetchBatchAccumulator.onItem(new Row1(2L)); Iterator<? extends Row> result = fetchBatchAccumulator.processBatch(false).get(10, TimeUnit.SECONDS); assertThat(result.next().get(0), is(1)); assertThat(result.next().get(0), is(2)); fetchBatchAccumulator.onItem(new Row1(3L)); fetchBatchAccumulator.onItem(new Row1(4L)); result = fetchBatchAccumulator.processBatch(false).get(10, TimeUnit.SECONDS); assertThat(result.next().get(0), is(3)); assertThat(result.next().get(0), is(4)); } private static List<Symbol> buildOutputSymbols() { return Collections.singletonList(new FetchReference( new InputColumn(0), ID )); } private FetchProjectorContext buildFetchProjectorContext() { Map<String, IntSet> nodeToReaderIds = new HashMap<>(2); IntSet nodeReadersNodeOne = new IntHashSet(); nodeReadersNodeOne.add(0); IntSet nodeReadersNodeTwo = new IntHashSet(); nodeReadersNodeTwo.add(2); nodeToReaderIds.put("nodeOne", nodeReadersNodeOne); nodeToReaderIds.put("nodeTwo", nodeReadersNodeTwo); TreeMap<Integer, String> readerIndices = new TreeMap<>(); readerIndices.put(0, "t1"); Map<String, TableIdent> indexToTable = new HashMap<>(1); indexToTable.put("t1", USER_TABLE_IDENT); Map<TableIdent, FetchSource> tableToFetchSource = new HashMap<>(2); FetchSource fetchSource = new FetchSource(Collections.emptyList(), Collections.singletonList(new InputColumn(0)), Collections.singletonList(ID)); tableToFetchSource.put(USER_TABLE_IDENT, fetchSource); return new FetchProjectorContext( tableToFetchSource, nodeToReaderIds, readerIndices, indexToTable ); } private static class DummyFetchOperation implements FetchOperation { int numFetches = 0; @Override public CompletableFuture<IntObjectMap<? extends Bucket>> fetch(String nodeId, IntObjectMap<? extends IntContainer> toFetch, boolean closeContext) { numFetches++; IntObjectHashMap<Bucket> readerToBuckets = new IntObjectHashMap<>(); for (IntObjectCursor<? extends IntContainer> cursor : toFetch) { List<Object[]> rows = new ArrayList<>(); for (IntCursor docIdCursor : cursor.value) { rows.add(new Object[]{docIdCursor.value}); } readerToBuckets.put(cursor.key, new CollectionBucket(rows)); } return CompletableFuture.completedFuture(readerToBuckets); } } }