Source:
<code>public Sequence<Cursor> makeCursors( @Nullable final Filter filter, @Nonnull final Interval interval, @Nonnull final VirtualColumns virtualColumns, @Nonnull final Granularity gran, final boolean descending, @Nullable final QueryMetrics<?> queryMetrics ) { final Set<String> baseColumns = new HashSet<>(); Iterables.addAll(baseColumns, baseAdapter.getAvailableDimensions()); Iterables.addAll(baseColumns, baseAdapter.getAvailableMetrics()); final List<VirtualColumn> preJoinVirtualColumns = new ArrayList<>(); final List<VirtualColumn> postJoinVirtualColumns = new ArrayList<>(); for (VirtualColumn virtualColumn : virtualColumns.getVirtualColumns()) { if (baseColumns.containsAll(virtualColumn.requiredColumns())) { preJoinVirtualColumns.add(virtualColumn); <START> baseColumns.add(virtualColumn.getOutputName()); <END> } else { postJoinVirtualColumns.add(virtualColumn); } } JoinFilterSplit joinFilterSplit = JoinFilterAnalyzer.splitFilter( this, baseColumns, filter, enableFilterPushDown ); preJoinVirtualColumns.addAll(joinFilterSplit.getPushDownVirtualColumns()); final Sequence<Cursor> baseCursorSequence = baseAdapter.makeCursors( joinFilterSplit.getBaseTableFilter().isPresent() ? joinFilterSplit.getBaseTableFilter().get() : null, interval, VirtualColumns.create(preJoinVirtualColumns), gran, descending, queryMetrics ); return Sequences.map( baseCursorSequence, cursor -> { Cursor retVal = cursor; for (JoinableClause clause : clauses) { retVal = HashJoinEngine.makeJoinCursor(retVal, clause); } return PostJoinCursor.wrap( retVal, VirtualColumns.create(postJoinVirtualColumns), joinFilterSplit.getJoinTableFilter().isPresent() ? joinFilterSplit.getJoinTableFilter().get() : null ); } ); }</code><technical_language>missing unit tests for this in HashJoinSegmentStorageAdapterTest</technical_language>

Target:
public Sequence<Cursor> makeCursors( @Nullable final Filter filter, @Nonnull final Interval interval, @Nonnull final VirtualColumns virtualColumns, @Nonnull final Granularity gran, final boolean descending, @Nullable final QueryMetrics<?> queryMetrics ) { final List<VirtualColumn> preJoinVirtualColumns = new ArrayList<>(); final List<VirtualColumn> postJoinVirtualColumns = new ArrayList<>(); final Set<String> baseColumns = determineBaseColumnsWithPreAndPostJoinVirtualColumns( virtualColumns, preJoinVirtualColumns, postJoinVirtualColumns ); JoinFilterSplit joinFilterSplit = JoinFilterAnalyzer.splitFilter( this, baseColumns, filter, enableFilterPushDown ); preJoinVirtualColumns.addAll(joinFilterSplit.getPushDownVirtualColumns()); final Sequence<Cursor> baseCursorSequence = baseAdapter.makeCursors( joinFilterSplit.getBaseTableFilter().isPresent() ? joinFilterSplit.getBaseTableFilter().get() : null, interval, VirtualColumns.create(preJoinVirtualColumns), gran, descending, queryMetrics ); return Sequences.map( baseCursorSequence, cursor -> { Cursor retVal = cursor; for (JoinableClause clause : clauses) { retVal = HashJoinEngine.makeJoinCursor(retVal, clause); } return PostJoinCursor.wrap( retVal, VirtualColumns.create(postJoinVirtualColumns), joinFilterSplit.getJoinTableFilter().isPresent() ? joinFilterSplit.getJoinTableFilter().get() : null ); } ); }