private static boolean isThreeArgCase(final RexNode rexNode) { return rexNode.getKind() == SqlKind.CASE && ((RexCall) rexNode).getOperands().size() == 3; } }
public static boolean isConstant(RexNode rexNode) { if (rexNode instanceof RexLiteral) { return true; } if (rexNode instanceof RexCall && SqlKind.CAST.equals(rexNode.getKind()) && ((RexCall) rexNode).getOperands().get(0) instanceof RexLiteral) { return true; } return false; } }
private static void populateEquivalences(Map<Integer, BitSet> equivalence, RexNode predicate) { switch (predicate.getKind()) { case EQUALS: RexCall call = (RexCall) predicate; final List<RexNode> operands = call.getOperands(); if (operands.get(0) instanceof RexInputRef) { final RexInputRef ref0 = (RexInputRef) operands.get(0); if (operands.get(1) instanceof RexInputRef) { final RexInputRef ref1 = (RexInputRef) operands.get(1); populateEquivalence(equivalence, ref0.getIndex(), ref1.getIndex()); populateEquivalence(equivalence, ref1.getIndex(), ref0.getIndex()); } } } }
private static void populateEquivalences(Map<Integer, BitSet> equivalence, RexNode predicate) { switch (predicate.getKind()) { case EQUALS: RexCall call = (RexCall) predicate; final List<RexNode> operands = call.getOperands(); if (operands.get(0) instanceof RexInputRef) { final RexInputRef ref0 = (RexInputRef) operands.get(0); if (operands.get(1) instanceof RexInputRef) { final RexInputRef ref1 = (RexInputRef) operands.get(1); populateEquivalence(equivalence, ref0.getIndex(), ref1.getIndex()); populateEquivalence(equivalence, ref1.getIndex(), ref0.getIndex()); } } } }
private List<RexNode> extractFilterPreds(Filter filterOp) { List<RexNode> conjs = new ArrayList<>(); for (RexNode r : HiveRelOptUtil.conjunctions(filterOp.getCondition())) { if (r.getKind() == SqlKind.IS_NOT_NULL) { RexCall isNotNullNode = (RexCall) r; if (RexUtil.isReferenceOrAccess(isNotNullNode.getOperands().get(0), true)) { ImmutableBitSet ref = RelOptUtil.InputFinder.bits(isNotNullNode); RelColumnOrigin co = mq.getColumnOrigin(filterOp, ref.nextSetBit(0)); if (co == null) { // We add it back conjs.add(r); continue; } RelOptHiveTable table = (RelOptHiveTable) co.getOriginTable(); List<ColStatistics> colStats = table.getColStat(ImmutableList.of(co.getOriginColumnOrdinal()), true); if (colStats == null || colStats.isEmpty() || colStats.get(0).getNumNulls() != 0) { // We add it back conjs.add(r); } } } else { conjs.add(r); } } return conjs; }
/** Finds a {@link RexInputRef} that is equivalent to a {@link CorRef}, * and if found, throws a {@link Util.FoundOne}. */ private void findCorrelationEquivalent(CorRef correlation, RexNode e) throws Util.FoundOne { switch (e.getKind()) { case EQUALS: final RexCall call = (RexCall) e; final List<RexNode> operands = call.getOperands(); if (references(operands.get(0), correlation) && operands.get(1) instanceof RexInputRef) { throw new Util.FoundOne(((RexInputRef) operands.get(1)).getIndex()); } if (references(operands.get(1), correlation) && operands.get(0) instanceof RexInputRef) { throw new Util.FoundOne(((RexInputRef) operands.get(0)).getIndex()); } break; case AND: for (RexNode operand : ((RexCall) e).getOperands()) { findCorrelationEquivalent(correlation, operand); } } }
/** Infers the alias of an expression. * * <p>If the expression was created by {@link #alias}, replaces the expression * in the project list. */ private String inferAlias(List<RexNode> exprList, RexNode expr) { switch (expr.getKind()) { case INPUT_REF: final RexInputRef ref = (RexInputRef) expr; return peek(0).getRowType().getFieldNames().get(ref.getIndex()); case CAST: return inferAlias(exprList, ((RexCall) expr).getOperands().get(0)); case AS: final RexCall call = (RexCall) expr; for (;;) { final int i = exprList.indexOf(expr); if (i < 0) { break; } exprList.set(i, call.getOperands().get(0)); } return ((NlsString) ((RexLiteral) call.getOperands().get(1)).getValue()) .getValue(); default: return null; } }
final SqlKind kind = expression.getKind();
private static RelFieldCollation collation(RexNode node, RelFieldCollation.Direction direction, RelFieldCollation.NullDirection nullDirection, List<RexNode> extraNodes) { switch (node.getKind()) { case INPUT_REF: return new RelFieldCollation(((RexInputRef) node).getIndex(), direction, Util.first(nullDirection, direction.defaultNullDirection())); case DESCENDING: return collation(((RexCall) node).getOperands().get(0), RelFieldCollation.Direction.DESCENDING, nullDirection, extraNodes); case NULLS_FIRST: return collation(((RexCall) node).getOperands().get(0), direction, RelFieldCollation.NullDirection.FIRST, extraNodes); case NULLS_LAST: return collation(((RexCall) node).getOperands().get(0), direction, RelFieldCollation.NullDirection.LAST, extraNodes); default: final int fieldIndex = extraNodes.size(); extraNodes.add(node); return new RelFieldCollation(fieldIndex, direction, Util.first(nullDirection, direction.defaultNullDirection())); } }
/** * Translates "literal" (a TIMESTAMP or DATE literal) to milliseconds since the epoch using the provided * session time zone. * * @param literal TIMESTAMP or DATE literal * @param timeZone session time zone * * @return milliseconds time */ public static DateTime calciteDateTimeLiteralToJoda(final RexNode literal, final DateTimeZone timeZone) { final SqlTypeName typeName = literal.getType().getSqlTypeName(); if (literal.getKind() != SqlKind.LITERAL || (typeName != SqlTypeName.TIMESTAMP && typeName != SqlTypeName.DATE)) { throw new IAE("Expected literal but got[%s]", literal.getKind()); } if (typeName == SqlTypeName.TIMESTAMP) { final TimestampString timestampString = (TimestampString) RexLiteral.value(literal); return CALCITE_TIMESTAMP_PARSER.parse(timestampString.toString()).withZoneRetainFields(timeZone); } else if (typeName == SqlTypeName.DATE) { final DateString dateString = (DateString) RexLiteral.value(literal); return CALCITE_DATE_PARSER.parse(dateString.toString()).withZoneRetainFields(timeZone); } else { throw new IAE("Expected TIMESTAMP or DATE but got[%s]", typeName); } }
private static RelFieldCollation collation(RexNode node, RelFieldCollation.Direction direction, RelFieldCollation.NullDirection nullDirection, List<RexNode> extraNodes) { switch (node.getKind()) { case INPUT_REF: return new RelFieldCollation(((RexInputRef) node).getIndex(), direction, Util.first(nullDirection, direction.defaultNullDirection())); case DESCENDING: return collation(((RexCall) node).getOperands().get(0), RelFieldCollation.Direction.DESCENDING, nullDirection, extraNodes); case NULLS_FIRST: return collation(((RexCall) node).getOperands().get(0), direction, RelFieldCollation.NullDirection.FIRST, extraNodes); case NULLS_LAST: return collation(((RexCall) node).getOperands().get(0), direction, RelFieldCollation.NullDirection.LAST, extraNodes); default: final int fieldIndex = extraNodes.size(); extraNodes.add(node); return new RelFieldCollation(fieldIndex, direction, Util.first(nullDirection, direction.defaultNullDirection())); } }
private static void replaceEmptyGroupAggr(final RelNode rel, RelNode parent) { // If this function is called, the parent should only include constant List<RexNode> exps = parent.getChildExps(); for (RexNode rexNode : exps) { if (!rexNode.accept(new HiveCalciteUtil.ConstantFinder())) { throw new RuntimeException("We expect " + parent.toString() + " to contain only constants. However, " + rexNode.toString() + " is " + rexNode.getKind()); } } HiveAggregate oldAggRel = (HiveAggregate) rel; RelDataTypeFactory typeFactory = oldAggRel.getCluster().getTypeFactory(); RelDataType longType = TypeConverter.convert(TypeInfoFactory.longTypeInfo, typeFactory); RelDataType intType = TypeConverter.convert(TypeInfoFactory.intTypeInfo, typeFactory); // Create the dummy aggregation. SqlAggFunction countFn = SqlFunctionConverter.getCalciteAggFn("count", false, ImmutableList.of(intType), longType); // TODO: Using 0 might be wrong; might need to walk down to find the // proper index of a dummy. List<Integer> argList = ImmutableList.of(0); AggregateCall dummyCall = new AggregateCall(countFn, false, argList, longType, null); Aggregate newAggRel = oldAggRel.copy(oldAggRel.getTraitSet(), oldAggRel.getInput(), oldAggRel.indicator, oldAggRel.getGroupSet(), oldAggRel.getGroupSets(), ImmutableList.of(dummyCall)); RelNode select = introduceDerivedTable(newAggRel); parent.replaceInput(0, select); } }
private boolean references(RexNode e, CorRef correlation) { switch (e.getKind()) { case CAST: final RexNode operand = ((RexCall) e).getOperands().get(0); if (isWidening(e.getType(), operand.getType())) { return references(operand, correlation); } return false; case FIELD_ACCESS: final RexFieldAccess f = (RexFieldAccess) e; if (f.getField().getIndex() == correlation.field && f.getReferenceExpr() instanceof RexCorrelVariable) { if (((RexCorrelVariable) f.getReferenceExpr()).id == correlation.corr) { return true; } } // fall through default: return false; } }
private boolean references(RexNode e, CorRef correlation) { switch (e.getKind()) { case CAST: final RexNode operand = ((RexCall) e).getOperands().get(0); if (isWidening(e.getType(), operand.getType())) { return references(operand, correlation); } return false; case FIELD_ACCESS: final RexFieldAccess f = (RexFieldAccess) e; if (f.getField().getIndex() == correlation.field && f.getReferenceExpr() instanceof RexCorrelVariable) { if (((RexCorrelVariable) f.getReferenceExpr()).id == correlation.corr) { return true; } } // fall through default: return false; } }
final SqlKind kind = rexNode.getKind(); final SqlTypeName sqlTypeName = rexNode.getType().getSqlTypeName();
@Test public void testIsNull_one() { // @formatter:off final RelNode basePlan = builder .scan("t") .filter( builder.call(SqlStdOperatorTable.IS_NULL, builder.field("_str") ) ) .build(); // @formatter:on statObj.setNumNulls(1); planner.setRoot(basePlan); System.out.println(RelOptUtil.toString(basePlan)); RelNode optimizedRelNode = planner.findBestExp(); System.out.println(RelOptUtil.toString(optimizedRelNode)); assertNotEquals("should not be a literal", SqlKind.LITERAL, optimizedRelNode.getChildExps().get(0).getKind()); }
@Test public void testIsNull_all() { // @formatter:off final RelNode basePlan = builder .scan("t") .filter( builder.call(SqlStdOperatorTable.IS_NULL, builder.field("_str") ) ) .build(); // @formatter:on statObj.setNumNulls(3); planner.setRoot(basePlan); System.out.println(RelOptUtil.toString(basePlan)); RelNode optimizedRelNode = planner.findBestExp(); System.out.println(RelOptUtil.toString(optimizedRelNode)); assertEquals("missing literal", SqlKind.LITERAL, optimizedRelNode.getChildExps().get(0).getKind()); RexLiteral val = (RexLiteral) optimizedRelNode.getChildExps().get(0); assertEquals(true, val.getValue()); }
@Test public void testIsNotNull() { // @formatter:off final RelNode basePlan = builder .scan("t") .filter( builder.call(SqlStdOperatorTable.IS_NOT_NULL, builder.field("_str") ) ) .build(); // @formatter:on statObj.setNumNulls(0); planner.setRoot(basePlan); System.out.println(RelOptUtil.toString(basePlan)); RelNode optimizedRelNode = planner.findBestExp(); System.out.println(RelOptUtil.toString(optimizedRelNode)); assertEquals("missing literal", SqlKind.LITERAL, optimizedRelNode.getChildExps().get(0).getKind()); RexLiteral val = (RexLiteral) optimizedRelNode.getChildExps().get(0); assertEquals(true, val.getValue()); }
@Test public void testIsNull_zero() { // @formatter:off final RelNode basePlan = builder .scan("t") .filter( builder.call(SqlStdOperatorTable.IS_NULL, builder.field("_str") ) ) .build(); // @formatter:on statObj.setNumNulls(0); planner.setRoot(basePlan); System.out.println(RelOptUtil.toString(basePlan)); RelNode optimizedRelNode = planner.findBestExp(); System.out.println(RelOptUtil.toString(optimizedRelNode)); assertEquals("missing literal", SqlKind.LITERAL, optimizedRelNode.getChildExps().get(0).getKind()); RexLiteral val = (RexLiteral) optimizedRelNode.getChildExps().get(0); assertEquals(false, val.getValue()); }
@Test public void testGreaterThan_Below() { // @formatter:off final RelNode basePlan = builder .scan("t") .filter( builder.call(SqlStdOperatorTable.GREATER_THAN, builder.field("_int"), builder.literal(0) ) ) .build(); // @formatter:on statObj.setRange(100, 200); planner.setRoot(basePlan); RelNode optimizedRelNode = planner.findBestExp(); assertEquals("missing literal", SqlKind.LITERAL, optimizedRelNode.getChildExps().get(0).getKind()); RexLiteral val = (RexLiteral) optimizedRelNode.getChildExps().get(0); assertEquals(true, val.getValue()); }