/** * Converts an expression from {@link SqlNode} to {@link RexNode} format, * mapping identifier references to predefined expressions. * * @param node Expression to translate * @param nameToNodeMap map from String to {@link RexNode}; when an * {@link SqlIdentifier} is encountered, it is used as a * key and translated to the corresponding value from * this map * @return Converted expression */ public RexNode convertExpression( SqlNode node, Map<String, RexNode> nameToNodeMap) { final Map<String, RelDataType> nameToTypeMap = new HashMap<String, RelDataType>(); for (Map.Entry<String, RexNode> entry : nameToNodeMap.entrySet()) { nameToTypeMap.put(entry.getKey(), entry.getValue().getType()); } Blackboard bb = createBlackboard( new ParameterScope((SqlValidatorImpl) validator, nameToTypeMap), nameToNodeMap); return bb.convertExpression(node); }
/** * Converts a WHERE clause. * * @param bb Blackboard * @param where WHERE clause, may be null */ private void convertWhere( final Blackboard bb, final SqlNode where) { if (where == null) { return; } SqlNode newWhere = pushDownNotForIn(where); replaceSubqueries(bb, newWhere, RelOptUtil.Logic.UNKNOWN_AS_FALSE); final RexNode convertedWhere = bb.convertExpression(newWhere); // only allocate filter if the condition is not TRUE if (!convertedWhere.isAlwaysTrue()) { bb.setRoot( RelOptUtil.createFilter(bb.root, convertedWhere), false); } }
List<RexNode> extraLeftExprs, List<RexNode> extraRightExprs) { switch (node.getKind()) { case AND: case OR: fix(extraRightExprs, mid, mid + 1); extraLeftExprs.add(node); return new RexInputRef(mid, node.getType()); case RIGHT: final int index2 = mid + rightCount + extraRightExprs.size(); extraRightExprs.add(node); return new RexInputRef(index2, node.getType()); case BOTH: case EMPTY:
private static boolean containsGet(RexNode node) { try { node.accept( new RexVisitorImpl<Void>(true) { @Override public Void visitCall(RexCall call) { if (call.getOperator() == RexBuilder.GET_OPERATOR) { throw Util.FoundOne.NULL; } return super.visitCall(call); } }); return false; } catch (Util.FoundOne e) { return true; } }
/** * Creates a key for {@link RexNode} which is the same as another key of * another RexNode only if the two have both the same type and textual * representation. For example, "10" integer and "10" bigint result in * different keys. */ public static Pair<String, String> makeKey(RexNode expr) { return Pair.of(expr.toString(), expr.getType().getFullTypeString()); }
/** * Decompose a rex predicate into list of RexNodes that are AND'ed together * * @param rexPredicate predicate to be analyzed * @param rexList list of decomposed RexNodes */ public static void decomposeConjunction( RexNode rexPredicate, List<RexNode> rexList) { if (rexPredicate == null || rexPredicate.isAlwaysTrue()) { return; } if (rexPredicate.isA(RexKind.And)) { for (RexNode operand : ((RexCall) rexPredicate).getOperands()) { decomposeConjunction(operand, rexList); } } else { rexList.add(rexPredicate); } }
public RexNode apply(RexNode input) { return input.isAlwaysTrue() ? rexBuilder.makeLiteral(false) : input.isAlwaysFalse() ? rexBuilder.makeLiteral(true) : input.getKind() == SqlKind.NOT ? ((RexCall) input).operands.get(0) : rexBuilder.makeCall(SqlStdOperatorTable.NOT, input); } };
public boolean isA(SqlKind kind) { return getKind() == kind; }
assert literalExpr.isA(SqlKind.CAST); RexNode child = ((RexCall) literalExpr).getOperands().get(0); assert RexLiteral.isNullLiteral(child);
/** * Decomposes a predicate into a list of expressions that are OR'ed * together. * * @param rexPredicate predicate to be analyzed * @param rexList list of decomposed RexNodes */ public static void decomposeDisjunction( RexNode rexPredicate, List<RexNode> rexList) { if (rexPredicate == null || rexPredicate.isAlwaysFalse()) { return; } if (rexPredicate.isA(SqlKind.OR)) { for (RexNode operand : ((RexCall) rexPredicate).getOperands()) { decomposeDisjunction(operand, rexList); } } else { rexList.add(rexPredicate); } }
/** * Shifts every {@link RexInputRef} in an expression by {@code offset}. */ public static RexNode shift(RexNode node, final int offset) { return node.accept( new RexShuttle() { @Override public RexNode visitInputRef(RexInputRef input) { return new RexInputRef(input.getIndex() + offset, input.getType()); } }); }
/** * Creates a key for {@link RexNode} which is the same as another key of * another RexNode only if the two have both the same type and textual * representation. For example, "10" integer and "10" bigint result in * different keys. */ public static String makeKey(RexNode expr) { String type = expr.getType().getFullTypeString(); String separator = ";"; String node = expr.toString(); StringBuilder keyBuilder = new StringBuilder( type.length() + separator.length() + node.length()); keyBuilder.append(type).append(separator).append(node); return keyBuilder.toString(); }
/** * Decomposes a predicate into a list of expressions that are AND'ed * together. * * @param rexPredicate predicate to be analyzed * @param rexList list of decomposed RexNodes */ public static void decomposeConjunction( RexNode rexPredicate, List<RexNode> rexList) { if (rexPredicate == null || rexPredicate.isAlwaysTrue()) { return; } if (rexPredicate.isA(SqlKind.AND)) { for (RexNode operand : ((RexCall) rexPredicate).getOperands()) { decomposeConjunction(operand, rexList); } } else { rexList.add(rexPredicate); } }
public boolean canExpand(RexCall call) { return call.isA(RexKind.Reinterpret) && call.operands.get(0).isA(RexKind.Reinterpret); }
private int lookupOrCreateGroupExpr(RexNode expr) { for (int i = 0; i < convertedInputExprs.size(); i++) { RexNode convertedInputExpr = convertedInputExprs.get(i); if (expr.toString().equals(convertedInputExpr.toString())) { return i; } } // not found -- add it int index = convertedInputExprs.size(); addExpr(expr, null); return index; }
public void addGroupExpr(SqlNode expr) { RexNode convExpr = bb.convertExpression(expr); final RexNode rex = lookupGroupExpr(expr); if (rex != null) { return; // don't add duplicates, in e.g. "GROUP BY x, y, x" } groupExprs.add(expr); String name = nameMap.get(expr.toString()); addExpr(convExpr, name); final RelDataType type = convExpr.getType(); inputRefs.add(rexBuilder.makeInputRef(type, inputRefs.size())); }
/** * Returns a guess for the selectivity of an expression. * * @param exp expression of interest, or null for none (implying a * selectivity of 1.0) * @return guessed selectivity */ public static double getSelectivity(RexNode exp) { if ((exp == null) || exp.isAlwaysTrue()) { return 1d; } return 0.1d; }
/** * Returns the highest level of any of the inputs of an expression. */ public int maxInputFor(RexNode expr) { level = 0; expr.accept(this); return level; } }