Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BaseDeleteLoader may ignore delete records for binary columns #11239

Open
1 of 3 tasks
Gerrrr opened this issue Sep 30, 2024 · 0 comments
Open
1 of 3 tasks

BaseDeleteLoader may ignore delete records for binary columns #11239

Gerrrr opened this issue Sep 30, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@Gerrrr
Copy link

Gerrrr commented Sep 30, 2024

Apache Iceberg version

1.6.1 (latest release)

Query engine

None

Please describe the bug 🐞

In case of a binary column, Iceberg Equality Delete loader, BaseDeleteLoader reuses the underlying ByteBuffer used to read the delete records. In some situations it leads to overwriting previously read records from the delete file and in turn produces duplicates in the output.

Unfortunately, I can't share the exact code to reproduce the bug, but here is the table that contains the issue - 9a264a21-cc2f-4f13-8e7d-4d899a31ca2f 2.zip. A read from that table will contain duplicates as the equality delete reader will miss one of the 2 records present in the delete file.

In principle, it should be easy to reproduce with a table having a binary column and doing an overwrite on it. Unfortunately, I am new to Iceberg and couldn't find working instructions on how to set up a local environment and do an overwrite using equality deletes. If someone helps me with a local setup, I will be happy to provide a more actionable example.

Here are the pointers in the code to show how/why the overwrite happens:

  • Parquet reader configuration for delete files set up to reuse the ByteBuffer:

    case PARQUET:
    return Parquet.read(inputFile)
    .project(projection)
    .filter(filter)
    .reuseContainers()
    .createReaderFunc(newParquetReaderFunc(projection))
    .build();

  • ParquetValueReaders that reuses the same ByteByffer:

public ByteBuffer read(ByteBuffer reuse) {
Binary binary = column.nextBinary();
ByteBuffer data = binary.toByteBuffer();
if (reuse != null && reuse.hasArray() && reuse.capacity() >= data.remaining()) {
data.get(reuse.array(), reuse.arrayOffset(), data.remaining());
reuse.position(0);
reuse.limit(binary.length());
return reuse;
} else {
byte[] array = new byte[data.remaining()];
data.get(array, 0, data.remaining());
return ByteBuffer.wrap(array);
}
}
}

  • And finally, InternalRecordWrapper copies the pointer to that ByteBuffer (instead of its content) leading to the overwrite:
    public InternalRecordWrapper copyFor(StructLike record) {
    return new InternalRecordWrapper(transforms).wrap(record);
    }
  • Reading subsequent records from the delete file overwrites previously read records if the newer records fit into the buffer.

Willingness to contribute

  • I can contribute a fix for this bug independently
  • I would be willing to contribute a fix for this bug with guidance from the Iceberg community
  • I cannot contribute a fix for this bug at this time
@Gerrrr Gerrrr added the bug Something isn't working label Sep 30, 2024
@Gerrrr Gerrrr changed the title BaseDeleteLoader may ignore records BaseDeleteLoader may ignore delete records for binary columns Sep 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant