15 package com.cloudera.impala.planner;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.Comparator;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.ListIterator;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
58 import com.cloudera.impala.common.Pair;
59 import com.google.common.base.Preconditions;
60 import com.google.common.base.Predicate;
61 import com.google.common.collect.Iterables;
62 import com.google.common.collect.Lists;
63 import com.google.common.collect.Sets;
72 private final static Logger
LOG = LoggerFactory.getLogger(SingleNodePlanner.class);
97 QueryStmt queryStmt = ctx_.getQueryStmt();
100 Analyzer analyzer = queryStmt.getAnalyzer();
101 analyzer.computeEquivClasses();
102 analyzer.getTimeline().markEvent(
"Equivalence classes computed");
114 analyzer.materializeSlots(queryStmt.getBaseTblResultExprs());
117 LOG.trace(
"desctbl: " + analyzer.getDescTbl().debugString());
120 Preconditions.checkNotNull(singleNodePlan);
121 return singleNodePlan;
129 ArrayList<TupleId> tupleIds = Lists.newArrayList();
130 stmt.getMaterializedTupleIds(tupleIds);
136 node.setOutputSmap(((SelectStmt) stmt).getBaseTblSmap());
147 if (analyzer.hasEmptyResultSet())
return createEmptyNode(stmt, analyzer);
151 SelectStmt selectStmt = (SelectStmt) stmt;
155 if (((SelectStmt) stmt).getAnalyticInfo() != null) {
156 AnalyticInfo analyticInfo = selectStmt.getAnalyticInfo();
157 ArrayList<TupleId> stmtTupleIds = Lists.newArrayList();
158 stmt.getMaterializedTupleIds(stmtTupleIds);
161 List<Expr> inputPartitionExprs = Lists.newArrayList();
163 root = analyticPlanner.createSingleNodePlan(root,
164 aggInfo != null ? aggInfo.getGroupingExprs() : null, inputPartitionExprs);
165 if (aggInfo != null && !inputPartitionExprs.isEmpty()) {
167 aggInfo.setPartitionExprs(inputPartitionExprs);
171 Preconditions.checkState(stmt instanceof
UnionStmt);
176 boolean sortHasMaterializedSlots =
false;
177 if (stmt.evaluateOrderBy()) {
179 stmt.getSortInfo().getSortTupleDescriptor().getSlots()) {
180 if (sortSlotDesc.isMaterialized()) {
181 sortHasMaterializedSlots =
true;
187 if (stmt.evaluateOrderBy() && sortHasMaterializedSlots) {
188 long limit = stmt.getLimit();
191 boolean useTopN = stmt.hasLimit() && !disableTopN;
193 useTopN, stmt.getOffset());
194 Preconditions.checkState(root.hasValidStats());
195 root.setLimit(limit);
198 root.setLimit(stmt.getLimit());
199 root.computeStats(analyzer);
217 Preconditions.checkNotNull(root);
220 List<Expr> conjuncts = analyzer.getUnassignedConjuncts(root);
222 analyzer.createEquivConjuncts(tid, conjuncts);
224 if (conjuncts.isEmpty())
return root;
228 selectNode.init(analyzer);
229 Preconditions.checkState(selectNode.hasValidStats());
247 Analyzer analyzer, List<Pair<TableRef, PlanNode>> refPlans)
249 LOG.trace(
"createCheapestJoinPlan");
250 if (refPlans.size() == 1)
return refPlans.get(0).second;
254 ArrayList<Pair<TableRef, Long>> candidates = Lists.newArrayList();
255 for (Pair<TableRef, PlanNode> entry: refPlans) {
277 candidates.add(
new Pair(ref,
new Long(0)));
278 LOG.trace(
"candidate " + ref.getUniqueAlias() +
": 0");
281 Preconditions.checkNotNull(ref.getDesc());
282 long materializedSize =
284 candidates.add(
new Pair(ref,
new Long(materializedSize)));
285 LOG.trace(
"candidate " + ref.getUniqueAlias() +
": " + Long.toString(materializedSize));
287 if (candidates.isEmpty())
return null;
291 Collections.sort(candidates,
292 new Comparator<Pair<TableRef, Long>>() {
293 public int compare(Pair<TableRef, Long> a, Pair<TableRef, Long> b) {
294 long diff = b.second - a.second;
295 return (diff < 0 ? -1 : (diff > 0 ? 1 : 0));
299 for (Pair<TableRef, Long> candidate: candidates) {
301 if (result != null)
return result;
312 Analyzer analyzer,
TableRef leftmostRef, List<Pair<TableRef, PlanNode>> refPlans)
315 LOG.trace(
"createJoinPlan: " + leftmostRef.getUniqueAlias());
317 List<Pair<TableRef, PlanNode>> remainingRefs = Lists.newArrayList();
319 for (Pair<TableRef, PlanNode> entry: refPlans) {
320 if (entry.first == leftmostRef) {
323 remainingRefs.add(entry);
326 Preconditions.checkNotNull(root);
329 Set<TableRef> joinedRefs = Sets.newHashSet();
330 joinedRefs.add(leftmostRef);
333 boolean planHasInvertedJoin =
false;
334 if (leftmostRef.
getJoinOp().isOuterJoin()
336 || leftmostRef.
getJoinOp().isCrossJoin()) {
341 leftmostRef.invertJoin(refPlans, analyzer);
342 planHasInvertedJoin =
true;
347 while (!remainingRefs.isEmpty()) {
351 Pair<TableRef, PlanNode> minEntry = null;
352 for (Pair<TableRef, PlanNode> entry: remainingRefs) {
354 LOG.trace(Integer.toString(i) +
" considering ref " + ref.
getUniqueAlias());
364 if (joinOp.isOuterJoin() || joinOp.isSemiJoin()) {
365 List<TupleId> currentTids = Lists.newArrayList(root.getTblRefIds());
366 currentTids.add(ref.getId());
371 List<TupleId> tableRefTupleIds = ref.getAllTupleIds();
372 if (!currentTids.containsAll(tableRefTupleIds) ||
373 !tableRefTupleIds.containsAll(currentTids)) {
378 }
else if (ref.
getJoinOp().isCrossJoin()) {
383 analyzer.setAssignedConjuncts(root.getAssignedConjuncts());
385 boolean invertJoin =
false;
386 if (joinOp.isOuterJoin() || joinOp.isSemiJoin() || joinOp.isCrossJoin()) {
392 long lhsCard = root.getCardinality();
393 long rhsCard = rhsPlan.getCardinality();
394 if (lhsCard != -1 && rhsCard != -1 &&
395 lhsCard * root.getAvgRowSize() < rhsCard * rhsPlan.getAvgRowSize() &&
396 !joinOp.isNullAwareLeftAntiJoin()) {
402 ref.setJoinOp(ref.getJoinOp().invert());
404 planHasInvertedJoin =
true;
408 if (candidate == null)
continue;
409 LOG.trace(
"cardinality=" + Long.toString(candidate.getCardinality()));
413 if (joinOp.isOuterJoin() || joinOp.isSemiJoin()) {
421 || (candidate.getClass().equals(newRoot.getClass())
428 if (newRoot == null) {
436 Preconditions.checkState(!planHasInvertedJoin);
442 long lhsCardinality = root.getCardinality();
443 long rhsCardinality = minEntry.second.getCardinality();
444 numOps += lhsCardinality + rhsCardinality;
445 LOG.debug(Integer.toString(i) +
" chose " + minEntry.first.getUniqueAlias()
446 +
" #lhs=" + Long.toString(lhsCardinality)
447 +
" #rhs=" + Long.toString(rhsCardinality)
448 +
" #ops=" + Long.toString(numOps));
449 remainingRefs.remove(minEntry);
450 joinedRefs.add(minEntry.first);
454 root.setId(ctx_.getNextNodeId());
455 analyzer.setAssignedConjuncts(root.getAssignedConjuncts());
466 Analyzer analyzer, List<Pair<TableRef, PlanNode>> refPlans)
469 Preconditions.checkState(!refPlans.isEmpty());
470 PlanNode root = refPlans.get(0).second;
471 for (
int i = 1; i < refPlans.size(); ++i) {
472 TableRef innerRef = refPlans.get(i).first;
473 PlanNode innerPlan = refPlans.get(i).second;
475 root.setId(ctx_.getNextNodeId());
487 if (selectStmt.getTableRefs().isEmpty()) {
503 selectStmt.materializeRequiredSlots(analyzer);
505 ArrayList<TupleId> rowTuples = Lists.newArrayList();
507 for (
TableRef tblRef: selectStmt.getTableRefs()) {
508 rowTuples.addAll(tblRef.getMaterializedTupleIds());
515 if (analyzer.hasEmptySpjResultSet()) {
517 emptySetNode.init(analyzer);
518 emptySetNode.setOutputSmap(selectStmt.getBaseTblSmap());
525 List<Pair<TableRef, PlanNode>> refPlans = Lists.newArrayList();
526 for (
TableRef ref: selectStmt.getTableRefs()) {
528 Preconditions.checkState(plan != null);
529 refPlans.add(
new Pair(ref, plan));
532 for (Pair<TableRef, PlanNode> entry: refPlans) {
533 entry.second.setAssignedConjuncts(analyzer.getAssignedConjuncts());
537 if (!selectStmt.getSelectList().isStraightJoin()) {
538 Set<ExprId> assignedConjuncts = analyzer.getAssignedConjuncts();
540 if (root == null) analyzer.setAssignedConjuncts(assignedConjuncts);
542 if (selectStmt.getSelectList().isStraightJoin() || root == null) {
546 Preconditions.checkNotNull(root);
550 if (selectStmt.getAggInfo() != null) {
566 Preconditions.checkState(selectStmt.getAggInfo() != null);
571 Preconditions.checkState(root.hasValidStats());
579 aggInfo.getSecondPhaseDistinctAggInfo());
581 Preconditions.checkState(root.hasValidStats());
584 root.assignConjuncts(analyzer);
594 Preconditions.checkState(selectStmt.getTableRefs().isEmpty());
595 ArrayList<Expr> resultExprs = selectStmt.getResultExprs();
596 ArrayList<String> colLabels = selectStmt.getColLabels();
598 TupleDescriptor tupleDesc = analyzer.getDescTbl().createTupleDescriptor(
"union");
599 tupleDesc.setIsMaterialized(
true);
603 unionNode.addConstExprList(Lists.newArrayList(resultExprs));
606 for (
int i = 0; i < resultExprs.size(); ++i) {
608 slotDesc.setLabel(colLabels.get(i));
609 slotDesc.setSourceExpr(resultExprs.get(i));
610 slotDesc.setType(resultExprs.get(i).getType());
611 slotDesc.setStats(ColumnStats.fromExpr(resultExprs.get(i)));
612 slotDesc.setIsMaterialized(
true);
614 resultExprs.set(i, slotRef);
616 tupleDesc.computeMemLayout();
618 unionNode.init(analyzer);
633 ListIterator<Expr> i = conjuncts.listIterator();
635 while (i.hasNext()) {
638 BinaryPredicate comp = (BinaryPredicate) e;
639 if (comp.
getOp() == BinaryPredicate.Operator.NE)
continue;
640 Expr slotBinding = comp.getSlotBinding(d.getId());
641 if (slotBinding == null || !slotBinding.
isConstant() ||
646 if (comp.
getOp() == BinaryPredicate.Operator.EQ) {
648 return ValueRange.createEqRange(slotBinding);
651 if (result == null) result =
new ValueRange();
654 if (comp.
getOp() == BinaryPredicate.Operator.GT
655 || comp.getOp() == BinaryPredicate.
Operator.GE) {
656 if (result.getLowerBound() == null) {
657 result.setLowerBound(slotBinding);
658 result.setLowerBoundInclusive(comp.getOp() == BinaryPredicate.Operator.GE);
662 if (result.getUpperBound() == null) {
663 result.setUpperBound(slotBinding);
664 result.setUpperBoundInclusive(comp.getOp() == BinaryPredicate.Operator.LE);
699 QueryStmt viewStmt = inlineViewRef.getViewStmt();
701 SelectStmt selectStmt = (SelectStmt) viewStmt;
703 if (inlineViewRef.getAnalyzer().hasEmptyResultSet()) {
707 Preconditions.checkState(inlineViewRef.getMaterializedTupleIds().size() == 1);
709 analyzer.getTupleDesc(inlineViewRef.getId()).materializeSlots();
711 inlineViewRef.getMaterializedTupleIds().
get(0));
712 if (analyzer.hasEmptyResultSet())
return unionNode;
713 unionNode.setTblRefIds(Lists.newArrayList(inlineViewRef.getId()));
714 unionNode.addConstExprList(selectStmt.getBaseTblResultExprs());
715 unionNode.init(analyzer);
721 createQueryPlan(inlineViewRef.getViewStmt(), inlineViewRef.getAnalyzer(),
false);
725 rootNode.setTblRefIds(Lists.newArrayList(inlineViewRef.getId()));
728 if (analyzer.isOuterJoined(inlineViewRef.getId())) {
731 List<Expr> nullableRhs = TupleIsNullPredicate.wrapExprs(
732 inlineViewSmap.getRhs(), rootNode.
getTupleIds(), analyzer);
741 rootNode.getOutputSmap(), analyzer);
742 rootNode.setOutputSmap(composedSmap);
754 analyzer, inlineViewRef.getDesc().getId().asList(), rootNode);
771 List<Expr> unassignedConjuncts =
772 analyzer.getUnassignedConjuncts(inlineViewRef.getId().asList(),
true);
776 List<Expr> substUnassigned = Expr.substituteList(unassignedConjuncts,
777 inlineViewRef.getBaseTblSmap(), analyzer,
false);
778 analyzer.materializeSlots(substUnassigned);
782 List<Expr> preds = Lists.newArrayList();
783 for (
Expr e: unassignedConjuncts) {
788 unassignedConjuncts.removeAll(preds);
791 analyzer.createEquivConjuncts(inlineViewRef.getId(), preds);
796 List<Expr> viewPredicates =
797 Expr.substituteList(preds, inlineViewRef.getSmap(), analyzer,
false);
804 public boolean apply(
Expr expr) {
806 || ((BinaryPredicate) expr).getOp() != BinaryPredicate.Operator.EQ) {
810 && expr.getChild(0) instanceof
SlotRef
811 && expr.getChild(1) instanceof
SlotRef
812 && (((
SlotRef) expr.getChild(0)).getSlotId() ==
813 ((
SlotRef) expr.getChild(1)).getSlotId())) {
819 Iterables.removeIf(viewPredicates, isIdentityPredicate);
825 analyzer.markConjunctsAssigned(preds);
826 inlineViewRef.getAnalyzer().registerConjuncts(viewPredicates);
830 List<Expr> substUnassigned = Expr.substituteList(unassignedConjuncts,
831 inlineViewRef.getBaseTblSmap(), analyzer,
false);
832 analyzer.materializeSlots(substUnassigned);
839 return !inlineViewRef.getViewStmt().hasLimit()
840 && !inlineViewRef.getViewStmt().hasOffset()
841 && (!(inlineViewRef.getViewStmt() instanceof
SelectStmt)
842 || !((SelectStmt) inlineViewRef.
getViewStmt()).hasAnalyticInfo());
851 if (tblRef.getTable() instanceof
HdfsTable) {
854 scanNode.init(analyzer);
858 scanNode.init(analyzer);
860 }
else if (tblRef.getTable() instanceof
HBaseTable) {
869 List<Expr> conjuncts = analyzer.getUnassignedConjuncts(scanNode);
872 analyzer.markConjunctsAssigned(conjuncts);
873 List<ValueRange> keyRanges = Lists.newArrayList();
875 for (
int i = 0; i < tblRef.getTable().getNumClusteringCols(); ++i) {
877 tblRef.getDesc(), tblRef.getTable().getColumns().
get(i));
878 if (slotDesc == null || !slotDesc.
getType().isStringType()) {
891 scanNode.addConjuncts(conjuncts);
892 scanNode.init(analyzer);
914 List<BinaryPredicate> joinConjuncts, List<Expr> joinPredicates) {
915 joinConjuncts.clear();
916 joinPredicates.clear();
917 TupleId tblRefId = joinedTblRef.getId();
918 List<TupleId> tblRefIds = tblRefId.asList();
919 List<Expr> candidates = analyzer.getEqJoinConjuncts(planIds, joinedTblRef);
920 if (candidates == null)
return;
922 List<TupleId> joinTupleIds = Lists.newArrayList();
923 joinTupleIds.addAll(planIds);
924 joinTupleIds.add(tblRefId);
925 for (
Expr e: candidates) {
927 if (e.getChild(0).isConstant() || e.getChild(1).isConstant())
continue;
930 if (e.getChild(0).isBoundByTupleIds(tblRefIds)) {
931 rhsExpr = e.getChild(0);
933 Preconditions.checkState(e.getChild(1).isBoundByTupleIds(tblRefIds));
934 rhsExpr = e.getChild(1);
938 if (e.getChild(1).isBoundByTupleIds(planIds)) {
939 lhsExpr = e.getChild(1);
940 }
else if (e.getChild(0).isBoundByTupleIds(planIds)) {
941 lhsExpr = e.getChild(0);
947 Preconditions.checkState(lhsExpr != rhsExpr);
948 joinPredicates.add(e);
951 joinConjunct.analyzeNoThrow(analyzer);
952 joinConjuncts.add(joinConjunct);
954 if (!joinPredicates.isEmpty())
return;
955 Preconditions.checkState(joinConjuncts.isEmpty());
958 List<SlotId> lhsSlotIds = Lists.newArrayList();
960 analyzer.getEquivSlots(slotDesc.getId(), planIds, lhsSlotIds);
961 if (!lhsSlotIds.isEmpty()) {
966 analyzer.createEqPredicate(lhsSlotIds.get(0), slotDesc.getId());
967 joinConjuncts.add(pred);
980 Preconditions.checkState(innerRef != null ^ outerRef != null);
981 TableRef tblRef = (innerRef != null) ? innerRef : outerRef;
983 List<BinaryPredicate> eqJoinConjuncts = Lists.newArrayList();
984 List<Expr> eqJoinPredicates = Lists.newArrayList();
987 if (innerRef != null) {
989 analyzer, outer.getTblRefIds(), innerRef, eqJoinConjuncts, eqJoinPredicates);
991 if (!innerRef.getJoinOp().isOuterJoin()) {
992 analyzer.createEquivConjuncts(outer.getTblRefIds(), innerRef.getId(),
997 analyzer, inner.getTblRefIds(), outerRef, eqJoinConjuncts, eqJoinPredicates);
999 if (!outerRef.getJoinOp().isOuterJoin()) {
1000 analyzer.createEquivConjuncts(inner.getTblRefIds(), outerRef.getId(),
1005 Expr swapTmp = eqJoinConjunct.getChild(0);
1006 eqJoinConjunct.setChild(0, eqJoinConjunct.getChild(1));
1007 eqJoinConjunct.setChild(1, swapTmp);
1012 if (eqJoinConjuncts.isEmpty()) {
1017 if (tblRef.getJoinOp().isOuterJoin() ||
1018 tblRef.getJoinOp().isSemiJoin()) {
1020 String.format(
"%s join with '%s' without equi-join " +
1021 "conjuncts is not supported.",
1022 tblRef.getJoinOp().isOuterJoin() ?
"Outer" :
"Semi",
1023 innerRef.getUniqueAlias()));
1026 result.init(analyzer);
1035 analyzer.markConjunctsAssigned(eqJoinPredicates);
1037 List<Expr> otherJoinConjuncts = Lists.newArrayList();
1038 if (tblRef.getJoinOp().isOuterJoin()) {
1041 otherJoinConjuncts = analyzer.getUnassignedOjConjuncts(tblRef);
1042 }
else if (tblRef.getJoinOp().isSemiJoin()) {
1046 otherJoinConjuncts =
1047 analyzer.getUnassignedConjuncts(tblRef.getAllTupleIds(),
false);
1048 if (tblRef.getJoinOp().isNullAwareLeftAntiJoin()) {
1049 boolean hasNullMatchingEqOperator =
false;
1053 Iterator<BinaryPredicate> it = eqJoinConjuncts.iterator();
1054 while (it.hasNext()) {
1057 otherJoinConjuncts.add(conjunct);
1061 Preconditions.checkState(!hasNullMatchingEqOperator);
1062 hasNullMatchingEqOperator =
true;
1065 Preconditions.checkState(hasNullMatchingEqOperator);
1068 analyzer.markConjunctsAssigned(otherJoinConjuncts);
1071 new HashJoinNode(outer, inner, tblRef, eqJoinConjuncts, otherJoinConjuncts);
1072 result.init(analyzer);
1088 "Unknown TableRef node: " + tblRef.getClass().getSimpleName());
1105 QueryStmt queryStmt = op.getQueryStmt();
1106 if (op.isDropped())
continue;
1108 SelectStmt selectStmt = (SelectStmt) queryStmt;
1110 unionNode.addConstExprList(selectStmt.getBaseTblResultExprs());
1116 unionNode.addChild(opPlan, op.getQueryStmt().getBaseTblResultExprs());
1118 if (unionDistinctPlan != null) {
1119 Preconditions.checkState(unionStmt.hasDistinctOps());
1120 Preconditions.checkState(unionDistinctPlan instanceof
AggregationNode);
1121 unionNode.addChild(unionDistinctPlan,
1122 unionStmt.getDistinctAggInfo().getGroupingExprs());
1124 unionNode.init(analyzer);
1143 List<Expr> conjuncts =
1144 analyzer.getUnassignedConjuncts(unionStmt.getTupleId().asList(),
false);
1145 if (!unionStmt.hasAnalyticExprs()) {
1151 List<Expr> opConjuncts =
1152 Expr.substituteList(conjuncts, op.getSmap(), analyzer,
false);
1153 op.getAnalyzer().registerConjuncts(opConjuncts);
1156 if (op.getAnalyzer().hasEmptyResultSet()) op.drop();
1158 analyzer.markConjunctsAssigned(conjuncts);
1161 analyzer.materializeSlots(conjuncts);
1164 unionStmt.materializeRequiredSlots(analyzer);
1168 if (unionStmt.hasDistinctOps()) {
1170 analyzer, unionStmt, unionStmt.getDistinctOperands(), null);
1173 result.init(analyzer);
1176 if (unionStmt.hasAllOps()) {
1177 result =
createUnionPlan(analyzer, unionStmt, unionStmt.getAllOperands(), result);
1180 if (unionStmt.hasAnalyticExprs()) {
1182 analyzer, unionStmt.getTupleId().asList(), result);
boolean isNullAwareLeftAntiJoin()
PlanNode createJoinPlan(Analyzer analyzer, TableRef leftmostRef, List< Pair< TableRef, PlanNode >> refPlans)
SingleNodePlanner(PlannerContext ctx)
PlanNode createUnionPlan(UnionStmt unionStmt, Analyzer analyzer)
List< TableRef > getTableRefs()
PlanNode createConstantSelectPlan(SelectStmt selectStmt, Analyzer analyzer)
static final ScalarType STRING
boolean canEvalPredicate(List< TupleId > tupleIds, Expr e)
void getHashLookupJoinConjuncts(Analyzer analyzer, List< TupleId > planIds, TableRef joinedTblRef, List< BinaryPredicate > joinConjuncts, List< Expr > joinPredicates)
PlanNode createScanNode(Analyzer analyzer, TableRef tblRef)
PlanNode createQueryPlan(QueryStmt stmt, Analyzer analyzer, boolean disableTopN)
Operator(String description, String name, TComparisonOp thriftOp)
PlanNode createEmptyNode(QueryStmt stmt, Analyzer analyzer)
boolean canMigrateConjuncts(InlineViewRef inlineViewRef)
ArrayList< TupleId > getTupleIds()
ValueRange createHBaseValueRange(SlotDescriptor d, List< Expr > conjuncts)
TQueryOptions getQueryOptions()
PlanNode createAggregationPlan(SelectStmt selectStmt, Analyzer analyzer, PlanNode root)
PlanNode createSelectPlan(SelectStmt selectStmt, Analyzer analyzer)
PlanNode createFromClauseJoinPlan(Analyzer analyzer, List< Pair< TableRef, PlanNode >> refPlans)
UnionNode createUnionPlan(Analyzer analyzer, UnionStmt unionStmt, List< UnionOperand > unionOperands, PlanNode unionDistinctPlan)
PlanNode createSingleNodePlan()
ArrayList< Expr > getBaseTblResultExprs()
PlanNode createInlineViewPlan(Analyzer analyzer, InlineViewRef inlineViewRef)
TupleDescriptor getDesc()
PlanNode createTableRefNode(Analyzer analyzer, TableRef tblRef)
PlanNode addUnassignedConjuncts(Analyzer analyzer, List< TupleId > tupleIds, PlanNode root)
boolean isRegisteredPredicate()
boolean isNullMatchingEq()
PlanNodeId getNextNodeId()
PlanNode createJoinNode(Analyzer analyzer, PlanNode outer, PlanNode inner, TableRef outerRef, TableRef innerRef)
void migrateConjunctsToInlineView(Analyzer analyzer, InlineViewRef inlineViewRef)
PlanNode createCheapestJoinPlan(Analyzer analyzer, List< Pair< TableRef, PlanNode >> refPlans)
final PlannerContext ctx_