|
34 | 34 | import org.apache.paimon.flink.LogicalTypeConversion; |
35 | 35 | import org.apache.paimon.options.Options; |
36 | 36 | import org.apache.paimon.schema.SchemaChange; |
| 37 | +import org.apache.paimon.table.Table; |
37 | 38 |
|
38 | 39 | import java.util.ArrayList; |
39 | 40 | import java.util.HashMap; |
40 | 41 | import java.util.List; |
41 | 42 | import java.util.Map; |
42 | 43 |
|
| 44 | +import static org.apache.flink.cdc.common.utils.Preconditions.checkArgument; |
| 45 | +import static org.apache.flink.cdc.common.utils.Preconditions.checkNotNull; |
| 46 | + |
43 | 47 | /** |
44 | 48 | * A {@code MetadataApplier} that applies metadata changes to Paimon. Support primary key table |
45 | 49 | * only. |
@@ -129,25 +133,113 @@ private void applyCreateTable(CreateTableEvent event) |
129 | 133 | private void applyAddColumn(AddColumnEvent event) |
130 | 134 | throws Catalog.TableNotExistException, Catalog.ColumnAlreadyExistException, |
131 | 135 | Catalog.ColumnNotExistException { |
132 | | - List<SchemaChange> tableChangeList = new ArrayList<>(); |
133 | | - event.getAddedColumns() |
134 | | - .forEach( |
135 | | - (column) -> { |
136 | | - SchemaChange tableChange = |
137 | | - SchemaChange.addColumn( |
138 | | - column.getAddColumn().getName(), |
139 | | - LogicalTypeConversion.toDataType( |
140 | | - DataTypeUtils.toFlinkDataType( |
141 | | - column.getAddColumn().getType()) |
142 | | - .getLogicalType())); |
143 | | - tableChangeList.add(tableChange); |
144 | | - }); |
| 136 | + List<SchemaChange> tableChangeList = applyAddColumnEventWithPosition(event); |
145 | 137 | catalog.alterTable( |
146 | 138 | new Identifier(event.tableId().getSchemaName(), event.tableId().getTableName()), |
147 | 139 | tableChangeList, |
148 | 140 | true); |
149 | 141 | } |
150 | 142 |
|
| 143 | + private List<SchemaChange> applyAddColumnEventWithPosition(AddColumnEvent event) |
| 144 | + throws Catalog.TableNotExistException { |
| 145 | + List<SchemaChange> tableChangeList = new ArrayList<>(); |
| 146 | + for (AddColumnEvent.ColumnWithPosition columnWithPosition : event.getAddedColumns()) { |
| 147 | + SchemaChange tableChange; |
| 148 | + switch (columnWithPosition.getPosition()) { |
| 149 | + case FIRST: |
| 150 | + tableChange = |
| 151 | + SchemaChange.addColumn( |
| 152 | + columnWithPosition.getAddColumn().getName(), |
| 153 | + LogicalTypeConversion.toDataType( |
| 154 | + DataTypeUtils.toFlinkDataType( |
| 155 | + columnWithPosition |
| 156 | + .getAddColumn() |
| 157 | + .getType()) |
| 158 | + .getLogicalType()), |
| 159 | + columnWithPosition.getAddColumn().getComment(), |
| 160 | + SchemaChange.Move.first( |
| 161 | + columnWithPosition.getAddColumn().getName())); |
| 162 | + tableChangeList.add(tableChange); |
| 163 | + break; |
| 164 | + case LAST: |
| 165 | + SchemaChange schemaChangeWithLastPosition = |
| 166 | + applyAddColumnWithLastPosition(columnWithPosition); |
| 167 | + tableChangeList.add(schemaChangeWithLastPosition); |
| 168 | + break; |
| 169 | + case BEFORE: |
| 170 | + SchemaChange schemaChangeWithBeforePosition = |
| 171 | + applyAddColumnWithBeforePosition( |
| 172 | + event.tableId().getSchemaName(), |
| 173 | + event.tableId().getTableName(), |
| 174 | + columnWithPosition); |
| 175 | + tableChangeList.add(schemaChangeWithBeforePosition); |
| 176 | + break; |
| 177 | + case AFTER: |
| 178 | + checkNotNull( |
| 179 | + columnWithPosition.getExistedColumnName(), |
| 180 | + "Existing column name must be provided for AFTER position"); |
| 181 | + tableChange = |
| 182 | + SchemaChange.addColumn( |
| 183 | + columnWithPosition.getAddColumn().getName(), |
| 184 | + LogicalTypeConversion.toDataType( |
| 185 | + DataTypeUtils.toFlinkDataType( |
| 186 | + columnWithPosition |
| 187 | + .getAddColumn() |
| 188 | + .getType()) |
| 189 | + .getLogicalType()), |
| 190 | + columnWithPosition.getAddColumn().getComment(), |
| 191 | + SchemaChange.Move.after( |
| 192 | + columnWithPosition.getAddColumn().getName(), |
| 193 | + columnWithPosition.getExistedColumnName())); |
| 194 | + tableChangeList.add(tableChange); |
| 195 | + break; |
| 196 | + default: |
| 197 | + throw new IllegalArgumentException( |
| 198 | + "Unknown column position: " + columnWithPosition.getPosition()); |
| 199 | + } |
| 200 | + } |
| 201 | + return tableChangeList; |
| 202 | + } |
| 203 | + |
| 204 | + private SchemaChange applyAddColumnWithLastPosition( |
| 205 | + AddColumnEvent.ColumnWithPosition columnWithPosition) { |
| 206 | + return SchemaChange.addColumn( |
| 207 | + columnWithPosition.getAddColumn().getName(), |
| 208 | + LogicalTypeConversion.toDataType( |
| 209 | + DataTypeUtils.toFlinkDataType(columnWithPosition.getAddColumn().getType()) |
| 210 | + .getLogicalType()), |
| 211 | + columnWithPosition.getAddColumn().getComment()); |
| 212 | + } |
| 213 | + |
| 214 | + private SchemaChange applyAddColumnWithBeforePosition( |
| 215 | + String schemaName, |
| 216 | + String tableName, |
| 217 | + AddColumnEvent.ColumnWithPosition columnWithPosition) |
| 218 | + throws Catalog.TableNotExistException { |
| 219 | + String existedColumnName = columnWithPosition.getExistedColumnName(); |
| 220 | + Table table = catalog.getTable(new Identifier(schemaName, tableName)); |
| 221 | + List<String> columnNames = table.rowType().getFieldNames(); |
| 222 | + int index = checkColumnPosition(existedColumnName, columnNames); |
| 223 | + |
| 224 | + return SchemaChange.addColumn( |
| 225 | + columnWithPosition.getAddColumn().getName(), |
| 226 | + LogicalTypeConversion.toDataType( |
| 227 | + DataTypeUtils.toFlinkDataType(columnWithPosition.getAddColumn().getType()) |
| 228 | + .getLogicalType()), |
| 229 | + columnWithPosition.getAddColumn().getComment(), |
| 230 | + SchemaChange.Move.after( |
| 231 | + columnWithPosition.getAddColumn().getName(), columnNames.get(index - 1))); |
| 232 | + } |
| 233 | + |
| 234 | + private int checkColumnPosition(String existedColumnName, List<String> columnNames) { |
| 235 | + if (existedColumnName == null) { |
| 236 | + return 0; |
| 237 | + } |
| 238 | + int index = columnNames.indexOf(existedColumnName); |
| 239 | + checkArgument(index == -1, "Column %s not found", existedColumnName); |
| 240 | + return index; |
| 241 | + } |
| 242 | + |
151 | 243 | private void applyDropColumn(DropColumnEvent event) |
152 | 244 | throws Catalog.ColumnAlreadyExistException, Catalog.TableNotExistException, |
153 | 245 | Catalog.ColumnNotExistException { |
|
0 commit comments