wgtmac commented on PR #3700:
URL: https://github.com/apache/parquet-java/pull/3700#issuecomment-5450573700

   Sorry for the delay. I still think the current approach is not clean. To 
avoid more roundtrip discussion, I've put up a draft as the diff below. Let me 
know what you think.
   
   ```
   diff --git 
a/parquet-column/src/main/java/org/apache/parquet/CorruptStatistics.java 
b/parquet-column/src/main/java/org/apache/parquet/CorruptStatistics.java
   index 546b9bdf..85493efc 100644
   --- a/parquet-column/src/main/java/org/apache/parquet/CorruptStatistics.java
   +++ b/parquet-column/src/main/java/org/apache/parquet/CorruptStatistics.java
   @@ -19,7 +19,6 @@
    package org.apache.parquet;
   
    import java.util.concurrent.atomic.AtomicBoolean;
   -import org.apache.parquet.SemanticVersion.SemanticVersionParseException;
    import org.apache.parquet.VersionParser.ParsedVersion;
    import org.apache.parquet.VersionParser.VersionParseException;
    import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName;
   @@ -110,11 +109,7 @@ public class CorruptStatistics {
        }
   
        if (!writerVersion.hasSemanticVersion()) {
   -      try {
   -        SemanticVersion.parse(writerVersion.version);
   -      } catch (SemanticVersionParseException e) {
   -        warnParseErrorOnce(createdBy, e);
   -      }
   +      warnParseErrorOnce(createdBy, 
writerVersion.getSemanticVersionParseFailure());
          return true;
        }
   
   diff --git 
a/parquet-column/src/test/java/org/apache/parquet/CorruptStatisticsTest.java 
b/parquet-column/src/test/java/org/apache/parquet/CorruptStatisticsTest.java
   index ff950a25..ba4668ad 100644
   --- 
a/parquet-column/src/test/java/org/apache/parquet/CorruptStatisticsTest.java
   +++ 
b/parquet-column/src/test/java/org/apache/parquet/CorruptStatisticsTest.java
   @@ -162,6 +162,8 @@ public class CorruptStatisticsTest {
        // version field present but not a valid semantic version
        ParsedVersion invalidSemver = new ParsedVersion("parquet-mr", 
"not-a-semver", "abc");
        assertThat(invalidSemver.hasSemanticVersion()).isFalse();
   +    assertThat(invalidSemver.getSemanticVersionParseFailure())
   +        .isInstanceOf(SemanticVersion.SemanticVersionParseException.class);
        assertThat(CorruptStatistics.shouldIgnoreStatistics(
                invalidSemver, "parquet-mr version not-a-semver (build abc)", 
PrimitiveTypeName.BINARY))
            .isTrue();
   diff --git 
a/parquet-common/src/main/java/org/apache/parquet/VersionParser.java 
b/parquet-common/src/main/java/org/apache/parquet/VersionParser.java
   index 07feb0d3..82e45eb8 100644
   --- a/parquet-common/src/main/java/org/apache/parquet/VersionParser.java
   +++ b/parquet-common/src/main/java/org/apache/parquet/VersionParser.java
   @@ -41,6 +41,7 @@ public class VersionParser {
   
        private final boolean hasSemver;
        private final SemanticVersion semver;
   +    private final Exception semanticVersionParseFailure;
   
        public ParsedVersion(String application, String version, String 
appBuildHash) {
          checkArgument(!Strings.isNullOrEmpty(application), "application 
cannot be null or empty");
   @@ -48,17 +49,20 @@ public class VersionParser {
          this.version = Strings.isNullOrEmpty(version) ? null : version;
          this.appBuildHash = Strings.isNullOrEmpty(appBuildHash) ? null : 
appBuildHash;
   
   -      SemanticVersion sv;
   -      boolean hasSemver;
   -      try {
   -        sv = SemanticVersion.parse(version);
   -        hasSemver = true;
   -      } catch (RuntimeException | SemanticVersionParseException e) {
   -        sv = null;
   -        hasSemver = false;
   +      SemanticVersion sv = null;
   +      boolean hasSemver = false;
   +      Exception parseFailure = null;
   +      if (this.version != null) {
   +        try {
   +          sv = SemanticVersion.parse(this.version);
   +          hasSemver = true;
   +        } catch (RuntimeException | SemanticVersionParseException e) {
   +          parseFailure = e;
   +        }
          }
          this.semver = sv;
          this.hasSemver = hasSemver;
   +      this.semanticVersionParseFailure = parseFailure;
        }
   
        public boolean hasSemanticVersion() {
   @@ -69,6 +73,14 @@ public class VersionParser {
          return semver;
        }
   
   +    /**
   +     * Returns the exception captured when parsing the semantic version 
failed, or {@code null} if
   +     * parsing succeeded.
   +     */
   +    Exception getSemanticVersionParseFailure() {
   +      return semanticVersionParseFailure;
   +    }
   +
        @Override
        public boolean equals(Object o) {
          if (this == o) return true;
   diff --git 
a/parquet-hadoop/src/main/java/org/apache/parquet/format/converter/ParquetMetadataConverter.java
 
b/parquet-hadoop/src/main/java/org/apache/parquet/format/converter/ParquetMetadataConverter.java
   index 1f2fd6e4..8f2dd852 100644
   --- 
a/parquet-hadoop/src/main/java/org/apache/parquet/format/converter/ParquetMetadataConverter.java
   +++ 
b/parquet-hadoop/src/main/java/org/apache/parquet/format/converter/ParquetMetadataConverter.java
   @@ -947,44 +947,7 @@ public class ParquetMetadataConverter {
      // Visible for testing
      static org.apache.parquet.column.statistics.Statistics 
fromParquetStatisticsInternal(
          String createdBy, Statistics formatStats, PrimitiveType type, 
SortOrder typeSortOrder) {
   -    org.apache.parquet.column.statistics.Statistics.Builder statsBuilder =
   -        
org.apache.parquet.column.statistics.Statistics.getBuilderForReading(type);
   -
   -    if (formatStats != null) {
   -      // Use the new V2 min-max statistics over the former one if it is 
filled
   -      if (formatStats.isSetMin_value() && formatStats.isSetMax_value()) {
   -        byte[] min = formatStats.min_value.array();
   -        byte[] max = formatStats.max_value.array();
   -        if (isMinMaxStatsSupported(type) || Arrays.equals(min, max)) {
   -          statsBuilder.withMin(min);
   -          statsBuilder.withMax(max);
   -        }
   -      } else {
   -        boolean isSet = formatStats.isSetMax() && formatStats.isSetMin();
   -        boolean maxEqualsMin = isSet ? Arrays.equals(formatStats.getMin(), 
formatStats.getMax()) : false;
   -        boolean sortOrdersMatch = SortOrder.SIGNED == typeSortOrder;
   -        // NOTE: See docs in CorruptStatistics for explanation of why this 
check is needed
   -        // The sort order is checked to avoid returning min/max stats that 
are not
   -        // valid with the type's sort order. In previous releases, all 
stats were
   -        // aggregated using a signed byte-wise ordering, which isn't valid 
for all the
   -        // types (e.g. strings, decimals etc.).
   -        if (!CorruptStatistics.shouldIgnoreStatistics(createdBy, 
type.getPrimitiveTypeName())
   -            && (sortOrdersMatch || maxEqualsMin)) {
   -          if (isSet) {
   -            statsBuilder.withMin(formatStats.min.array());
   -            statsBuilder.withMax(formatStats.max.array());
   -          }
   -        }
   -      }
   -
   -      if (formatStats.isSetNull_count()) {
   -        statsBuilder.withNumNulls(formatStats.null_count);
   -      }
   -      if (formatStats.isSetNan_count()) {
   -        statsBuilder.withNanCount(formatStats.getNan_count());
   -      }
   -    }
   -    return statsBuilder.build();
   +    return fromParquetStatisticsInternal(null, createdBy, formatStats, 
type, typeSortOrder);
      }
   
      // Visible for testing
   @@ -1015,7 +978,10 @@ public class ParquetMetadataConverter {
            // valid with the type's sort order. In previous releases, all 
stats were
            // aggregated using a signed byte-wise ordering, which isn't valid 
for all the
            // types (e.g. strings, decimals etc.).
   -        if (!CorruptStatistics.shouldIgnoreStatistics(writerVersion, 
createdBy, type.getPrimitiveTypeName())
   +        boolean shouldIgnoreStatistics = writerVersion == null
   +            ? CorruptStatistics.shouldIgnoreStatistics(createdBy, 
type.getPrimitiveTypeName())
   +            : CorruptStatistics.shouldIgnoreStatistics(writerVersion, 
createdBy, type.getPrimitiveTypeName());
   +        if (!shouldIgnoreStatistics
                && (sortOrdersMatch || maxEqualsMin)) {
              if (isSet) {
                statsBuilder.withMin(formatStats.min.array());
   @@ -1875,20 +1841,7 @@ public class ParquetMetadataConverter {
   
      public ColumnChunkMetaData buildColumnChunkMetaData(
          ColumnMetaData metaData, ColumnPath columnPath, PrimitiveType type, 
String createdBy) {
   -    return ColumnChunkMetaData.get(
   -        columnPath,
   -        type,
   -        fromFormatCodec(metaData.codec),
   -        convertEncodingStats(metaData.getEncoding_stats()),
   -        fromFormatEncodings(metaData.encodings),
   -        fromParquetStatistics(createdBy, metaData.statistics, type),
   -        metaData.data_page_offset,
   -        metaData.dictionary_page_offset,
   -        metaData.num_values,
   -        metaData.total_compressed_size,
   -        metaData.total_uncompressed_size,
   -        fromParquetSizeStatistics(metaData.size_statistics, type),
   -        fromParquetStatistics(metaData.geospatial_statistics, type));
   +    return buildColumnChunkMetaData(metaData, columnPath, type, null, 
createdBy);
      }
   
      public ColumnChunkMetaData buildColumnChunkMetaData(
   @@ -1934,10 +1887,8 @@ public class ParquetMetadataConverter {
            buildFileMetaData(parquetMetadata, messageType, encryptedFooter, 
fileDecryptor);
        String createdBy = fileMetaData.getCreatedBy();
        ParsedVersion writerVersion = null;
   -    boolean useWriterVersion = false;
        try {
          writerVersion = fileMetaData.getWriterVersion();
   -      useWriterVersion = true;
        } catch (VersionParseException e) {
          // Fall back to String-based path which logs the parse error with 
full context
        }
   @@ -2020,10 +1971,8 @@ public class ParquetMetadataConverter {
              if (!lazyMetadataDecryption) { // full column metadata (with 
stats) is available
                PrimitiveType primitiveType =
                    messageType.getType(columnPath.toArray()).asPrimitiveType();
   -            column = useWriterVersion
   -                ? buildColumnChunkMetaData(
   -                    metaData, columnPath, primitiveType, writerVersion, 
createdBy)
   -                : buildColumnChunkMetaData(metaData, columnPath, 
primitiveType, createdBy);
   +            column = buildColumnChunkMetaData(
   +                metaData, columnPath, primitiveType, writerVersion, 
createdBy);
                column.setRowGroupOrdinal(rowGroup.getOrdinal());
                if (metaData.isSetBloom_filter_offset()) {
                  
column.setBloomFilterOffset(metaData.getBloom_filter_offset());
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to