use of org.apache.calcite.rex.RexCallBinding in project calcite by apache.
the class StandardConvertletTable method convertAggregateFunction.
public RexNode convertAggregateFunction(SqlRexContext cx, SqlAggFunction fun, SqlCall call) {
final List<SqlNode> operands = call.getOperandList();
final List<RexNode> exprs;
if (call.isCountStar()) {
exprs = ImmutableList.of();
} else {
exprs = convertExpressionList(cx, operands, SqlOperandTypeChecker.Consistency.NONE);
}
RelDataType returnType = cx.getValidator().getValidatedNodeTypeIfKnown(call);
final int groupCount = cx.getGroupCount();
if (returnType == null) {
RexCallBinding binding = new RexCallBinding(cx.getTypeFactory(), fun, exprs, ImmutableList.<RelCollation>of()) {
@Override
public int getGroupCount() {
return groupCount;
}
};
returnType = fun.inferReturnType(binding);
}
return cx.getRexBuilder().makeCall(returnType, fun, exprs);
}
use of org.apache.calcite.rex.RexCallBinding in project calcite by apache.
the class SortProjectTransposeRule method onMatch.
// ~ Methods ----------------------------------------------------------------
public void onMatch(RelOptRuleCall call) {
final Sort sort = call.rel(0);
final Project project = call.rel(1);
final RelOptCluster cluster = project.getCluster();
if (sort.getConvention() != project.getConvention()) {
return;
}
// Determine mapping between project input and output fields. If sort
// relies on non-trivial expressions, we can't push.
final Mappings.TargetMapping map = RelOptUtil.permutationIgnoreCast(project.getProjects(), project.getInput().getRowType());
for (RelFieldCollation fc : sort.getCollation().getFieldCollations()) {
if (map.getTargetOpt(fc.getFieldIndex()) < 0) {
return;
}
final RexNode node = project.getProjects().get(fc.getFieldIndex());
if (node.isA(SqlKind.CAST)) {
// Check whether it is a monotonic preserving cast, otherwise we cannot push
final RexCall cast = (RexCall) node;
final RexCallBinding binding = RexCallBinding.create(cluster.getTypeFactory(), cast, ImmutableList.of(RelCollations.of(RexUtil.apply(map, fc))));
if (cast.getOperator().getMonotonicity(binding) == SqlMonotonicity.NOT_MONOTONIC) {
return;
}
}
}
final RelCollation newCollation = cluster.traitSet().canonize(RexUtil.apply(map, sort.getCollation()));
final Sort newSort = sort.copy(sort.getTraitSet().replace(newCollation), project.getInput(), newCollation, sort.offset, sort.fetch);
RelNode newProject = project.copy(sort.getTraitSet(), ImmutableList.<RelNode>of(newSort));
// Not only is newProject equivalent to sort;
// newSort is equivalent to project's input
// (but only if the sort is not also applying an offset/limit).
Map<RelNode, RelNode> equiv;
if (sort.offset == null && sort.fetch == null && cluster.getPlanner().getRelTraitDefs().contains(RelCollationTraitDef.INSTANCE)) {
equiv = ImmutableMap.of((RelNode) newSort, project.getInput());
} else {
equiv = ImmutableMap.of();
}
call.transformTo(newProject, equiv);
}
use of org.apache.calcite.rex.RexCallBinding in project flink by apache.
the class FlinkRelMdCollation method project.
/**
* Helper method to determine a {@link Project}'s collation.
*/
public static List<RelCollation> project(RelMetadataQuery mq, RelNode input, List<? extends RexNode> projects) {
final SortedSet<RelCollation> collations = new TreeSet<>();
final List<RelCollation> inputCollations = mq.collations(input);
if (inputCollations == null || inputCollations.isEmpty()) {
return com.google.common.collect.ImmutableList.of();
}
final com.google.common.collect.Multimap<Integer, Integer> targets = com.google.common.collect.LinkedListMultimap.create();
final Map<Integer, SqlMonotonicity> targetsWithMonotonicity = new HashMap<>();
for (Ord<RexNode> project : Ord.<RexNode>zip(projects)) {
if (project.e instanceof RexInputRef) {
targets.put(((RexInputRef) project.e).getIndex(), project.i);
} else if (project.e instanceof RexCall) {
final RexCall call = (RexCall) project.e;
final RexCallBinding binding = RexCallBinding.create(input.getCluster().getTypeFactory(), call, inputCollations);
targetsWithMonotonicity.put(project.i, call.getOperator().getMonotonicity(binding));
}
}
final List<RelFieldCollation> fieldCollations = new ArrayList<>();
loop: for (RelCollation ic : inputCollations) {
if (ic.getFieldCollations().isEmpty()) {
continue;
}
fieldCollations.clear();
for (RelFieldCollation ifc : ic.getFieldCollations()) {
final Collection<Integer> integers = targets.get(ifc.getFieldIndex());
if (integers.isEmpty()) {
// cannot do this collation
continue loop;
}
fieldCollations.add(ifc.withFieldIndex(integers.iterator().next()));
}
assert !fieldCollations.isEmpty();
collations.add(RelCollations.of(fieldCollations));
}
final List<RelFieldCollation> fieldCollationsForRexCalls = new ArrayList<>();
for (Map.Entry<Integer, SqlMonotonicity> entry : targetsWithMonotonicity.entrySet()) {
final SqlMonotonicity value = entry.getValue();
switch(value) {
case NOT_MONOTONIC:
case CONSTANT:
break;
default:
fieldCollationsForRexCalls.add(new RelFieldCollation(entry.getKey(), RelFieldCollation.Direction.of(value)));
break;
}
}
if (!fieldCollationsForRexCalls.isEmpty()) {
collations.add(RelCollations.of(fieldCollationsForRexCalls));
}
return com.google.common.collect.ImmutableList.copyOf(collations);
}
use of org.apache.calcite.rex.RexCallBinding in project hive by apache.
the class HiveRelOptUtil method getNewRelFieldCollations.
/**
* Map Sort and SortExchange keys to the specified Project columns.
* @param project the Project
* @param sortCollation current collation in Sort
* @param cluster RelOptCluster
* @return new collation should be used in the Sort
*/
public static List<RelFieldCollation> getNewRelFieldCollations(HiveProject project, RelCollation sortCollation, RelOptCluster cluster) {
// Determine mapping between project input and output fields.
// In Hive, Sort is always based on RexInputRef
// HiveSort*PullUpConstantsRule should remove constants (RexLiteral)
// We only need to check if project can contain all the positions that sortCollation needs.
final Mappings.TargetMapping map = RelOptUtil.permutationIgnoreCast(project.getProjects(), project.getInput().getRowType()).inverse();
Set<Integer> needed = new HashSet<>();
for (RelFieldCollation fc : sortCollation.getFieldCollations()) {
needed.add(fc.getFieldIndex());
final RexNode node = project.getProjects().get(map.getTarget(fc.getFieldIndex()));
if (node.isA(SqlKind.CAST)) {
// Check whether it is a monotonic preserving cast, otherwise we cannot push
final RexCall cast = (RexCall) node;
final RexCallBinding binding = RexCallBinding.create(cluster.getTypeFactory(), cast, ImmutableList.of(RexUtil.apply(map, sortCollation)));
if (cast.getOperator().getMonotonicity(binding) == SqlMonotonicity.NOT_MONOTONIC) {
return null;
}
}
}
Map<Integer, Integer> m = new HashMap<>();
for (int projPos = 0; projPos < project.getProjects().size(); projPos++) {
RexNode expr = project.getProjects().get(projPos);
if (expr instanceof RexInputRef) {
Set<Integer> positions = HiveCalciteUtil.getInputRefs(expr);
if (positions.size() <= 1) {
int parentPos = positions.iterator().next();
if (needed.contains(parentPos)) {
m.put(parentPos, projPos);
needed.remove(parentPos);
}
}
}
}
if (!needed.isEmpty()) {
return null;
}
List<RelFieldCollation> fieldCollations = new ArrayList<>();
for (RelFieldCollation fc : sortCollation.getFieldCollations()) {
fieldCollations.add(new RelFieldCollation(m.get(fc.getFieldIndex()), fc.direction, fc.nullDirection));
}
return fieldCollations;
}
use of org.apache.calcite.rex.RexCallBinding in project calcite by apache.
the class RelMdCollation method project.
/**
* Helper method to determine a {@link Project}'s collation.
*/
public static List<RelCollation> project(RelMetadataQuery mq, RelNode input, List<? extends RexNode> projects) {
final SortedSet<RelCollation> collations = new TreeSet<>();
final List<RelCollation> inputCollations = mq.collations(input);
if (inputCollations == null || inputCollations.isEmpty()) {
return ImmutableList.of();
}
final Multimap<Integer, Integer> targets = LinkedListMultimap.create();
final Map<Integer, SqlMonotonicity> targetsWithMonotonicity = new HashMap<>();
for (Ord<RexNode> project : Ord.<RexNode>zip(projects)) {
if (project.e instanceof RexInputRef) {
targets.put(((RexInputRef) project.e).getIndex(), project.i);
} else if (project.e instanceof RexCall) {
final RexCall call = (RexCall) project.e;
final RexCallBinding binding = RexCallBinding.create(input.getCluster().getTypeFactory(), call, inputCollations);
targetsWithMonotonicity.put(project.i, call.getOperator().getMonotonicity(binding));
}
}
final List<RelFieldCollation> fieldCollations = new ArrayList<>();
loop: for (RelCollation ic : inputCollations) {
if (ic.getFieldCollations().isEmpty()) {
continue;
}
fieldCollations.clear();
for (RelFieldCollation ifc : ic.getFieldCollations()) {
final Collection<Integer> integers = targets.get(ifc.getFieldIndex());
if (integers.isEmpty()) {
// cannot do this collation
continue loop;
}
fieldCollations.add(ifc.copy(integers.iterator().next()));
}
assert !fieldCollations.isEmpty();
collations.add(RelCollations.of(fieldCollations));
}
final List<RelFieldCollation> fieldCollationsForRexCalls = new ArrayList<>();
for (Map.Entry<Integer, SqlMonotonicity> entry : targetsWithMonotonicity.entrySet()) {
final SqlMonotonicity value = entry.getValue();
switch(value) {
case NOT_MONOTONIC:
case CONSTANT:
break;
default:
fieldCollationsForRexCalls.add(new RelFieldCollation(entry.getKey(), RelFieldCollation.Direction.of(value)));
break;
}
}
if (!fieldCollationsForRexCalls.isEmpty()) {
collations.add(RelCollations.of(fieldCollationsForRexCalls));
}
return ImmutableList.copyOf(collations);
}
Aggregations