Java Code Examples for org.apache.calcite.rex.RexNode#isAlwaysFalse()

The following examples show how to use org.apache.calcite.rex.RexNode#isAlwaysFalse() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: RelOptUtil.java    From Bats with Apache License 2.0 5 votes vote down vote up
/**
 * 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);
    }
}
 
Example 2
Source File: RelOptUtil.java    From calcite with Apache License 2.0 5 votes vote down vote up
/**
 * 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);
  }
}
 
Example 3
Source File: RexImplicationChecker.java    From Bats with Apache License 2.0 4 votes vote down vote up
/**
 * Checks if condition first implies (&rArr;) condition second.
 *
 * <p>This reduces to SAT problem which is NP-Complete.
 * When this method says first implies second then it is definitely true.
 * But it cannot prove that first does not imply second.
 *
 * @param first first condition
 * @param second second condition
 * @return true if it can prove first &rArr; second; otherwise false i.e.,
 * it doesn't know if implication holds
 */
public boolean implies(RexNode first, RexNode second) {
  // Validation
  if (!validate(first, second)) {
    return false;
  }

  LOGGER.debug("Checking if {} => {}", first.toString(), second.toString());

  // Get DNF
  RexNode firstDnf = RexUtil.toDnf(builder, first);
  RexNode secondDnf = RexUtil.toDnf(builder, second);

  // Check Trivial Cases
  if (firstDnf.isAlwaysFalse()
      || secondDnf.isAlwaysTrue()) {
    return true;
  }

  // Decompose DNF into a list of conditions, each of which is a conjunction.
  // For example,
  //   (x > 10 AND y > 30) OR (z > 90)
  // is converted to list of 2 conditions:
  //   (x > 10 AND y > 30)
  //   z > 90
  //
  // Similarly, decompose CNF into a list of conditions, each of which is a
  // disjunction.
  List<RexNode> firsts = RelOptUtil.disjunctions(firstDnf);
  List<RexNode> seconds = RelOptUtil.disjunctions(secondDnf);

  for (RexNode f : firsts) {
    // Check if f implies at least
    // one of the conjunctions in list secondDnfs.
    // If f could not imply even one conjunction in
    // secondDnfs, then final implication may be false.
    if (!impliesAny(f, seconds)) {
      LOGGER.debug("{} does not imply {}", first, second);
      return false;
    }
  }

  LOGGER.debug("{} implies {}", first, second);
  return true;
}
 
Example 4
Source File: RelOptUtil.java    From Bats with Apache License 2.0 4 votes vote down vote up
/**
 * Decomposes a predicate into a list of expressions that are AND'ed
 * together, and a list of expressions that are preceded by NOT.
 *
 * <p>For example, {@code a AND NOT b AND NOT (c and d) AND TRUE AND NOT
 * FALSE} returns {@code rexList = [a], notList = [b, c AND d]}.</p>
 *
 * <p>TRUE and NOT FALSE expressions are ignored. FALSE and NOT TRUE
 * expressions are placed on {@code rexList} and {@code notList} as other
 * expressions.</p>
 *
 * <p>For example, {@code a AND TRUE AND NOT TRUE} returns
 * {@code rexList = [a], notList = [TRUE]}.</p>
 *
 * @param rexPredicate predicate to be analyzed
 * @param rexList      list of decomposed RexNodes (except those with NOT)
 * @param notList      list of decomposed RexNodes that were prefixed NOT
 */
public static void decomposeConjunction(RexNode rexPredicate, List<RexNode> rexList, List<RexNode> notList) {
    if (rexPredicate == null || rexPredicate.isAlwaysTrue()) {
        return;
    }
    switch (rexPredicate.getKind()) {
    case AND:
        for (RexNode operand : ((RexCall) rexPredicate).getOperands()) {
            decomposeConjunction(operand, rexList, notList);
        }
        break;
    case NOT:
        final RexNode e = ((RexCall) rexPredicate).getOperands().get(0);
        if (e.isAlwaysFalse()) {
            return;
        }
        switch (e.getKind()) {
        case OR:
            final List<RexNode> ors = new ArrayList<>();
            decomposeDisjunction(e, ors);
            for (RexNode or : ors) {
                switch (or.getKind()) {
                case NOT:
                    rexList.add(((RexCall) or).getOperands().get(0));
                    break;
                default:
                    notList.add(or);
                }
            }
            break;
        default:
            notList.add(e);
        }
        break;
    case LITERAL:
        if (!RexLiteral.isNullLiteral(rexPredicate) && RexLiteral.booleanValue(rexPredicate)) {
            return; // ignore TRUE
        }
        // fall through
    default:
        rexList.add(rexPredicate);
        break;
    }
}
 
