3434import org .apache .paimon .flink .LogicalTypeConversion ;
3535import org .apache .paimon .options .Options ;
3636import org .apache .paimon .schema .SchemaChange ;
37+ import org .apache .paimon .table .Table ;
3738
3839import java .util .ArrayList ;
3940import java .util .HashMap ;
4041import java .util .List ;
4142import java .util .Map ;
4243
44+ import static org .apache .flink .cdc .common .utils .Preconditions .checkArgument ;
45+ import static org .apache .flink .cdc .common .utils .Preconditions .checkNotNull ;
46+
4347/**
4448 * A {@code MetadataApplier} that applies metadata changes to Paimon. Support primary key table
4549 * only.
@@ -129,35 +133,90 @@ private void applyCreateTable(CreateTableEvent event)
129133 private void applyAddColumn (AddColumnEvent event )
130134 throws Catalog .TableNotExistException , Catalog .ColumnAlreadyExistException ,
131135 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 );
145137 catalog .alterTable (
146138 new Identifier (event .tableId ().getSchemaName (), event .tableId ().getTableName ()),
147139 tableChangeList ,
148140 true );
149141 }
150142
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+ SchemaChangeProvider .add (
152+ columnWithPosition ,
153+ SchemaChange .Move .first (
154+ columnWithPosition .getAddColumn ().getName ()));
155+ tableChangeList .add (tableChange );
156+ break ;
157+ case LAST :
158+ SchemaChange schemaChangeWithLastPosition =
159+ SchemaChangeProvider .add (columnWithPosition );
160+ tableChangeList .add (schemaChangeWithLastPosition );
161+ break ;
162+ case BEFORE :
163+ SchemaChange schemaChangeWithBeforePosition =
164+ applyAddColumnWithBeforePosition (
165+ event .tableId ().getSchemaName (),
166+ event .tableId ().getTableName (),
167+ columnWithPosition );
168+ tableChangeList .add (schemaChangeWithBeforePosition );
169+ break ;
170+ case AFTER :
171+ checkNotNull (
172+ columnWithPosition .getExistedColumnName (),
173+ "Existing column name must be provided for AFTER position" );
174+ SchemaChange .Move after =
175+ SchemaChange .Move .after (
176+ columnWithPosition .getAddColumn ().getName (),
177+ columnWithPosition .getExistedColumnName ());
178+ tableChange = SchemaChangeProvider .add (columnWithPosition , after );
179+ tableChangeList .add (tableChange );
180+ break ;
181+ default :
182+ throw new IllegalArgumentException (
183+ "Unknown column position: " + columnWithPosition .getPosition ());
184+ }
185+ }
186+ return tableChangeList ;
187+ }
188+
189+ private SchemaChange applyAddColumnWithBeforePosition (
190+ String schemaName ,
191+ String tableName ,
192+ AddColumnEvent .ColumnWithPosition columnWithPosition )
193+ throws Catalog .TableNotExistException {
194+ String existedColumnName = columnWithPosition .getExistedColumnName ();
195+ Table table = catalog .getTable (new Identifier (schemaName , tableName ));
196+ List <String > columnNames = table .rowType ().getFieldNames ();
197+ int index = checkColumnPosition (existedColumnName , columnNames );
198+ SchemaChange .Move after =
199+ SchemaChange .Move .after (
200+ columnWithPosition .getAddColumn ().getName (), columnNames .get (index - 1 ));
201+
202+ return SchemaChangeProvider .add (columnWithPosition , after );
203+ }
204+
205+ private int checkColumnPosition (String existedColumnName , List <String > columnNames ) {
206+ if (existedColumnName == null ) {
207+ return 0 ;
208+ }
209+ int index = columnNames .indexOf (existedColumnName );
210+ checkArgument (index != -1 , "Column %s not found" , existedColumnName );
211+ return index ;
212+ }
213+
151214 private void applyDropColumn (DropColumnEvent event )
152215 throws Catalog .ColumnAlreadyExistException , Catalog .TableNotExistException ,
153216 Catalog .ColumnNotExistException {
154217 List <SchemaChange > tableChangeList = new ArrayList <>();
155218 event .getDroppedColumnNames ()
156- .forEach (
157- (column ) -> {
158- SchemaChange tableChange = SchemaChange .dropColumn (column );
159- tableChangeList .add (tableChange );
160- });
219+ .forEach ((column ) -> tableChangeList .add (SchemaChangeProvider .drop (column )));
161220 catalog .alterTable (
162221 new Identifier (event .tableId ().getSchemaName (), event .tableId ().getTableName ()),
163222 tableChangeList ,
@@ -170,10 +229,8 @@ private void applyRenameColumn(RenameColumnEvent event)
170229 List <SchemaChange > tableChangeList = new ArrayList <>();
171230 event .getNameMapping ()
172231 .forEach (
173- (oldName , newName ) -> {
174- SchemaChange tableChange = SchemaChange .renameColumn (oldName , newName );
175- tableChangeList .add (tableChange );
176- });
232+ (oldName , newName ) ->
233+ tableChangeList .add (SchemaChangeProvider .rename (oldName , newName )));
177234 catalog .alterTable (
178235 new Identifier (event .tableId ().getSchemaName (), event .tableId ().getTableName ()),
179236 tableChangeList ,
@@ -186,15 +243,9 @@ private void applyAlterColumn(AlterColumnTypeEvent event)
186243 List <SchemaChange > tableChangeList = new ArrayList <>();
187244 event .getTypeMapping ()
188245 .forEach (
189- (oldName , newType ) -> {
190- SchemaChange tableChange =
191- SchemaChange .updateColumnType (
192- oldName ,
193- LogicalTypeConversion .toDataType (
194- DataTypeUtils .toFlinkDataType (newType )
195- .getLogicalType ()));
196- tableChangeList .add (tableChange );
197- });
246+ (oldName , newType ) ->
247+ tableChangeList .add (
248+ SchemaChangeProvider .updateColumnType (oldName , newType )));
198249 catalog .alterTable (
199250 new Identifier (event .tableId ().getSchemaName (), event .tableId ().getTableName ()),
200251 tableChangeList ,
0 commit comments