Conversation
…e so for reference it is
…emitting pos deltes
…erg validation test pending
…c/olake into feat/iceberg-deletion-vectors
|
AI review w.r.t. v3 spec |
| * time after a whole sync's worth of work. | ||
| */ | ||
| private void validateOrUpgradeFormatVersion(Table table, DeleteMode deleteMode) { | ||
| int current = ((org.apache.iceberg.HasTableOperations) table).operations().current().formatVersion(); |
There was a problem hiding this comment.
| int current = ((org.apache.iceberg.HasTableOperations) table).operations().current().formatVersion(); | |
| int curSpecVersion = ((org.apache.iceberg.HasTableOperations) table).operations().current().formatVersion(); |
| if (current < required) { | ||
| // e.g. a stream reconfigured from eq/pos to dv against a table that | ||
| // already exists at v2. One-way; see IcebergUtil.ensureFormatVersion. | ||
| IcebergUtil.ensureFormatVersion(table, required); |
There was a problem hiding this comment.
we can write logic here only, instead of creating a function
| deleteMode types.UpdateType | ||
| // pendingVectors buffers positions per data file until a batch is worth sending. Only used under DeleteModeDeletionVector. | ||
| pendingVectors map[string]*pendingVector | ||
| pendingVectorCount int |
There was a problem hiding this comment.
this variable seems not required
There was a problem hiding this comment.
it is required for checking delete batch size and flush
There was a problem hiding this comment.
queueVectorDeletes runs once per batch, and each call adds len(deletes). The send happens only once the total reaches deletionVectorBatchSize, which can take many calls. local would reset to 0 on every call, so it would only ever see one batch's count.
| if (filePath != null) { | ||
| referencedDataFiles.add(filePath.toString()); | ||
| } | ||
| if (deleteFile.content() != FileContent.POSITION_DELETES) { |
There was a problem hiding this comment.
we need validation for deletion vector as well right? like deletion vector is committed for the file which not exist?
There was a problem hiding this comment.
have we tested conflicting dv ?
There was a problem hiding this comment.
POSITION_DELETES covers both dv and pos deletes files, rowDelta.validateDataFilesExist(referencedDataFiles) would handle that
There was a problem hiding this comment.
in arrow writer as well?
There was a problem hiding this comment.
yeah, Iceberg has only 3 content types (DATA, POSITION_DELETES, EQUALITY_DELETES)
| import io.debezium.server.iceberg.rpc.RecordIngest.IcebergPayload; | ||
|
|
||
| /** How a writer represents the removal of a row that a later version supersedes. */ | ||
| public enum DeleteMode { |
There was a problem hiding this comment.
the resolver will be in common part right, it should not depend on arrow right? let us simplify if possible we can discuss
There was a problem hiding this comment.
how is it depending on arrow mode? could you please explain more on this
|
we need to run clear destination once someone change eq -> dv or pos -> dv |
|
| # TEMP(hack): dropped `github.event_name == 'pull_request' &&` to run ITs from push while the | ||
| # PR has merge conflicts. REVERT BEFORE MERGE. | ||
| if: ${{ !cancelled() && needs.preflight.result == 'success' && needs.preflight.outputs.drivers != '[]' && needs.build-jar.result != 'failure' && needs.apt-warm.result != 'failure' }} |
| if writer.positionalDeleteWriter == nil { | ||
| // Deletion vectors are encoded server-side from streamed positions, so this | ||
| // mode writes no delete file of its own - see sendPendingVectors. | ||
| if writer.positionalDeleteWriter == nil && w.deleteMode != types.UpdateTypeDeletionVector { |
There was a problem hiding this comment.
we can remove this check ? or let us also not create equality writer as well?
There was a problem hiding this comment.
for eq there is already w.indexThread == nil check, it won't create eq writer
| if (filePath != null) { | ||
| referencedDataFiles.add(filePath.toString()); | ||
| } | ||
| if (deleteFile.content() != FileContent.POSITION_DELETES) { |
There was a problem hiding this comment.
in arrow writer as well?
| * including the destination check, which sends EQUALITY for its throwaway table. | ||
| * UNRECOGNIZED means the sender knows a mode this build does not. | ||
| */ | ||
| public static DeleteMode resolve(IcebergPayload.DeleteMode deleteMode) { |
There was a problem hiding this comment.
let us do clear destination when user changes back from dv to anything
| } | ||
|
|
||
| DeleteWriteResult result = writer.result(); | ||
| return new WrittenDeletes(result.deleteFiles(), result.rewrittenDeleteFiles()); |
There was a problem hiding this comment.
we are sure that all older dv also merged? as well as pos got removed?
| */ | ||
| static Map<String, List<DeleteFile>> planDeletes(Table table) { | ||
| Map<String, List<DeleteFile>> byPath = Maps.newHashMap(); | ||
| try (CloseableIterable<FileScanTask> tasks = table.newScan().planFiles()) { |
There was a problem hiding this comment.
this is heavy operation and we already do it eq migrator, see if we can have some different logic here
…tazip-inc/olake into feat/iceberg-deletion-vectors
…eat/iceberg-deletion-vectors
| // Deletion-vector replace semantics: a superseded vector must leave the table | ||
| // in the SAME commit the new one arrives in, or the table ends up with two | ||
| // vectors for one data file. Always empty outside DELETION_VECTOR mode. | ||
| rewrittenDeleteFiles.forEach(rowDelta::removeDeletes); |
| OutputFileFactory dvFileFactory = IcebergUtil.getTableOutputFileFactory(icebergTable, FileFormat.PUFFIN); | ||
| // A vector replaces the data file's previous one, so it has to be seeded with | ||
| // the positions already deleted or this commit would resurrect them. | ||
| return new PositionalDeleteSink.DeletionVectors( |
There was a problem hiding this comment.
do we need to have previous loader in delta writer as well?
| // One writer for both layouts: an unpartitioned table is a single entry keyed | ||
| // on the empty partition struct, so there is no partitioned/unpartitioned split. | ||
| // pos vs dv is entirely the sink's concern from here - the writer never branches. | ||
| return new PositionalDeltaWriter(icebergTable.spec(), format, appenderFactory, fileFactory, |
There was a problem hiding this comment.
let us separate the names, call dv writer explicit
| * close. Keeping one delete file per referenced data file is what lets Iceberg treat | ||
| * them as file-scoped and match them to data files by path rather than by partition. | ||
| */ | ||
| final class PositionalFiles implements PositionalDeleteSink { |
There was a problem hiding this comment.
this was not there in older version ?
Description
Adds
dvas a third per-stream delete mode alongsideeqandpos, writing Iceberg v3 Puffin deletion vectors instead of Parquet positional deletes.Introduces
PositionalDeleteSinksoPositionalDeltaWritercan target either representation, plusDeletionVectorConverterandPreviousDeleteLoaderto merge new deletes with existing Parquet positional deletes or deletion vectors without resurrecting previously deleted rows.Updates
EqualityDeleteMigrator.migrate()to accept atargetMode, allowing tables to switch from equality deletes directly toposordvencoding in a single atomicRewriteFilescommit.Fixes #1168
Type of change
How Has This Been Tested?
Screenshots or Recordings
Documentation
Related PR's (If Any):