Example 5
Source File: RelMdRowCount.java    From dremio-oss with Apache License 2.0 4 votes vote down vote up
public static double estimateRowCount(Join rel, RelMetadataQuery mq) {
  double rightJoinFactor = 1.0;

  RexNode condition = rel.getCondition();
  if (condition.isAlwaysTrue()) {
    // Cartesian join is only supported for NLJ. If join type is right, make it more expensive
    if (rel.getJoinType() == JoinRelType.RIGHT) {
      rightJoinFactor = 2.0;
    }
    return RelMdUtil.getJoinRowCount(mq, rel, condition) * rightJoinFactor;
  }

  final PlannerSettings plannerSettings = PrelUtil.getPlannerSettings(rel.getCluster().getPlanner());
  double filterMinSelectivityEstimateFactor = plannerSettings == null ?
    PlannerSettings.DEFAULT_FILTER_MIN_SELECTIVITY_ESTIMATE_FACTOR :
    plannerSettings.getFilterMinSelectivityEstimateFactor();
  double filterMaxSelectivityEstimateFactor = plannerSettings == null ?
    PlannerSettings.DEFAULT_FILTER_MAX_SELECTIVITY_ESTIMATE_FACTOR :
    plannerSettings.getFilterMaxSelectivityEstimateFactor();

  final RexNode remaining;
  if (rel instanceof JoinRelBase) {
    remaining = ((JoinRelBase) rel).getRemaining();
  } else {
    remaining = RelOptUtil.splitJoinCondition(rel.getLeft(), rel.getRight(), condition, new ArrayList<>(), new ArrayList<>(), new ArrayList<>());
  }

  double selectivity = mq.getSelectivity(rel, remaining);
  if (!remaining.isAlwaysFalse()) {
    // Cap selectivity at filterMinSelectivityEstimateFactor unless it is always FALSE
    if (selectivity < filterMinSelectivityEstimateFactor) {
      selectivity = filterMinSelectivityEstimateFactor;
    }
  }

  if (!remaining.isAlwaysTrue()) {
    // Cap selectivity at filterMaxSelectivityEstimateFactor unless it is always TRUE
    if (selectivity > filterMaxSelectivityEstimateFactor) {
      selectivity = filterMaxSelectivityEstimateFactor;
    }
    // Make right join more expensive for inequality join condition (logical phase)
    if (rel.getJoinType() == JoinRelType.RIGHT) {
      rightJoinFactor = 2.0;
    }
  }

  return selectivity * Math.max(mq.getRowCount(rel.getLeft()), mq.getRowCount(rel.getRight())) * rightJoinFactor;
}
 
Example 6
Source File: DruidJsonFilter.java    From calcite with Apache License 2.0 4 votes vote down vote up
/**
 * @param rexNode    rexNode to translate to Druid Filter
 * @param rowType    rowType of filter input
 * @param druidQuery Druid query
 *
 * @return Druid Json Filters or null when can not translate to valid Druid Filters.
 */
