use of org.apache.calcite.plan.RelOptPredicateList in project hive by apache.
the class HiveRelMdPredicates method getPredicates.
/** Infers predicates for a {@link org.apache.calcite.rel.core.Join}. */
public RelOptPredicateList getPredicates(Join join, RelMetadataQuery mq) {
RexBuilder rB = join.getCluster().getRexBuilder();
RelNode left = join.getInput(0);
RelNode right = join.getInput(1);
final RelOptPredicateList leftInfo = mq.getPulledUpPredicates(left);
final RelOptPredicateList rightInfo = mq.getPulledUpPredicates(right);
JoinConditionBasedPredicateInference jI = new JoinConditionBasedPredicateInference(join, RexUtil.composeConjunction(rB, leftInfo.pulledUpPredicates, false), RexUtil.composeConjunction(rB, rightInfo.pulledUpPredicates, false));
return jI.inferPredicates(false);
}
use of org.apache.calcite.plan.RelOptPredicateList in project hive by apache.
the class HiveRelMdPredicates method getPredicates.
/**
* Infers predicates for a Union.
*/
public RelOptPredicateList getPredicates(Union union, RelMetadataQuery mq) {
RexBuilder rB = union.getCluster().getRexBuilder();
Map<String, RexNode> finalPreds = new HashMap<>();
List<RexNode> finalResidualPreds = new ArrayList<>();
for (int i = 0; i < union.getInputs().size(); i++) {
RelNode input = union.getInputs().get(i);
RelOptPredicateList info = mq.getPulledUpPredicates(input);
if (info.pulledUpPredicates.isEmpty()) {
return RelOptPredicateList.EMPTY;
}
Map<String, RexNode> preds = new HashMap<>();
List<RexNode> residualPreds = new ArrayList<>();
for (RexNode pred : info.pulledUpPredicates) {
final String predString = pred.toString();
if (i == 0) {
preds.put(predString, pred);
continue;
}
if (finalPreds.containsKey(predString)) {
preds.put(predString, pred);
} else {
residualPreds.add(pred);
}
}
// Add new residual preds
finalResidualPreds.add(RexUtil.composeConjunction(rB, residualPreds, false));
// Add those that are not part of the final set to residual
for (Entry<String, RexNode> e : finalPreds.entrySet()) {
if (!preds.containsKey(e.getKey())) {
// This node was in previous union inputs, but it is not in this one
for (int j = 0; j < i; j++) {
finalResidualPreds.set(j, RexUtil.composeConjunction(rB, Lists.newArrayList(finalResidualPreds.get(j), e.getValue()), false));
}
}
}
// Final preds
finalPreds = preds;
}
List<RexNode> preds = new ArrayList<>(finalPreds.values());
RexNode disjPred = RexUtil.composeDisjunction(rB, finalResidualPreds, false);
if (!disjPred.isAlwaysTrue()) {
preds.add(disjPred);
}
return RelOptPredicateList.of(preds);
}
use of org.apache.calcite.plan.RelOptPredicateList in project hive by apache.
the class HiveSortLimitPullUpConstantsRule method onMatch.
@Override
public void onMatch(RelOptRuleCall call) {
final RelNode parent = call.rel(0);
final Sort sort = call.rel(1);
final int count = sort.getInput().getRowType().getFieldCount();
if (count == 1) {
// Project operator.
return;
}
final RexBuilder rexBuilder = sort.getCluster().getRexBuilder();
final RelMetadataQuery mq = RelMetadataQuery.instance();
final RelOptPredicateList predicates = mq.getPulledUpPredicates(sort.getInput());
if (predicates == null) {
return;
}
Map<RexNode, RexNode> conditionsExtracted = HiveReduceExpressionsRule.predicateConstants(RexNode.class, rexBuilder, predicates);
Map<RexNode, RexNode> constants = new HashMap<>();
for (int i = 0; i < count; i++) {
RexNode expr = rexBuilder.makeInputRef(sort.getInput(), i);
if (conditionsExtracted.containsKey(expr)) {
constants.put(expr, conditionsExtracted.get(expr));
}
}
// None of the expressions are constant. Nothing to do.
if (constants.isEmpty()) {
return;
}
if (count == constants.size()) {
// At least a single item in project is required.
constants.remove(constants.keySet().iterator().next());
}
// Create expressions for Project operators before and after the Sort
List<RelDataTypeField> fields = sort.getInput().getRowType().getFieldList();
List<Pair<RexNode, String>> newChildExprs = new ArrayList<>();
List<RexNode> topChildExprs = new ArrayList<>();
List<String> topChildExprsFields = new ArrayList<>();
for (int i = 0; i < count; i++) {
RexNode expr = rexBuilder.makeInputRef(sort.getInput(), i);
RelDataTypeField field = fields.get(i);
if (constants.containsKey(expr)) {
topChildExprs.add(constants.get(expr));
topChildExprsFields.add(field.getName());
} else {
newChildExprs.add(Pair.<RexNode, String>of(expr, field.getName()));
topChildExprs.add(expr);
topChildExprsFields.add(field.getName());
}
}
// Update field collations
final Mappings.TargetMapping mapping = RelOptUtil.permutation(Pair.left(newChildExprs), sort.getInput().getRowType()).inverse();
List<RelFieldCollation> fieldCollations = new ArrayList<>();
for (RelFieldCollation fc : sort.getCollation().getFieldCollations()) {
final int target = mapping.getTargetOpt(fc.getFieldIndex());
if (target < 0) {
// It is a constant, we can ignore it
continue;
}
fieldCollations.add(fc.copy(target));
}
// Update top Project positions
topChildExprs = ImmutableList.copyOf(RexUtil.apply(mapping, topChildExprs));
// Create new Project-Sort-Project sequence
final RelBuilder relBuilder = call.builder();
relBuilder.push(sort.getInput());
relBuilder.project(Pair.left(newChildExprs), Pair.right(newChildExprs));
final ImmutableList<RexNode> sortFields = relBuilder.fields(RelCollations.of(fieldCollations));
relBuilder.sortLimit(sort.offset == null ? -1 : RexLiteral.intValue(sort.offset), sort.fetch == null ? -1 : RexLiteral.intValue(sort.fetch), sortFields);
// Create top Project fixing nullability of fields
relBuilder.project(topChildExprs, topChildExprsFields);
relBuilder.convert(sort.getRowType(), false);
List<RelNode> inputs = new ArrayList<>();
for (RelNode child : parent.getInputs()) {
if (!((HepRelVertex) child).getCurrentRel().equals(sort)) {
inputs.add(child);
} else {
inputs.add(relBuilder.build());
}
}
call.transformTo(parent.copy(parent.getTraitSet(), inputs));
}
use of org.apache.calcite.plan.RelOptPredicateList in project hive by apache.
the class HiveUnionPullUpConstantsRule method onMatch.
@Override
public void onMatch(RelOptRuleCall call) {
final Union union = call.rel(0);
final int count = union.getRowType().getFieldCount();
if (count == 1) {
// Project operator.
return;
}
final RexBuilder rexBuilder = union.getCluster().getRexBuilder();
final RelMetadataQuery mq = RelMetadataQuery.instance();
final RelOptPredicateList predicates = mq.getPulledUpPredicates(union);
if (predicates == null) {
return;
}
Map<RexNode, RexNode> conditionsExtracted = HiveReduceExpressionsRule.predicateConstants(RexNode.class, rexBuilder, predicates);
Map<RexNode, RexNode> constants = new HashMap<>();
for (int i = 0; i < count; i++) {
RexNode expr = rexBuilder.makeInputRef(union, i);
if (conditionsExtracted.containsKey(expr)) {
constants.put(expr, conditionsExtracted.get(expr));
}
}
// None of the expressions are constant. Nothing to do.
if (constants.isEmpty()) {
return;
}
// Create expressions for Project operators before and after the Union
List<RelDataTypeField> fields = union.getRowType().getFieldList();
List<RexNode> topChildExprs = new ArrayList<>();
List<String> topChildExprsFields = new ArrayList<>();
List<RexNode> refs = new ArrayList<>();
ImmutableBitSet.Builder refsIndexBuilder = ImmutableBitSet.builder();
for (int i = 0; i < count; i++) {
RexNode expr = rexBuilder.makeInputRef(union, i);
RelDataTypeField field = fields.get(i);
if (constants.containsKey(expr)) {
topChildExprs.add(constants.get(expr));
topChildExprsFields.add(field.getName());
} else {
topChildExprs.add(expr);
topChildExprsFields.add(field.getName());
refs.add(expr);
refsIndexBuilder.set(i);
}
}
ImmutableBitSet refsIndex = refsIndexBuilder.build();
// Update top Project positions
final Mappings.TargetMapping mapping = RelOptUtil.permutation(refs, union.getInput(0).getRowType()).inverse();
topChildExprs = ImmutableList.copyOf(RexUtil.apply(mapping, topChildExprs));
// Create new Project-Union-Project sequences
final RelBuilder relBuilder = call.builder();
for (int i = 0; i < union.getInputs().size(); i++) {
RelNode input = union.getInput(i);
List<Pair<RexNode, String>> newChildExprs = new ArrayList<>();
for (int j = 0; j < refsIndex.cardinality(); j++) {
int pos = refsIndex.nth(j);
newChildExprs.add(Pair.<RexNode, String>of(rexBuilder.makeInputRef(input, pos), input.getRowType().getFieldList().get(pos).getName()));
}
if (newChildExprs.isEmpty()) {
// At least a single item in project is required.
newChildExprs.add(Pair.<RexNode, String>of(topChildExprs.get(0), topChildExprsFields.get(0)));
}
// Add the input with project on top
relBuilder.push(input);
relBuilder.project(Pair.left(newChildExprs), Pair.right(newChildExprs));
}
relBuilder.union(union.all, union.getInputs().size());
// Create top Project fixing nullability of fields
relBuilder.project(topChildExprs, topChildExprsFields);
relBuilder.convert(union.getRowType(), false);
call.transformTo(relBuilder.build());
}
use of org.apache.calcite.plan.RelOptPredicateList in project hive by apache.
the class HiveRelMdPredicates method getPredicates.
/**
* Infers predicates for a project.
*
* <ol>
* <li>create a mapping from input to projection. Map only positions that
* directly reference an input column.
* <li>Expressions that only contain above columns are retained in the
* Project's pullExpressions list.
* <li>For e.g. expression 'a + e = 9' below will not be pulled up because 'e'
* is not in the projection list.
*
* <pre>
* childPullUpExprs: {a > 7, b + c < 10, a + e = 9}
* projectionExprs: {a, b, c, e / 2}
* projectionPullupExprs: {a > 7, b + c < 10}
* </pre>
*
* </ol>
*/
public RelOptPredicateList getPredicates(Project project, RelMetadataQuery mq) {
RelNode child = project.getInput();
final RexBuilder rexBuilder = project.getCluster().getRexBuilder();
RelOptPredicateList childInfo = mq.getPulledUpPredicates(child);
List<RexNode> projectPullUpPredicates = new ArrayList<RexNode>();
HashMultimap<Integer, Integer> inpIndxToOutIndxMap = HashMultimap.create();
ImmutableBitSet.Builder columnsMappedBuilder = ImmutableBitSet.builder();
Mapping m = Mappings.create(MappingType.PARTIAL_FUNCTION, child.getRowType().getFieldCount(), project.getRowType().getFieldCount());
for (Ord<RexNode> o : Ord.zip(project.getProjects())) {
if (o.e instanceof RexInputRef) {
int sIdx = ((RexInputRef) o.e).getIndex();
m.set(sIdx, o.i);
inpIndxToOutIndxMap.put(sIdx, o.i);
columnsMappedBuilder.set(sIdx);
}
}
// Go over childPullUpPredicates. If a predicate only contains columns in
// 'columnsMapped' construct a new predicate based on mapping.
final ImmutableBitSet columnsMapped = columnsMappedBuilder.build();
for (RexNode r : childInfo.pulledUpPredicates) {
ImmutableBitSet rCols = RelOptUtil.InputFinder.bits(r);
if (columnsMapped.contains(rCols)) {
r = r.accept(new RexPermuteInputsShuttle(m, child));
projectPullUpPredicates.add(r);
}
}
// Project can also generate constants. We need to include them.
for (Ord<RexNode> expr : Ord.zip(project.getProjects())) {
if (RexLiteral.isNullLiteral(expr.e)) {
projectPullUpPredicates.add(rexBuilder.makeCall(SqlStdOperatorTable.IS_NULL, rexBuilder.makeInputRef(project, expr.i)));
} else if (expr.e instanceof RexLiteral) {
final RexLiteral literal = (RexLiteral) expr.e;
projectPullUpPredicates.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, rexBuilder.makeInputRef(project, expr.i), literal));
} else if (expr.e instanceof RexCall && HiveCalciteUtil.isDeterministicFuncOnLiterals(expr.e)) {
//TODO: Move this to calcite
projectPullUpPredicates.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, rexBuilder.makeInputRef(project, expr.i), expr.e));
}
}
return RelOptPredicateList.of(projectPullUpPredicates);
}
Aggregations