apache / apache/parquet-java

Potential bug in ParquetWriteProtocol

オープン
#2,701 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る
Component: Parquet Priority: Minor Type: bug
主要言語
Java
スター
3.1k
フォーク
1.6k
平均マージ
3日 12時間
マージ済み PR(30日)
33

説明

We found what we think is a bug in ParquetWriteProtocol, in which ParquetWriteProtocol will fail on instantiation of StructWriteProtocol if the StructType contains an empty child struct.

Specifically, for the ParquetWriteProtocol, if the thriftStruct contains an empty struct, logic in ThriftSchemaConvertVisitor drops the element, yielding a MessageType that has 1 fewer fields than the original schema. Subsequent logic in ParquetWriteProtocol.StructWriteProtocol tries to populate a `children` element by iterating through the thrift struct children and trying to get the element from the ColumnIO object
```java

Given: ThriftStruct with 20 fields
MessageType schema = ThriftSchemaConverter.convertWithoutProjection(thriftStruct)
-> ThriftSchemaConvertVisotor.convert(StructType struct...)
-> -> Visitor = new ThriftSchemaConvertVisitor(filter, true, keepOneOfEachUnion), state)
-> -> ConvertedField = struct.accept(visitor)
-> -> -> ThriftSchemaConvertVisotor.visit(struct, state)
-> -> -> -> ConvertedField converted = child.getType().accept(this, childState)
-> -> -> -> ThriftSchemaConvertVisotor.visit(struct, state) //here we’re at the child struct
```
 In here, we have both hasSentinelUnionColumns and hasNonSentinelUnionColumns defaulted as false and we look for any child elements, in which case, one of these is updated to true.  Thus, when we come to this step, we fall into the Drop() case.    

 
```java

  if (hasNonSentinelUnionColumns) {
      // user requested some of the fields of this struct, so we keep the struct
      return new Keep(state.path, new GroupType(state.repetition, state.name, convertedChildren));
    } else {
      // user requested none of the fields of this struct, so we drop it
      return new Drop(state.path);
    }
```
 

Because this field is Dropped, our MessageType.fieldsList is 19

 
```java

ColumnIO = new ColumnIOFactory().getColumnIO(MessageType) // again yields a ColumnIO with only 19 fields
TProtocol = new ParquetWriteProtocol(recordConsumer, columnIo, thriftStruct)
-> MessageWriteProtocol = new MessageWriteProtocol(ColumnIO schema, StructType thriftType)
-> -> new StructWriteProtocol(ColumnIO schema, StructType thriftType...)

for (i = 0 to thriftStruct.children.size) // which is 20
schema.getChild(i) // Out of bounds error on index 19
```

We currently have a workaround for this but would like to get a fix if possible.

**Reporter**: [Joy Bestourous](https://issues.apache.org/jira/secure/ViewProfile.jspa?name=jbestourous)

**Note**: *This issue was originally created as [PARQUET-2168](https://issues.apache.org/jira/browse/PARQUET-2168). Please see the [migration documentation](https://issues.apache.org/jira/browse/PARQUET-2502) for further details.*

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

調査の方向性

Start with ThriftSchemaConvertVisitor.visit and ParquetWriteProtocol.StructWriteProtocol, following the conversion from a thrift struct to MessageType and ColumnIO. Reproduce the failure with a thrift struct containing an empty child struct and inspect how dropped fields affect schema child lookup. Done means instantiation no longer produces the out-of-bounds error while preserving the intended schema conversion behavior.

索引モデルが issue の本文から書いたものです。

評価

技術スタック
java
領域
data-engineering
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
45/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。