@Override
  protected Pair<Expression, Boolean> visitLogicalExpression(
      LogicalExpression node, Context context) {
    if (node.getOperator() == AND) {
      List<Pair<Expression, Boolean>> resultPairs = new ArrayList<>();
      for (Expression term : node.getTerms()) {
        resultPairs.add(process(term, context));
      }

      List<Expression> newTimeFilterTerms = new ArrayList<>();
      List<Expression> newValueFilterTerms = new ArrayList<>();
      // rewrite predicate to avoid duplicate calculation on time filter
      // If Left-child or Right-child does not contain value filter
      // We can set it to true in Predicate Tree
      if (context.canRewrite) {
        getNewTimeValueExpressions(node, resultPairs, newTimeFilterTerms, newValueFilterTerms);
      }

      if (!newTimeFilterTerms.isEmpty()) {
        node.setTerms(newValueFilterTerms);

        return new Pair<>(
            newTimeFilterTerms.size() == 1
                ? newTimeFilterTerms.get(0)
                : new LogicalExpression(AND, newTimeFilterTerms),
            !newValueFilterTerms.isEmpty());
      }

      return new Pair<>(null, true);
    } else if (node.getOperator() == OR) {

      List<Pair<Expression, Boolean>> resultPairs = new ArrayList<>();
      for (Expression term : node.getTerms()) {
        resultPairs.add(process(term, new Context(false, false, context.timeColumnName)));
      }

      List<Expression> newTimeFilterTerms = new ArrayList<>();
      List<Expression> newValueFilterTerms = new ArrayList<>();

      getNewTimeValueExpressions(node, resultPairs, newTimeFilterTerms, newValueFilterTerms);

      // for example, `(t1 and s1) or t2`, `t1 or t2` meets this condition
      if (newTimeFilterTerms.size() == node.getTerms().size()) {
        if (context.isFirstOr && newValueFilterTerms.isEmpty()) {
          node.setTerms(Collections.singletonList(TRUE_LITERAL));
        }
        return new Pair<>(
            newTimeFilterTerms.size() == 1
                ? newTimeFilterTerms.get(0)
                : new LogicalExpression(OR, newTimeFilterTerms),
            !newValueFilterTerms.isEmpty());
      }

      return new Pair<>(null, true);
    } else {
      throw new IllegalStateException("Illegal state in visitLogicalExpression");
    }
  }
Extract global time predicate from query predicate.

@param predicate raw query predicate
@return Pair, left is globalTimePredicate, right is if hasValueFilter.
@throws UnknownExpressionTypeException unknown expression type
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/ir/GlobalTimePredicateExtractVisitor.java