Skip to content

Latest commit

 

History

History
155 lines (143 loc) · 5.19 KB

获取表达式的合取范式和析取范式.md

File metadata and controls

155 lines (143 loc) · 5.19 KB

介绍

析取 :用连词v把几个公式连接起来所构成的公式叫做析取

合取 :用连词^把几个公式连接起来而构成的公式叫做合取

RexNode.getOperands() : 获取表达式的子节点,单元表达式只有一个节点,使用数组下表[0]获取

获取表达式简单合取范式

 /**
   * 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);
    }
  }

获取析取范式列表

即表达式rexList结果中只要有一个为真,整个表达式 rexPredicate为真。

A OR (B AND C) -> lIST(A, (B AND C))

/**
   * Decomposes a predicate into a list of expressions that are OR'ed
   * together.
   * 这个方法抽取条件表达式中的析取范式list,即当list中表达式全部为true的时候,表达式为true
   *
   * @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);
    }
  }

获取条件表达式的合取范式

rexList 全部为true 并且 notList全为false的时候,整个表达式为真

A AND (NOT B) AND (C OR D) AND NOT (NOT(E) OR (F AND G)) 解析的结果为 rexList = List(A, C OR D, E) notList = List(B, F AND G)

 /**
   * 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 OR, 因为AND相连,此处不拆分OR条件,Spark中存在同样的问题
    case AND:
      // 如果是AND则需要继续取左右子节点(operands)继续判断 
      for (RexNode operand : ((RexCall) rexPredicate).getOperands()) {
        decomposeConjunction(operand, rexList, notList);
      }
      break;
    case NOT:
      // 如果是NOT,则取第一个子节点即NOT的子节点进行判断
      final RexNode e = ((RexCall) rexPredicate).getOperands().get(0);
      // 如果为假,在NOT的条件下即为真,不需要继续执行
      if (e.isAlwaysFalse()) {
        return;
      }
      switch (e.getKind()) {
        // NOT OR 组合需要获取所有的析取范式
      case OR:
        final List<RexNode> ors = new ArrayList<>();
        decomposeDisjunction(e, ors);
        for (RexNode or : ors) {
          switch (or.getKind()) {
          case NOT:
            // E = NOT(NOT(X) OR (YYY)), 如果要E为真,则需要X为假
            // 所以这里是添加到析取列表
            rexList.add(((RexCall) or).operands.get(0));
            break;
          default:
            notList.add(or);
          }
        }
        break;
      default:
        // 加入非析取list, 这里没有case AN, 因为在NOT条件中对于外层而言,
        // AND作为一个整体, 无法被完全分解
        notList.add(e);
      }
      break;
    case LITERAL:
      // 如果是常量,并且非空 & boolean类型值为true,可直接返回不判断
      if (!RexLiteral.isNullLiteral(rexPredicate)
          && RexLiteral.booleanValue(rexPredicate)) {
        return; // ignore TRUE
      }
      // 如果既不为空,常量值也不为true,由下面default处理
      // fall through
    default:
      // 非上述情况,则添加到析取队列
      rexList.add(rexPredicate);
      break;
    }
  }