@Nullable
static DruidJsonFilter toDruidFilters(final RexNode rexNode, RelDataType rowType,
    DruidQuery druidQuery) {
  if (rexNode.isAlwaysTrue()) {
    return JsonExpressionFilter.alwaysTrue();
  }
  if (rexNode.isAlwaysFalse()) {
    return JsonExpressionFilter.alwaysFalse();
  }
  switch (rexNode.getKind()) {
  case IS_TRUE:
  case IS_NOT_FALSE:
    return toDruidFilters(Iterables.getOnlyElement(((RexCall) rexNode).getOperands()), rowType,
        druidQuery);
  case IS_NOT_TRUE:
  case IS_FALSE:
    final DruidJsonFilter simpleFilter = toDruidFilters(Iterables
        .getOnlyElement(((RexCall) rexNode).getOperands()), rowType, druidQuery);
    return simpleFilter != null ? new JsonCompositeFilter(Type.NOT, simpleFilter)
        : simpleFilter;
  case AND:
  case OR:
  case NOT:
    final RexCall call = (RexCall) rexNode;
    final List<DruidJsonFilter> jsonFilters = new ArrayList<>();
    for (final RexNode e : call.getOperands()) {
      final DruidJsonFilter druidFilter = toDruidFilters(e, rowType, druidQuery);
      if (druidFilter == null) {
        return null;
      }
      jsonFilters.add(druidFilter);
    }
    return new JsonCompositeFilter(Type.valueOf(rexNode.getKind().name()),
        jsonFilters);
  }

  final DruidJsonFilter simpleLeafFilter = toSimpleDruidFilter(rexNode, rowType, druidQuery);
  return simpleLeafFilter == null
      ? toDruidExpressionFilter(rexNode, rowType, druidQuery)
      : simpleLeafFilter;
}
 
Example 7
Source File: RexImplicationChecker.java    From calcite with Apache License 2.0 4 votes vote down vote up
/**
 * Checks if condition first implies (&rArr;) condition second.
 *
 * <p>This reduces to SAT problem which is NP-Complete.
 * When this method says first implies second then it is definitely true.
 * But it cannot prove that first does not imply second.
 *
 * @param first first condition
 * @param second second condition
 * @return true if it can prove first &rArr; second; otherwise false i.e.,
 * it doesn't know if implication holds
 */
public boolean implies(RexNode first, RexNode second) {
  // Validation
  if (!validate(first, second)) {
    return false;
  }

  LOGGER.debug("Checking if {} => {}", first.toString(), second.toString());

  // Get DNF
  RexNode firstDnf = RexUtil.toDnf(builder, first);
  RexNode secondDnf = RexUtil.toDnf(builder, second);

  // Check Trivial Cases
  if (firstDnf.isAlwaysFalse()
      || secondDnf.isAlwaysTrue()) {
    return true;
  }

  // Decompose DNF into a list of conditions, each of which is a conjunction.
  // For example,
  //   (x > 10 AND y > 30) OR (z > 90)
  // is converted to list of 2 conditions:
  //   (x > 10 AND y > 30)
  //   z > 90
  //
  // Similarly, decompose CNF into a list of conditions, each of which is a
  // disjunction.
  List<RexNode> firsts = RelOptUtil.disjunctions(firstDnf);
  List<RexNode> seconds = RelOptUtil.disjunctions(secondDnf);

  for (RexNode f : firsts) {
    // Check if f implies at least
    // one of the conjunctions in list secondDnfs.
    // If f could not imply even one conjunction in
    // secondDnfs, then final implication may be false.
    if (!impliesAny(f, seconds)) {
      LOGGER.debug("{} does not imply {}", first, second);
      return false;
    }
  }

  LOGGER.debug("{} implies {}", first, second);
  return true;
}
 
Example 8
Source File: RelOptUtil.java    From calcite with Apache License 2.0 4 votes vote down vote up
/**
 * Decomposes a predicate into a list of expressions that are AND'ed
 * together, and a list of expressions that are preceded by NOT.
 *
 * <p>For example, {@code a AND NOT b AND NOT (c and d) AND TRUE AND NOT
 * FALSE} returns {@code rexList = [a], notList = [b, c AND d]}.</p>
 *
 * <p>TRUE and NOT FALSE expressions are ignored. FALSE and NOT TRUE
 * expressions are placed on {@code rexList} and {@code notList} as other
 * expressions.</p>
 *
 * <p>For example, {@code a AND TRUE AND NOT TRUE} returns
 * {@code rexList = [a], notList = [TRUE]}.</p>
 *
 * @param rexPredicate predicate to be analyzed
 * @param rexList      list of decomposed RexNodes (except those with NOT)
 * @param notList      list of decomposed RexNodes that were prefixed NOT
 */
