blob: 63e733f99f71d9fb3be73bf195cb461c4bffbceb [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF 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.
package org.apache.impala.planner;
import java.util.ArrayList;
import java.util.List;
import org.apache.impala.analysis.BinaryPredicate;
import org.apache.impala.analysis.Expr;
import org.apache.impala.thrift.TDataSink;
import org.apache.impala.thrift.TDataSinkType;
import org.apache.impala.thrift.TExplainLevel;
import org.apache.impala.thrift.TJoinBuildSink;
import org.apache.impala.thrift.TQueryOptions;
import com.google.common.base.Preconditions;
import static org.apache.impala.analysis.ToSqlOptions.DEFAULT;
/**
* Sink to materialize the build side of a join.
*/
public class JoinBuildSink extends DataSink {
// id of join's build-side table assigned during planning
private final JoinTableId joinTableId_;
// Reference to the join node that consumes the build side.
private final JoinNode joinNode_;
private final List<Expr> buildExprs_ = new ArrayList<>();
/**
* Creates sink for build side of 'joinNode' (extracts buildExprs_ from joinNode).
*/
public JoinBuildSink(JoinTableId joinTableId, JoinNode joinNode) {
Preconditions.checkState(joinTableId.isValid());
joinTableId_ = joinTableId;
joinNode_ = joinNode;
Preconditions.checkNotNull(joinNode);
Preconditions.checkState(joinNode instanceof JoinNode);
if (!(joinNode instanceof HashJoinNode)) return;
for (Expr eqJoinConjunct: joinNode.getEqJoinConjuncts()) {
BinaryPredicate p = (BinaryPredicate) eqJoinConjunct;
// by convention the build exprs are the rhs of the join conjuncts
buildExprs_.add(p.getChild(1).clone());
}
}
public JoinTableId getJoinTableId() { return joinTableId_; }
@Override
protected void toThriftImpl(TDataSink tsink) {
TJoinBuildSink tBuildSink = new TJoinBuildSink();
tBuildSink.setDest_node_id(joinNode_.getId().asInt());
for (Expr buildExpr: buildExprs_) {
tBuildSink.addToBuild_exprs(buildExpr.treeToThrift());
}
tsink.setJoin_build_sink(tBuildSink);
}
@Override
protected TDataSinkType getSinkType() {
return TDataSinkType.JOIN_BUILD_SINK;
}
@Override
public void appendSinkExplainString(String prefix, String detailPrefix,
TQueryOptions queryOptions, TExplainLevel detailLevel, StringBuilder output) {
output.append(String.format("%s%s\n", prefix, "JOIN BUILD"));
if (detailLevel.ordinal() > TExplainLevel.MINIMAL.ordinal()) {
output.append(
detailPrefix + "join-table-id=" + joinTableId_.toString()
+ " plan-id=" + fragment_.getPlanId().toString()
+ " cohort-id=" + fragment_.getCohortId().toString() + "\n");
if (!buildExprs_.isEmpty()) {
output.append(detailPrefix + "build expressions: ")
.append(Expr.toSql(buildExprs_, DEFAULT) + "\n");
}
}
}
@Override
protected String getLabel() {
return "JOIN BUILD";
}
@Override
public void computeResourceProfile(TQueryOptions queryOptions) {
// The memory consumption is counted against the join PlanNode.
resourceProfile_ = ResourceProfile.noReservation(0);
}
@Override
public void collectExprs(List<Expr> exprs) {
exprs.addAll(buildExprs_);
}
}