-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Flink: Dynamic Sink: Add support for dropping columns #14728
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
Changes from 5 commits
ef3656f
f72625c
e0f3cdf
0e125a1
959fc63
4bbc394
b96421c
6c95ce4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,10 +21,13 @@ | |
| import java.util.List; | ||
| import org.apache.iceberg.Schema; | ||
| import org.apache.iceberg.UpdateSchema; | ||
| import org.apache.iceberg.catalog.TableIdentifier; | ||
| import org.apache.iceberg.relocated.com.google.common.base.Preconditions; | ||
| import org.apache.iceberg.schema.SchemaWithPartnerVisitor; | ||
| import org.apache.iceberg.types.Type; | ||
| import org.apache.iceberg.types.Types; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
| /** | ||
| * Visitor class that accumulates the set of changes needed to evolve an existing schema into the | ||
|
|
@@ -36,30 +39,39 @@ | |
| * <li>Adding new columns | ||
| * <li>Widening the type of existing columsn | ||
| * <li>Reordering columns | ||
| * <li>Dropping columns (when dropUnusedColumns is enabled) | ||
| * </ul> | ||
| * | ||
| * We don't support: | ||
| * | ||
| * <ul> | ||
| * <li>Dropping columns | ||
| * <li>Renaming columns | ||
| * </ul> | ||
| * | ||
| * The reason is that dropping columns would create issues with late / out of order data. Once we | ||
| * drop fields, we wouldn't be able to easily add them back later without losing the associated | ||
| * data. Renaming columns is not supported because we compare schemas by name, which doesn't allow | ||
| * for renaming without additional hints. | ||
| * By default, columns that exist in the table but not in the input schema are made optional to | ||
| * avoid issues with late/out-of-order data. When dropUnusedColumns is enabled, these columns are | ||
| * dropped instead for 1:1 schema syncing. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe something like this:
|
||
| */ | ||
| public class EvolveSchemaVisitor extends SchemaWithPartnerVisitor<Integer, Boolean> { | ||
|
|
||
| private static final Logger LOG = LoggerFactory.getLogger(EvolveSchemaVisitor.class); | ||
| private final TableIdentifier identifier; | ||
| private final UpdateSchema api; | ||
| private final Schema existingSchema; | ||
| private final Schema targetSchema; | ||
|
|
||
| private EvolveSchemaVisitor(UpdateSchema api, Schema existingSchema, Schema targetSchema) { | ||
| private final boolean dropUnusedColumns; | ||
|
|
||
| private EvolveSchemaVisitor( | ||
| TableIdentifier identifier, | ||
| UpdateSchema api, | ||
| Schema existingSchema, | ||
| Schema targetSchema, | ||
| boolean dropUnusedColumns) { | ||
| this.identifier = identifier; | ||
| this.api = api; | ||
| this.existingSchema = existingSchema; | ||
| this.targetSchema = targetSchema; | ||
| this.dropUnusedColumns = dropUnusedColumns; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -70,12 +82,18 @@ private EvolveSchemaVisitor(UpdateSchema api, Schema existingSchema, Schema targ | |
| * @param api an UpdateSchema for adding changes | ||
| * @param existingSchema an existing schema | ||
| * @param targetSchema a new schema to compare with the existing | ||
| * @param dropUnusedColumns whether to drop columns not present in target schema | ||
| */ | ||
| public static void visit(UpdateSchema api, Schema existingSchema, Schema targetSchema) { | ||
| public static void visit( | ||
| TableIdentifier identifier, | ||
| UpdateSchema api, | ||
| Schema existingSchema, | ||
| Schema targetSchema, | ||
| boolean dropUnusedColumns) { | ||
| visit( | ||
| targetSchema, | ||
| -1, | ||
| new EvolveSchemaVisitor(api, existingSchema, targetSchema), | ||
| new EvolveSchemaVisitor(identifier, api, existingSchema, targetSchema, dropUnusedColumns), | ||
| new CompareSchemasVisitor.PartnerIdByNameAccessors(existingSchema)); | ||
| } | ||
|
|
||
|
|
@@ -103,11 +121,16 @@ public Boolean struct(Types.StructType struct, Integer partnerId, List<Boolean> | |
| after = columnName; | ||
| } | ||
|
|
||
| // Ensure that unused fields are made optional | ||
| for (Types.NestedField existingField : partnerStruct.fields()) { | ||
| if (struct.field(existingField.name()) == null) { | ||
| if (existingField.isRequired()) { | ||
| this.api.makeColumnOptional(this.existingSchema.findColumnName(existingField.fieldId())); | ||
| String columnName = this.existingSchema.findColumnName(existingField.fieldId()); | ||
| if (dropUnusedColumns) { | ||
| LOG.debug("{}: Dropping column: {}", identifier.name(), columnName); | ||
| this.api.deleteColumn(columnName); | ||
| } else { | ||
| if (existingField.isRequired()) { | ||
| this.api.makeColumnOptional(columnName); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.