/*
* Licensed 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.
*/
package com.facebook.presto.operator;
import com.facebook.presto.spi.Page;
import com.facebook.presto.spi.block.Block;
import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import java.util.List;
import java.util.Optional;
import static com.facebook.presto.operator.SyntheticAddress.decodePosition;
import static com.facebook.presto.operator.SyntheticAddress.decodeSliceIndex;
import static java.util.Objects.requireNonNull;
public class StandardJoinFilterFunction
implements JoinFilterFunction
{
private static final Block[] EMPTY_BLOCK_ARRAY = new Block[0];
private final InternalJoinFilterFunction filterFunction;
private final LongArrayList addresses;
private final List<Block[]> pages;
private final Optional<Integer> sortChannel;
public StandardJoinFilterFunction(InternalJoinFilterFunction filterFunction, LongArrayList addresses, List<List<Block>> channels, Optional<Integer> sortChannel)
{
this.filterFunction = requireNonNull(filterFunction, "filterFunction can not be null");
this.addresses = requireNonNull(addresses, "addresses is null");
this.sortChannel = requireNonNull(sortChannel, "sortChannel is null");
requireNonNull(channels, "channels can not be null");
ImmutableList.Builder<Block[]> pagesBuilder = ImmutableList.builder();
if (!channels.isEmpty()) {
int pagesCount = channels.get(0).size();
for (int pageIndex = 0; pageIndex < pagesCount; ++pageIndex) {
Block[] blocks = new Block[channels.size()];
for (int channelIndex = 0; channelIndex < channels.size(); ++channelIndex) {
blocks[channelIndex] = channels.get(channelIndex).get(pageIndex);
}
pagesBuilder.add(blocks);
}
}
this.pages = pagesBuilder.build();
}
@Override
public boolean filter(int leftAddress, int rightPosition, Page rightPage)
{
long pageAddress = addresses.getLong(leftAddress);
int blockIndex = decodeSliceIndex(pageAddress);
int blockPosition = decodePosition(pageAddress);
return filterFunction.filter(blockPosition, getLeftBlocks(blockIndex), rightPosition, rightPage.getBlocks());
}
@Override
public Optional<Integer> getSortChannel()
{
return sortChannel;
}
private Block[] getLeftBlocks(int leftBlockIndex)
{
if (pages.isEmpty()) {
return EMPTY_BLOCK_ARRAY;
}
else {
return pages.get(leftBlockIndex);
}
}
}