use of org.apache.calcite.rex.RexCall in project calcite by apache.
the class ReduceExpressionsRule method pushPredicateIntoCase.
/**
* Pushes predicates into a CASE.
*
* <p>We have a loose definition of 'predicate': any boolean expression will
* do, except CASE. For example '(CASE ...) = 5' or '(CASE ...) IS NULL'.
*/
public static RexCall pushPredicateIntoCase(RexCall call) {
if (call.getType().getSqlTypeName() != SqlTypeName.BOOLEAN) {
return call;
}
switch(call.getKind()) {
case CASE:
case AND:
case OR:
// don't push CASE into CASE!
return call;
case EQUALS:
{
// checks that the EQUALS operands may be splitted and
// doesn't push EQUALS into CASE
List<RexNode> equalsOperands = call.getOperands();
ImmutableBitSet left = RelOptUtil.InputFinder.bits(equalsOperands.get(0));
ImmutableBitSet right = RelOptUtil.InputFinder.bits(equalsOperands.get(1));
if (!left.isEmpty() && !right.isEmpty() && left.intersect(right).isEmpty()) {
return call;
}
}
}
int caseOrdinal = -1;
final List<RexNode> operands = call.getOperands();
for (int i = 0; i < operands.size(); i++) {
RexNode operand = operands.get(i);
switch(operand.getKind()) {
case CASE:
caseOrdinal = i;
}
}
if (caseOrdinal < 0) {
return call;
}
// Convert
// f(CASE WHEN p1 THEN v1 ... END, arg)
// to
// CASE WHEN p1 THEN f(v1, arg) ... END
final RexCall case_ = (RexCall) operands.get(caseOrdinal);
final List<RexNode> nodes = new ArrayList<>();
for (int i = 0; i < case_.getOperands().size(); i++) {
RexNode node = case_.getOperands().get(i);
if (!RexUtil.isCasePredicate(case_, i)) {
node = substitute(call, caseOrdinal, node);
}
nodes.add(node);
}
return case_.clone(call.getType(), nodes);
}
use of org.apache.calcite.rex.RexCall 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.RexCall in project calcite by apache.
the class ExtractOperatorConversion method toDruidExpression.
@Override
public String toDruidExpression(RexNode rexNode, RelDataType rowType, DruidQuery query) {
final RexCall call = (RexCall) rexNode;
final RexLiteral flag = (RexLiteral) call.getOperands().get(0);
final TimeUnitRange calciteUnit = (TimeUnitRange) flag.getValue();
final RexNode arg = call.getOperands().get(1);
final String input = DruidExpressions.toDruidExpression(arg, rowType, query);
if (input == null) {
return null;
}
final String druidUnit = EXTRACT_UNIT_MAP.get(calciteUnit);
if (druidUnit == null) {
return null;
}
return DruidExpressions.applyTimeExtract(input, druidUnit, TimeZone.getTimeZone(query.getConnectionConfig().timeZone()));
}
use of org.apache.calcite.rex.RexCall in project calcite by apache.
the class NaryOperatorConverter method toDruidExpression.
@Nullable
@Override
public String toDruidExpression(RexNode rexNode, RelDataType rowType, DruidQuery druidQuery) {
final RexCall call = (RexCall) rexNode;
final List<String> druidExpressions = DruidExpressions.toDruidExpressions(druidQuery, rowType, call.getOperands());
if (druidExpressions == null) {
return null;
}
return DruidExpressions.nAryOperatorCall(druidOperatorName, druidExpressions);
}
use of org.apache.calcite.rex.RexCall in project drill by axbaretto.
the class DrillRelOptUtil method findOperators.
/**
* Travesal RexNode to find at least one operator in the given collection. Continue search if RexNode has a
* RexInputRef which refers to a RexNode in project expressions.
*
* @param node : RexNode to search
* @param projExprs : the list of project expressions. Empty list means there is No project operator underneath.
* @param operators collection of operators to find
* @return : Return null if there is NONE; return the first appearance of item/flatten RexCall.
*/
public static RexCall findOperators(final RexNode node, final List<RexNode> projExprs, final Collection<String> operators) {
try {
RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {
public Void visitCall(RexCall call) {
if (operators.contains(call.getOperator().getName().toLowerCase())) {
throw new Util.FoundOne(call);
/* throw exception to interrupt tree walk (this is similar to
other utility methods in RexUtil.java */
}
return super.visitCall(call);
}
public Void visitInputRef(RexInputRef inputRef) {
if (projExprs.size() == 0) {
return super.visitInputRef(inputRef);
} else {
final int index = inputRef.getIndex();
RexNode n = projExprs.get(index);
if (n instanceof RexCall) {
RexCall r = (RexCall) n;
if (operators.contains(r.getOperator().getName().toLowerCase())) {
throw new Util.FoundOne(r);
}
}
return super.visitInputRef(inputRef);
}
}
};
node.accept(visitor);
return null;
} catch (Util.FoundOne e) {
Util.swallow(e, null);
return (RexCall) e.getNode();
}
}
Aggregations