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));
}
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);
}
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);
}
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());
}
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);
}
Aggregations