Search in sources :

Example 1 with RelMetadataQuery

use of org.apache.calcite.rel.metadata.RelMetadataQuery 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 = call.getMetadataQuery();
    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));
}
Also used : RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) HepRelVertex(org.apache.calcite.plan.hep.HepRelVertex) RelOptPredicateList(org.apache.calcite.plan.RelOptPredicateList) Sort(org.apache.calcite.rel.core.Sort) RexBuilder(org.apache.calcite.rex.RexBuilder) Pair(org.apache.calcite.util.Pair) RelBuilder(org.apache.calcite.tools.RelBuilder) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) Mappings(org.apache.calcite.util.mapping.Mappings) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) RexNode(org.apache.calcite.rex.RexNode)

Example 2 with RelMetadataQuery

use of org.apache.calcite.rel.metadata.RelMetadataQuery in project calcite by apache.

the class LogicalProject method create.

/**
 * Creates a LogicalProject, specifying row type rather than field names.
 */
public static LogicalProject create(final RelNode input, final List<? extends RexNode> projects, RelDataType rowType) {
    final RelOptCluster cluster = input.getCluster();
    final RelMetadataQuery mq = cluster.getMetadataQuery();
    final RelTraitSet traitSet = cluster.traitSet().replace(Convention.NONE).replaceIfs(RelCollationTraitDef.INSTANCE, new Supplier<List<RelCollation>>() {

        public List<RelCollation> get() {
            return RelMdCollation.project(mq, input, projects);
        }
    });
    return new LogicalProject(cluster, traitSet, input, projects, rowType);
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) List(java.util.List) RelTraitSet(org.apache.calcite.plan.RelTraitSet)

Example 3 with RelMetadataQuery

use of org.apache.calcite.rel.metadata.RelMetadataQuery in project calcite by apache.

the class EnumerableCalc method create.

/**
 * Creates an EnumerableCalc.
 */
public static EnumerableCalc create(final RelNode input, final RexProgram program) {
    final RelOptCluster cluster = input.getCluster();
    final RelMetadataQuery mq = cluster.getMetadataQuery();
    final RelTraitSet traitSet = cluster.traitSet().replace(EnumerableConvention.INSTANCE).replaceIfs(RelCollationTraitDef.INSTANCE, new Supplier<List<RelCollation>>() {

        public List<RelCollation> get() {
            return RelMdCollation.calc(mq, input, program);
        }
    }).replaceIf(RelDistributionTraitDef.INSTANCE, new Supplier<RelDistribution>() {

        public RelDistribution get() {
            return RelMdDistribution.calc(mq, input, program);
        }
    });
    return new EnumerableCalc(cluster, traitSet, input, program);
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) RelCollation(org.apache.calcite.rel.RelCollation) Supplier(com.google.common.base.Supplier) RelTraitSet(org.apache.calcite.plan.RelTraitSet) RelDistribution(org.apache.calcite.rel.RelDistribution)

Example 4 with RelMetadataQuery

use of org.apache.calcite.rel.metadata.RelMetadataQuery in project calcite by apache.

the class EnumerableCalc method implement.

