use of org.apache.calcite.rex.RexVisitorImpl in project hive by apache.
the class HiveCalciteUtil method checkMaterializable.
/**
* Check if the expression is usable for query materialization, returning the first failing expression.
*/
public static RexCall checkMaterializable(RexNode expr) {
boolean deterministic = true;
RexCall failingCall = null;
if (expr == null) {
return null;
}
RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {
@Override
public Void visitCall(org.apache.calcite.rex.RexCall call) {
// non-deterministic functions as well as runtime constants are not materializable.
if (!call.getOperator().isDeterministic() || call.getOperator().isDynamicFunction()) {
throw new Util.FoundOne(call);
}
return super.visitCall(call);
}
};
try {
expr.accept(visitor);
} catch (Util.FoundOne e) {
failingCall = (RexCall) e.getNode();
}
return failingCall;
}
use of org.apache.calcite.rex.RexVisitorImpl 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();
}
}
use of org.apache.calcite.rex.RexVisitorImpl in project drill by apache.
the class DrillRelMdSelectivity method getScanSelectivityInternal.
private double getScanSelectivityInternal(TableMetadata tableMetadata, RexNode predicate, List<SchemaPath> fieldNames, RexBuilder rexBuilder) {
double sel = 1.0;
if ((predicate == null) || predicate.isAlwaysTrue()) {
return sel;
}
List<RexNode> conjuncts1 = RelOptUtil.conjunctions(predicate);
// a Set that holds range predicates that are combined based on whether they are defined on the same column
Set<RexNode> combinedRangePredicates = new HashSet<>();
// pre-process the conjuncts such that predicates on the same column are grouped together
List<RexNode> conjuncts2 = preprocessRangePredicates(conjuncts1, fieldNames, rexBuilder, combinedRangePredicates);
for (RexNode pred : conjuncts2) {
double orSel = 0;
for (RexNode orPred : RelOptUtil.disjunctions(pred)) {
if (isMultiColumnPredicate(orPred) && !combinedRangePredicates.contains(orPred)) {
Set uniqueRefs = new HashSet<>();
uniqueRefs.add(DrillRelOptUtil.findAllRexInputRefs(orPred));
// If equality predicate involving single column - selectivity is 1.0
if (uniqueRefs.size() == 1) {
try {
RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {
@Override
public Void visitCall(RexCall call) {
if (call.getKind() != SqlKind.EQUALS) {
throw new Util.FoundOne(call);
}
return super.visitCall(call);
}
};
pred.accept(visitor);
orSel += 1.0;
} catch (Util.FoundOne e) {
// CALCITE guess
orSel += RelMdUtil.guessSelectivity(orPred);
}
}
} else if (orPred.isA(SqlKind.EQUALS)) {
orSel += computeEqualsSelectivity(tableMetadata, orPred, fieldNames);
} else if (orPred.isA(RANGE_PREDICATE) || combinedRangePredicates.contains(orPred)) {
orSel += computeRangeSelectivity(tableMetadata, orPred, fieldNames);
} else if (orPred.isA(SqlKind.NOT_EQUALS)) {
orSel += 1.0 - computeEqualsSelectivity(tableMetadata, orPred, fieldNames);
} else if (orPred.isA(SqlKind.LIKE)) {
// LIKE selectivity is 5% more than a similar equality predicate, capped at CALCITE guess
orSel += Math.min(computeEqualsSelectivity(tableMetadata, orPred, fieldNames) + LIKE_PREDICATE_SELECTIVITY, guessSelectivity(orPred));
} else if (orPred.isA(SqlKind.NOT)) {
if (orPred instanceof RexCall) {
// LIKE selectivity is 5% more than a similar equality predicate, capped at CALCITE guess
RexNode childOp = ((RexCall) orPred).getOperands().get(0);
if (childOp.isA(SqlKind.LIKE)) {
orSel += 1.0 - Math.min(computeEqualsSelectivity(tableMetadata, childOp, fieldNames) + LIKE_PREDICATE_SELECTIVITY, guessSelectivity(childOp));
} else {
orSel += 1.0 - guessSelectivity(orPred);
}
}
} else if (orPred.isA(SqlKind.IS_NULL)) {
orSel += 1.0 - computeIsNotNullSelectivity(tableMetadata, orPred, fieldNames);
} else if (orPred.isA(SqlKind.IS_NOT_NULL)) {
orSel += computeIsNotNullSelectivity(tableMetadata, orPred, fieldNames);
} else {
// Use the CALCITE guess.
orSel += guessSelectivity(orPred);
}
}
sel *= orSel;
}
// Cap selectivity if it exceeds 1.0
return (sel > 1.0) ? 1.0 : sel;
}
use of org.apache.calcite.rex.RexVisitorImpl in project drill by apache.
the class DrillRelMdSelectivity method findRexInputRef.
private static RexInputRef findRexInputRef(final RexNode node) {
try {
RexVisitor<Void> visitor = new RexVisitorImpl<Void>(true) {
@Override
public Void visitCall(RexCall call) {
for (RexNode child : call.getOperands()) {
child.accept(this);
}
return super.visitCall(call);
}
@Override
public Void visitInputRef(RexInputRef inputRef) {
throw new Util.FoundOne(inputRef);
}
};
node.accept(visitor);
return null;
} catch (Util.FoundOne e) {
Util.swallow(e, null);
return (RexInputRef) e.getNode();
}
}
use of org.apache.calcite.rex.RexVisitorImpl in project flink by apache.
the class SubQueryDecorrelator method analyzeCorConditions.
private static void analyzeCorConditions(final Set<CorrelationId> variableSet, final RexNode condition, final RexBuilder rexBuilder, final int maxCnfNodeCount, final List<RexNode> corConditions, final List<RexNode> nonCorConditions, final List<RexNode> unsupportedCorConditions) {
// converts the expanded expression to conjunctive normal form,
// like "(a AND b) OR c" will be converted to "(a OR c) AND (b OR c)"
final RexNode cnf = FlinkRexUtil.toCnf(rexBuilder, maxCnfNodeCount, condition);
// converts the cnf condition to a list of AND conditions
final List<RexNode> conjunctions = RelOptUtil.conjunctions(cnf);
// `true` for RexNode is supported correlation condition,
// `false` for RexNode is unsupported correlation condition,
// `null` for RexNode is not a correlation condition.
final RexVisitorImpl<Boolean> visitor = new RexVisitorImpl<Boolean>(true) {
@Override
public Boolean visitFieldAccess(RexFieldAccess fieldAccess) {
final RexNode ref = fieldAccess.getReferenceExpr();
if (ref instanceof RexCorrelVariable) {
return visitCorrelVariable((RexCorrelVariable) ref);
} else {
return super.visitFieldAccess(fieldAccess);
}
}
@Override
public Boolean visitCorrelVariable(RexCorrelVariable correlVariable) {
return variableSet.contains(correlVariable.id);
}
@Override
public Boolean visitSubQuery(RexSubQuery subQuery) {
final List<Boolean> result = new ArrayList<>();
for (RexNode operand : subQuery.operands) {
result.add(operand.accept(this));
}
// in (select t3.d from t3)
if (result.contains(true) || result.contains(false)) {
return false;
} else {
return null;
}
}
@Override
public Boolean visitCall(RexCall call) {
final List<Boolean> result = new ArrayList<>();
for (RexNode operand : call.operands) {
result.add(operand.accept(this));
}
if (result.contains(false)) {
return false;
} else if (result.contains(true)) {
// return call.op.getKind() != SqlKind.OR || !result.contains(null);
return call.op.getKind() != SqlKind.OR;
} else {
return null;
}
}
};
for (RexNode c : conjunctions) {
Boolean r = c.accept(visitor);
if (r == null) {
nonCorConditions.add(c);
} else if (r) {
corConditions.add(c);
} else {
unsupportedCorConditions.add(c);
}
}
}
Aggregations