private static TableDeletionEntry parsePredicate(Expression expression, TsTable table) {
    if (expression == null) {
      return new TableDeletionEntry(
          new DeletionPredicate(table.getTableName()),
          new TimeRange(Long.MIN_VALUE, Long.MAX_VALUE, true).toTsFileTimeRange());
    }

    Queue<Expression> expressionQueue = new LinkedList<>();
    expressionQueue.add(expression);
    DeletionPredicate predicate = new DeletionPredicate(table.getTableName());
    IDPredicate idPredicate = null;
    TimeRange timeRange = new TimeRange(Long.MIN_VALUE, Long.MAX_VALUE, true);
    while (!expressionQueue.isEmpty()) {
      Expression currExp = expressionQueue.remove();
      if (currExp instanceof LogicalExpression) {
        parseAndPredicate(((LogicalExpression) currExp), expressionQueue);
      } else if (currExp instanceof ComparisonExpression) {
        idPredicate =
            parseComparison(((ComparisonExpression) currExp), timeRange, idPredicate, table);
      } else if (currExp instanceof IsNullPredicate) {
        idPredicate = parseIsNull((IsNullPredicate) currExp, idPredicate, table);
      } else {
        throw new SemanticException("Unsupported expression: " + currExp + " in " + expression);
      }
    }
    if (idPredicate != null) {
      predicate.setIdPredicate(idPredicate);
    }
    if (timeRange.getStartTime() > timeRange.getEndTime()) {
      throw new SemanticException(
          String.format(
              "Start time %d is greater than end time %d",
              timeRange.getStartTime(), timeRange.getEndTime()));
    }

    return new TableDeletionEntry(predicate, timeRange.toTsFileTimeRange());
  }
Convert to a disjunctive normal forms.

<p>For example: ( A | B ) & ( C | D ) => ( A & C ) | ( A & D ) | ( B & C ) | ( B & D)

<p>Returns the original expression if the expression is null or if the distribution will expand
the expression by too much.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeUtils.java