public Result implement(EnumerableRelImplementor implementor, Prefer pref) {
    final JavaTypeFactory typeFactory = implementor.getTypeFactory();
    final BlockBuilder builder = new BlockBuilder();
    final EnumerableRel child = (EnumerableRel) getInput();
    final Result result = implementor.visitChild(this, 0, child, pref);
    final PhysType physType = PhysTypeImpl.of(typeFactory, getRowType(), pref.prefer(result.format));
    // final Enumerable<Employee> inputEnumerable = <<child adapter>>;
    // return new Enumerable<IntString>() {
    // Enumerator<IntString> enumerator() {
    // return new Enumerator<IntString>() {
    // public void reset() {
    // ...
    Type outputJavaType = physType.getJavaRowType();
    final Type enumeratorType = Types.of(Enumerator.class, outputJavaType);
    Type inputJavaType = result.physType.getJavaRowType();
    ParameterExpression inputEnumerator = Expressions.parameter(Types.of(Enumerator.class, inputJavaType), "inputEnumerator");
    Expression input = RexToLixTranslator.convert(Expressions.call(inputEnumerator, BuiltInMethod.ENUMERATOR_CURRENT.method), inputJavaType);
    final RexBuilder rexBuilder = getCluster().getRexBuilder();
    final RelMetadataQuery mq = RelMetadataQuery.instance();
    final RelOptPredicateList predicates = mq.getPulledUpPredicates(child);
    final RexSimplify simplify = new RexSimplify(rexBuilder, predicates, false, RexUtil.EXECUTOR);
    final RexProgram program = this.program.normalize(rexBuilder, simplify);
    BlockStatement moveNextBody;
    if (program.getCondition() == null) {
        moveNextBody = Blocks.toFunctionBlock(Expressions.call(inputEnumerator, BuiltInMethod.ENUMERATOR_MOVE_NEXT.method));
    } else {
        final BlockBuilder builder2 = new BlockBuilder();
        Expression condition = RexToLixTranslator.translateCondition(program, typeFactory, builder2, new RexToLixTranslator.InputGetterImpl(Collections.singletonList(Pair.of(input, result.physType))), implementor.allCorrelateVariables);
        builder2.add(Expressions.ifThen(condition, Expressions.return_(null, Expressions.constant(true))));
        moveNextBody = Expressions.block(Expressions.while_(Expressions.call(inputEnumerator, BuiltInMethod.ENUMERATOR_MOVE_NEXT.method), builder2.toBlock()), Expressions.return_(null, Expressions.constant(false)));
    }
    final BlockBuilder builder3 = new BlockBuilder();
    List<Expression> expressions = RexToLixTranslator.translateProjects(program, typeFactory, builder3, physType, DataContext.ROOT, new RexToLixTranslator.InputGetterImpl(Collections.singletonList(Pair.of(input, result.physType))), implementor.allCorrelateVariables);
    builder3.add(Expressions.return_(null, physType.record(expressions)));
    BlockStatement currentBody = builder3.toBlock();
    final Expression inputEnumerable = builder.append("inputEnumerable", result.block, false);
    final Expression body = Expressions.new_(enumeratorType, NO_EXPRS, Expressions.list(Expressions.fieldDecl(Modifier.PUBLIC | Modifier.FINAL, inputEnumerator, Expressions.call(inputEnumerable, BuiltInMethod.ENUMERABLE_ENUMERATOR.method)), EnumUtils.overridingMethodDecl(BuiltInMethod.ENUMERATOR_RESET.method, NO_PARAMS, Blocks.toFunctionBlock(Expressions.call(inputEnumerator, BuiltInMethod.ENUMERATOR_RESET.method))), EnumUtils.overridingMethodDecl(BuiltInMethod.ENUMERATOR_MOVE_NEXT.method, NO_PARAMS, moveNextBody), EnumUtils.overridingMethodDecl(BuiltInMethod.ENUMERATOR_CLOSE.method, NO_PARAMS, Blocks.toFunctionBlock(Expressions.call(inputEnumerator, BuiltInMethod.ENUMERATOR_CLOSE.method))), Expressions.methodDecl(Modifier.PUBLIC, BRIDGE_METHODS ? Object.class : outputJavaType, "current", NO_PARAMS, currentBody)));
    builder.add(Expressions.return_(null, Expressions.new_(BuiltInMethod.ABSTRACT_ENUMERABLE_CTOR.constructor, // Collections.singletonList(inputRowType),
    NO_EXPRS, ImmutableList.<MemberDeclaration>of(Expressions.methodDecl(Modifier.PUBLIC, enumeratorType, BuiltInMethod.ENUMERABLE_ENUMERATOR.method.getName(), NO_PARAMS, Blocks.toFunctionBlock(body))))));
    return implementor.result(physType, builder.toBlock());
}
Also used : RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) RexProgram(org.apache.calcite.rex.RexProgram) BlockStatement(org.apache.calcite.linq4j.tree.BlockStatement) Type(java.lang.reflect.Type) Enumerator(org.apache.calcite.linq4j.Enumerator) Expression(org.apache.calcite.linq4j.tree.Expression) ParameterExpression(org.apache.calcite.linq4j.tree.ParameterExpression) RexSimplify(org.apache.calcite.rex.RexSimplify) ParameterExpression(org.apache.calcite.linq4j.tree.ParameterExpression) RelOptPredicateList(org.apache.calcite.plan.RelOptPredicateList) JavaTypeFactory(org.apache.calcite.adapter.java.JavaTypeFactory) RexBuilder(org.apache.calcite.rex.RexBuilder) BlockBuilder(org.apache.calcite.linq4j.tree.BlockBuilder)

Example 5 with RelMetadataQuery

use of org.apache.calcite.rel.metadata.RelMetadataQuery in project calcite by apache.

the class EnumerableProject method create.

/**
 * Creates an EnumerableProject, specifying row type rather than field
 * names.
 */
public static EnumerableProject create(final RelNode input, final List<? extends RexNode> projects, RelDataType rowType) {
    final RelOptCluster cluster = input.getCluster();
    final RelMetadataQuery mq = cluster.getMetadataQuery();
    final RelTraitSet traitSet = cluster.traitSet().replace(EnumerableConvention.INSTANCE).replaceIfs(RelCollationTraitDef.INSTANCE, new Supplier<List<RelCollation>>() {

        public List<RelCollation> get() {
            return RelMdCollation.project(mq, input, projects);
        }
    });
    return new EnumerableProject(cluster, traitSet, input, projects, rowType);
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) List(java.util.List) RelTraitSet(org.apache.calcite.plan.RelTraitSet)

Aggregations

RelMetadataQuery (org.apache.calcite.rel.metadata.RelMetadataQuery)135 RelNode (org.apache.calcite.rel.RelNode)94 RexNode (org.apache.calcite.rex.RexNode)46 Test (org.junit.Test)43 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)29 ArrayList (java.util.ArrayList)24 RelOptPredicateList (org.apache.calcite.plan.RelOptPredicateList)24 RexBuilder (org.apache.calcite.rex.RexBuilder)23 RelBuilder (org.apache.calcite.tools.RelBuilder)21 RexTableInputRef (org.apache.calcite.rex.RexTableInputRef)16 ImmutableList (com.google.common.collect.ImmutableList)14 HashMap (java.util.HashMap)13 List (java.util.List)12 RelOptCluster (org.apache.calcite.plan.RelOptCluster)12 RelCollation (org.apache.calcite.rel.RelCollation)12 Aggregate (org.apache.calcite.rel.core.Aggregate)12 RexInputRef (org.apache.calcite.rex.RexInputRef)12 RelTraitSet (org.apache.calcite.plan.RelTraitSet)11 AggregateCall (org.apache.calcite.rel.core.AggregateCall)11 RelDistribution (org.apache.calcite.rel.RelDistribution)10