public static void decomposeConjunction(
    RexNode rexPredicate,
    List<RexNode> rexList,
    List<RexNode> notList) {
  if (rexPredicate == null || rexPredicate.isAlwaysTrue()) {
    return;
  }
  switch (rexPredicate.getKind()) {
  case AND:
    for (RexNode operand : ((RexCall) rexPredicate).getOperands()) {
      decomposeConjunction(operand, rexList, notList);
    }
    break;
  case NOT:
    final RexNode e = ((RexCall) rexPredicate).getOperands().get(0);
    if (e.isAlwaysFalse()) {
      return;
    }
    switch (e.getKind()) {
    case OR:
      final List<RexNode> ors = new ArrayList<>();
      decomposeDisjunction(e, ors);
      for (RexNode or : ors) {
        switch (or.getKind()) {
        case NOT:
          rexList.add(((RexCall) or).operands.get(0));
          break;
        default:
          notList.add(or);
        }
      }
      break;
    default:
      notList.add(e);
    }
    break;
  case LITERAL:
    if (!RexLiteral.isNullLiteral(rexPredicate)
        && RexLiteral.booleanValue(rexPredicate)) {
      return; // ignore TRUE
    }
    // fall through
  default:
    rexList.add(rexPredicate);
    break;
  }
}
 
Example 9
Source File: SubstitutionVisitor.java    From Bats with Apache License 2.0 3 votes vote down vote up
/**
 * Maps a condition onto a target.
 *
 * <p>If condition is stronger than target, returns the residue.
 * If it is equal to target, returns the expression that evaluates to
 * the constant {@code true}. If it is weaker than target, returns
 * {@code null}.</p>
 *
 * <p>The terms satisfy the relation</p>
 *
 * <blockquote>
 * <pre>{@code condition = target AND residue}</pre>
 * </blockquote>
 *
 * <p>and {@code residue} must be as weak as possible.</p>
 *
 * <p>Example #1: condition stronger than target</p>
 * <ul>
 * <li>condition: x = 1 AND y = 2</li>
 * <li>target: x = 1</li>
 * <li>residue: y = 2</li>
 * </ul>
 *
 * <p>Note that residue {@code x &gt; 0 AND y = 2} would also satisfy the
 * relation {@code condition = target AND residue} but is stronger than
 * necessary, so we prefer {@code y = 2}.</p>
 *
 * <p>Example #2: target weaker than condition (valid, but not currently
 * implemented)</p>
 * <ul>
 * <li>condition: x = 1</li>
 * <li>target: x = 1 OR z = 3</li>
 * <li>residue: x = 1</li>
 * </ul>
 *
 * <p>Example #3: condition and target are equivalent</p>
 * <ul>
 * <li>condition: x = 1 AND y = 2</li>
 * <li>target: y = 2 AND x = 1</li>
 * <li>residue: TRUE</li>
 * </ul>
 *
 * <p>Example #4: condition weaker than target</p>
 * <ul>
 * <li>condition: x = 1</li>
 * <li>target: x = 1 AND y = 2</li>
 * <li>residue: null (i.e. no match)</li>
 * </ul>
 *
 * <p>There are many other possible examples. It amounts to solving
 * whether {@code condition AND NOT target} can ever evaluate to
 * true, and therefore is a form of the NP-complete
 * <a href="http://en.wikipedia.org/wiki/Satisfiability">Satisfiability</a>
 * problem.</p>
 */
@VisibleForTesting
public static RexNode splitFilter(final RexSimplify simplify, RexNode condition, RexNode target) {
    final RexBuilder rexBuilder = simplify.rexBuilder;
    RexNode condition2 = canonizeNode(rexBuilder, condition);
    RexNode target2 = canonizeNode(rexBuilder, target);

    // First, try splitting into ORs.
    // Given target c1 OR c2 OR c3 OR c4
    // and condition c2 OR c4
    // residue is c2 OR c4
    // Also deals with case target [x] condition [x] yields residue [true].
    RexNode z = splitOr(rexBuilder, condition2, target2);
    if (z != null) {
        return z;
    }

    if (isEquivalent(rexBuilder, condition2, target2)) {
        return rexBuilder.makeLiteral(true);
    }

    RexNode x = andNot(rexBuilder, target2, condition2);
    if (mayBeSatisfiable(x)) {
        RexNode x2 = RexUtil.composeConjunction(rexBuilder, ImmutableList.of(condition2, target2));
        RexNode r = canonizeNode(rexBuilder, simplify.simplifyUnknownAsFalse(x2));
        if (!r.isAlwaysFalse() && isEquivalent(rexBuilder, condition2, r)) {
            List<RexNode> conjs = RelOptUtil.conjunctions(r);
            for (RexNode e : RelOptUtil.conjunctions(target2)) {
                removeAll(conjs, e);
            }
            return RexUtil.composeConjunction(rexBuilder, conjs);
        }
    }
    return null;
}
 
