public static Schema applySchemaChangeEvent(Schema schema, SchemaChangeEvent event) {
        return SchemaChangeEventVisitor.visit(
                event,
                addColumnEvent -> applyAddColumnEvent(addColumnEvent, schema),
                alterColumnTypeEvent -> applyAlterColumnTypeEvent(alterColumnTypeEvent, schema),
                createTableEvent -> createTableEvent.getSchema(),
                dropColumnEvent -> applyDropColumnEvent(dropColumnEvent, schema),
                dropTableEvent -> schema,
                renameColumnEvent -> applyRenameColumnEvent(renameColumnEvent, schema),
                truncateTableEvent -> schema);
    }
@Test
    public void testApplyColumnSchemaChangeEvent() {
        TableId tableId = TableId.parse("default.default.table1");
        Schema schema =
                Schema.newBuilder()
                        .physicalColumn("col1", DataTypes.STRING())
                        .physicalColumn("col2", DataTypes.STRING())
                        .build();

        // add column in last position
        List<AddColumnEvent.ColumnWithPosition> addedColumns = new ArrayList<>();
        addedColumns.add(
                new AddColumnEvent.ColumnWithPosition(
                        Column.physicalColumn("col3", DataTypes.STRING())));
        AddColumnEvent addColumnEvent = new AddColumnEvent(tableId, addedColumns);
        schema = SchemaUtils.applySchemaChangeEvent(schema, addColumnEvent);
        Assertions.assertThat(schema)
                .isEqualTo(
                        Schema.newBuilder()
                                .physicalColumn("col1", DataTypes.STRING())
                                .physicalColumn("col2", DataTypes.STRING())
                                .physicalColumn("col3", DataTypes.STRING())
                                .build());

        // add new column before existed column
        addedColumns = new ArrayList<>();
        addedColumns.add(
                new AddColumnEvent.ColumnWithPosition(
                        Column.physicalColumn("col4", DataTypes.STRING()),
                        AddColumnEvent.ColumnPosition.BEFORE,
                        "col3"));
        addColumnEvent = new AddColumnEvent(tableId, addedColumns);
        schema = SchemaUtils.applySchemaChangeEvent(schema, addColumnEvent);
        Assertions.assertThat(schema)
                .isEqualTo(
                        Schema.newBuilder()
                                .physicalColumn("col1", DataTypes.STRING())
                                .physicalColumn("col2", DataTypes.STRING())
                                .physicalColumn("col4", DataTypes.STRING())
                                .physicalColumn("col3", DataTypes.STRING())
                                .build());

        // add new column after existed column
        addedColumns = new ArrayList<>();
        addedColumns.add(
                new AddColumnEvent.ColumnWithPosition(
                        Column.physicalColumn("col5", DataTypes.STRING()),
                        AddColumnEvent.ColumnPosition.AFTER,
                        "col4"));
        addColumnEvent = new AddColumnEvent(tableId, addedColumns);
        schema = SchemaUtils.applySchemaChangeEvent(schema, addColumnEvent);
        Assertions.assertThat(schema)
                .isEqualTo(
                        Schema.newBuilder()
                                .physicalColumn("col1", DataTypes.STRING())
                                .physicalColumn("col2", DataTypes.STRING())
                                .physicalColumn("col4", DataTypes.STRING())
                                .physicalColumn("col5", DataTypes.STRING())
                                .physicalColumn("col3", DataTypes.STRING())
                                .build());

        // add column in first position
        addedColumns = new ArrayList<>();
        addedColumns.add(
                new AddColumnEvent.ColumnWithPosition(
                        Column.physicalColumn("col0", DataTypes.STRING()),
                        AddColumnEvent.ColumnPosition.FIRST,
                        null));
        addColumnEvent = new AddColumnEvent(tableId, addedColumns);
        schema = SchemaUtils.applySchemaChangeEvent(schema, addColumnEvent);
        Assertions.assertThat(schema)
                .isEqualTo(
                        Schema.newBuilder()
                                .physicalColumn("col0", DataTypes.STRING())
                                .physicalColumn("col1", DataTypes.STRING())
                                .physicalColumn("col2", DataTypes.STRING())
                                .physicalColumn("col4", DataTypes.STRING())
                                .physicalColumn("col5", DataTypes.STRING())
                                .physicalColumn("col3", DataTypes.STRING())
                                .build());

        // drop columns
        DropColumnEvent dropColumnEvent =
                new DropColumnEvent(tableId, Arrays.asList("col3", "col5"));
        schema = SchemaUtils.applySchemaChangeEvent(schema, dropColumnEvent);
        Assertions.assertThat(schema)
                .isEqualTo(
                        Schema.newBuilder()
                                .physicalColumn("col0", DataTypes.STRING())
                                .physicalColumn("col1", DataTypes.STRING())
                                .physicalColumn("col2", DataTypes.STRING())
                                .physicalColumn("col4", DataTypes.STRING())
                                .build());

        // rename columns
        Map<String, String> nameMapping = new HashMap<>();
        nameMapping.put("col2", "newCol2");
        nameMapping.put("col4", "newCol4");
        RenameColumnEvent renameColumnEvent = new RenameColumnEvent(tableId, nameMapping);
        schema = SchemaUtils.applySchemaChangeEvent(schema, renameColumnEvent);
        Assertions.assertThat(schema)
                .isEqualTo(
                        Schema.newBuilder()
                                .physicalColumn("col0", DataTypes.STRING())
                                .physicalColumn("col1", DataTypes.STRING())
                                .physicalColumn("newCol2", DataTypes.STRING())
                                .physicalColumn("newCol4", DataTypes.STRING())
                                .build());

        // alter column types
        Map<String, DataType> typeMapping = new HashMap<>();
        typeMapping.put("newCol2", DataTypes.VARCHAR(10));
        typeMapping.put("newCol4", DataTypes.VARCHAR(10));
        AlterColumnTypeEvent alterColumnTypeEvent = new AlterColumnTypeEvent(tableId, typeMapping);
        schema = SchemaUtils.applySchemaChangeEvent(schema, alterColumnTypeEvent);
        Assertions.assertThat(schema)
                .isEqualTo(
                        Schema.newBuilder()
                                .physicalColumn("col0", DataTypes.STRING())
                                .physicalColumn("col1", DataTypes.STRING())
                                .physicalColumn("newCol2", DataTypes.VARCHAR(10))
                                .physicalColumn("newCol4", DataTypes.VARCHAR(10))
                                .build());
    }