public boolean needProcess()
      throws Exception {
    if (_segmentMetadata.getTotalDocs() == 0) {
      return false;
    }
    try (SegmentDirectory.Reader segmentReader = _segmentDirectory.createReader()) {
      // Check if there is need to update default columns according to the schema.
      if (_schema != null) {
        DefaultColumnHandler defaultColumnHandler = DefaultColumnHandlerFactory
            .getDefaultColumnHandler(null, _segmentMetadata, _indexLoadingConfig, _schema, null);
        if (defaultColumnHandler.needUpdateDefaultColumns()) {
          LOGGER.info("Found default columns need updates in segment: {}", _segmentMetadata.getName());
          return true;
        }
      }
      // Check if there is need to update single-column indices, like inverted index, json index etc.
      for (IndexType<?, ?, ?> type : IndexService.getInstance().getAllIndexes()) {
        if (createHandler(type).needUpdateIndices(segmentReader)) {
          LOGGER.info("Found index type: {} needs updates in segment: {}", type, _segmentMetadata.getName());
          return true;
        }
      }
      // Check if there is need to create/modify/remove star-trees.
      if (needProcessStarTrees()) {
        LOGGER.info("Found startree index needs updates in segment: {}", _segmentMetadata.getName());
        return true;
      }
      // Check if there is need to update column min max value.
      List<String> columnMinMaxValueUpdates = columnMinMaxValueUpdates();
      if (!columnMinMaxValueUpdates.isEmpty()) {
        LOGGER.info("Found min max values need updates for columns: {} in segment: {}",
            columnMinMaxValueUpdates, _segmentMetadata.getName());
        return true;
      }
    }
    return false;
  }
@Test
  public void testNeedAddMinMaxValue()
      throws Exception {

    String[] stringValuesInvalid = {"A,", "B,", "C,", "D,", "E"};
    String[] stringValuesValid = {"A", "B", "C", "D", "E"};
    long[] longValues = {1588316400000L, 1588489200000L, 1588662000000L, 1588834800000L, 1589007600000L};
    TableConfig tableConfig = new TableConfigBuilder(TableType.OFFLINE).setTableName("testTable").build();
    Schema schema = new Schema.SchemaBuilder().addSingleValueDimension("stringCol", FieldSpec.DataType.STRING)
        .addMetric("longCol", FieldSpec.DataType.LONG).build();

    FileUtils.deleteQuietly(INDEX_DIR);

    // build good segment, no needPreprocess
    File segment = buildTestSegment(tableConfig, schema, "validSegment", stringValuesValid, longValues);
    SegmentDirectory segmentDirectory = SegmentDirectoryLoaderRegistry.getDefaultSegmentDirectoryLoader()
        .load(segment.toURI(),
            new SegmentDirectoryLoaderContext.Builder().setSegmentDirectoryConfigs(_configuration).build());
    IndexLoadingConfig indexLoadingConfig = getDefaultIndexLoadingConfig();
    indexLoadingConfig.setColumnMinMaxValueGeneratorMode(ColumnMinMaxValueGeneratorMode.ALL);
    SegmentPreProcessor processor = new SegmentPreProcessor(segmentDirectory, indexLoadingConfig, schema);
    assertFalse(processor.needProcess());

    // build bad segment, still no needPreprocess, since minMaxInvalid flag should be set
    FileUtils.deleteQuietly(INDEX_DIR);
    segment = buildTestSegment(tableConfig, schema, "invalidSegment", stringValuesInvalid, longValues);
    segmentDirectory = SegmentDirectoryLoaderRegistry.getDefaultSegmentDirectoryLoader().load(segment.toURI(),
        new SegmentDirectoryLoaderContext.Builder().setSegmentDirectoryConfigs(_configuration).build());
    indexLoadingConfig = getDefaultIndexLoadingConfig();
    indexLoadingConfig.setColumnMinMaxValueGeneratorMode(ColumnMinMaxValueGeneratorMode.NONE);
    processor = new SegmentPreProcessor(segmentDirectory, indexLoadingConfig, schema);
    assertFalse(processor.needProcess());

    indexLoadingConfig.setColumnMinMaxValueGeneratorMode(ColumnMinMaxValueGeneratorMode.ALL);
    processor = new SegmentPreProcessor(segmentDirectory, indexLoadingConfig, schema);
    assertFalse(processor.needProcess());

    // modify metadata, to remove min/max, now needPreprocess
    removeMinMaxValuesFromMetadataFile(segment);
    segmentDirectory = SegmentDirectoryLoaderRegistry.getDefaultSegmentDirectoryLoader().load(segment.toURI(),
        new SegmentDirectoryLoaderContext.Builder().setSegmentDirectoryConfigs(_configuration).build());
    processor = new SegmentPreProcessor(segmentDirectory, indexLoadingConfig, schema);
    assertTrue(processor.needProcess());

    FileUtils.deleteQuietly(INDEX_DIR);
  }