Example 10
Source File: SubstitutionVisitor.java    From calcite with Apache License 2.0 3 votes vote down vote up
/**
 * Maps a condition onto a target.
 *
 * <p>If condition is stronger than target, returns the residue.
 * If it is equal to target, returns the expression that evaluates to
 * the constant {@code true}. If it is weaker than target, returns
 * {@code null}.</p>
 *
 * <p>The terms satisfy the relation</p>
 *
 * <blockquote>
 * <pre>{@code condition = target AND residue}</pre>
 * </blockquote>
 *
 * <p>and {@code residue} must be as weak as possible.</p>
 *
 * <p>Example #1: condition stronger than target</p>
 * <ul>
 * <li>condition: x = 1 AND y = 2</li>
 * <li>target: x = 1</li>
 * <li>residue: y = 2</li>
 * </ul>
 *
 * <p>Note that residue {@code x &gt; 0 AND y = 2} would also satisfy the
 * relation {@code condition = target AND residue} but is stronger than
 * necessary, so we prefer {@code y = 2}.</p>
 *
 * <p>Example #2: target weaker than condition (valid, but not currently
 * implemented)</p>
 * <ul>
 * <li>condition: x = 1</li>
 * <li>target: x = 1 OR z = 3</li>
 * <li>residue: x = 1</li>
 * </ul>
 *
 * <p>Example #3: condition and target are equivalent</p>
 * <ul>
 * <li>condition: x = 1 AND y = 2</li>
 * <li>target: y = 2 AND x = 1</li>
 * <li>residue: TRUE</li>
 * </ul>
 *
 * <p>Example #4: condition weaker than target</p>
 * <ul>
 * <li>condition: x = 1</li>
 * <li>target: x = 1 AND y = 2</li>
 * <li>residue: null (i.e. no match)</li>
 * </ul>
 *
 * <p>There are many other possible examples. It amounts to solving
 * whether {@code condition AND NOT target} can ever evaluate to
 * true, and therefore is a form of the NP-complete
 * <a href="http://en.wikipedia.org/wiki/Satisfiability">Satisfiability</a>
 * problem.</p>
 */
@VisibleForTesting
public static RexNode splitFilter(final RexSimplify simplify,
    RexNode condition, RexNode target) {
  final RexBuilder rexBuilder = simplify.rexBuilder;
  RexNode condition2 = canonizeNode(rexBuilder, condition);
  RexNode target2 = canonizeNode(rexBuilder, target);

  // First, try splitting into ORs.
  // Given target    c1 OR c2 OR c3 OR c4
  // and condition   c2 OR c4
  // residue is      c2 OR c4
  // Also deals with case target [x] condition [x] yields residue [true].
  RexNode z = splitOr(rexBuilder, condition2, target2);
  if (z != null) {
    return z;
  }

  if (isEquivalent(rexBuilder, condition2, target2)) {
    return rexBuilder.makeLiteral(true);
  }

  RexNode x = andNot(rexBuilder, target2, condition2);
  if (mayBeSatisfiable(x)) {
    RexNode x2 = RexUtil.composeConjunction(rexBuilder,
        ImmutableList.of(condition2, target2));
    RexNode r = canonizeNode(rexBuilder,
        simplify.simplifyUnknownAsFalse(x2));
    if (!r.isAlwaysFalse() && isEquivalent(rexBuilder, condition2, r)) {
      List<RexNode> conjs = RelOptUtil.conjunctions(r);
      for (RexNode e : RelOptUtil.conjunctions(target2)) {
        removeAll(conjs, e);
      }
      return RexUtil.composeConjunction(rexBuilder, conjs);
    }
  }
  return null;
}