/** * Produce a row for the current probe position, if it doesn't match any row on lookup side and this is an outer join. * * @return whether pageBuilder became full */ private boolean outerJoinCurrentPosition() { if (probeOnOuterSide && joinPosition < 0) { pageBuilder.appendNullForBuild(probe); if (tryBuildPage()) { return false; } } return true; }
/** * append the index for the probe and copy the row for the build */ public void appendRow(JoinProbe probe, LookupSource lookupSource, long joinPosition) { // probe side appendProbeIndex(probe); // build side buildPageBuilder.declarePosition(); lookupSource.appendTo(joinPosition, buildPageBuilder, 0); }
JoinProbeFactory joinProbeFactory = new JoinProbeFactory(new int[] {0}, ImmutableList.of(0), OptionalInt.empty()); LookupSource lookupSource = new TestLookupSource(ImmutableList.of(BIGINT), page); LookupJoinPageBuilder lookupJoinPageBuilder = new LookupJoinPageBuilder(ImmutableList.of(BIGINT)); Page output = lookupJoinPageBuilder.build(probe); assertEquals(output.getChannelCount(), 2); assertTrue(output.getBlock(0) instanceof DictionaryBlock); assertEquals(output.getPositionCount(), 0); lookupJoinPageBuilder.reset(); lookupJoinPageBuilder.appendRow(probe, lookupSource, joinPosition); output = lookupJoinPageBuilder.build(probe); assertEquals(output.getChannelCount(), 2); assertTrue(output.getBlock(0) instanceof DictionaryBlock); lookupJoinPageBuilder.reset(); lookupJoinPageBuilder.appendRow(probe, lookupSource, joinPosition); output = lookupJoinPageBuilder.build(probe); assertEquals(output.getChannelCount(), 2); assertFalse(output.getBlock(0) instanceof DictionaryBlock); lookupJoinPageBuilder.reset(); lookupJoinPageBuilder.appendRow(probe, lookupSource, joinPosition); output = lookupJoinPageBuilder.build(probe);
public LookupJoinOperator( OperatorContext operatorContext, List<Type> probeTypes, List<Type> buildOutputTypes, JoinType joinType, LookupSourceFactory lookupSourceFactory, JoinProbeFactory joinProbeFactory, Runnable afterClose, OptionalInt lookupJoinsCount, HashGenerator hashGenerator, PartitioningSpillerFactory partitioningSpillerFactory) { this.operatorContext = requireNonNull(operatorContext, "operatorContext is null"); this.probeTypes = ImmutableList.copyOf(requireNonNull(probeTypes, "probeTypes is null")); requireNonNull(joinType, "joinType is null"); // Cannot use switch case here, because javac will synthesize an inner class and cause IllegalAccessError probeOnOuterSide = joinType == PROBE_OUTER || joinType == FULL_OUTER; this.joinProbeFactory = requireNonNull(joinProbeFactory, "joinProbeFactory is null"); this.afterClose = requireNonNull(afterClose, "afterClose is null"); this.lookupJoinsCount = requireNonNull(lookupJoinsCount, "lookupJoinsCount is null"); this.hashGenerator = requireNonNull(hashGenerator, "hashGenerator is null"); this.lookupSourceFactory = requireNonNull(lookupSourceFactory, "lookupSourceFactory is null"); this.partitioningSpillerFactory = requireNonNull(partitioningSpillerFactory, "partitioningSpillerFactory is null"); this.lookupSourceProviderFuture = lookupSourceFactory.createLookupSourceProvider(); this.statisticsCounter = new JoinStatisticsCounter(joinType); operatorContext.setInfoSupplier(this.statisticsCounter); this.pageBuilder = new LookupJoinPageBuilder(buildOutputTypes); }
/** * Produce rows matching join condition for the current probe position. If this method was called previously * for the current probe position, calling this again will produce rows that wasn't been produced in previous * invocations. * * @return true if all eligible rows have been produced; false otherwise */ private boolean joinCurrentPosition(LookupSource lookupSource, DriverYieldSignal yieldSignal) { // while we have a position on lookup side to join against... while (joinPosition >= 0) { if (lookupSource.isJoinPositionEligible(joinPosition, probe.getPosition(), probe.getPage())) { currentProbePositionProducedRow = true; pageBuilder.appendRow(probe, lookupSource, joinPosition); joinSourcePositions++; } // get next position on lookup side for this probe row joinPosition = lookupSource.getNextJoinPosition(joinPosition, probe.getPosition(), probe.getPage()); if (yieldSignal.isSet() || tryBuildPage()) { return false; } } return true; }
@Override public boolean isFinished() { boolean finished = this.finished && probe == null && pageBuilder.isEmpty() && outputPage == null; // if finished drop references so memory is freed early if (finished) { close(); } return finished; }
private boolean tryBuildPage() { if (pageBuilder.isFull()) { buildPage(); return true; } return false; }
/** * append the index for the probe and append nulls for the build */ public void appendNullForBuild(JoinProbe probe) { // probe side appendProbeIndex(probe); // build side buildPageBuilder.declarePosition(); for (int i = 0; i < buildOutputChannelCount; i++) { buildPageBuilder.getBlockBuilder(i).appendNull(); } }