|
36 | 36 | import org.apache.fluss.metadata.Schema; |
37 | 37 | import org.apache.fluss.metadata.TableBucket; |
38 | 38 | import org.apache.fluss.metadata.TableDescriptor; |
| 39 | +import org.apache.fluss.metadata.TableInfo; |
39 | 40 | import org.apache.fluss.metadata.TablePath; |
40 | 41 | import org.apache.fluss.metrics.registry.MetricRegistry; |
41 | 42 | import org.apache.fluss.rpc.GatewayClientProxy; |
|
49 | 50 | import org.apache.fluss.rpc.messages.ListDatabasesRequest; |
50 | 51 | import org.apache.fluss.rpc.messages.MetadataRequest; |
51 | 52 | import org.apache.fluss.rpc.messages.MetadataResponse; |
| 53 | +import org.apache.fluss.rpc.messages.PbAddColumn; |
52 | 54 | import org.apache.fluss.rpc.messages.PbAlterConfig; |
53 | 55 | import org.apache.fluss.rpc.messages.PbBucketMetadata; |
54 | 56 | import org.apache.fluss.rpc.messages.PbPartitionMetadata; |
|
62 | 64 | import org.apache.fluss.server.zk.data.BucketAssignment; |
63 | 65 | import org.apache.fluss.server.zk.data.TableAssignment; |
64 | 66 | import org.apache.fluss.types.DataTypes; |
| 67 | +import org.apache.fluss.utils.json.DataTypeJsonSerde; |
| 68 | +import org.apache.fluss.utils.json.JsonSerdeUtils; |
65 | 69 |
|
66 | 70 | import org.junit.jupiter.api.BeforeEach; |
67 | 71 | import org.junit.jupiter.api.Test; |
@@ -298,6 +302,7 @@ void testTableManagement(boolean isCoordinatorServer) throws Exception { |
298 | 302 | newAlterTableRequest( |
299 | 303 | tablePath, |
300 | 304 | alterTableProperties(setProperties, resetProperties), |
| 305 | + Collections.emptyList(), |
301 | 306 | false)) |
302 | 307 | .get(); |
303 | 308 | // get the table and check it |
@@ -655,6 +660,48 @@ void testMetadataCompatibility(boolean isCoordinatorServer) throws Exception { |
655 | 660 | FLUSS_CLUSTER_EXTENSION.getTabletServerNodes()); |
656 | 661 | } |
657 | 662 |
|
| 663 | + @Test |
| 664 | + void testSchemaEvolution() throws Exception { |
| 665 | + AdminReadOnlyGateway gateway = getAdminOnlyGateway(true); |
| 666 | + AdminGateway adminGateway = getAdminGateway(); |
| 667 | + |
| 668 | + // create database and table |
| 669 | + String db1 = "db1"; |
| 670 | + String tb1 = "tb1"; |
| 671 | + TablePath tablePath = TablePath.of(db1, tb1); |
| 672 | + adminGateway.createDatabase(newCreateDatabaseRequest(db1, false)).get(); |
| 673 | + TableDescriptor tableDescriptor = newPkTable(); |
| 674 | + adminGateway.createTable(newCreateTableRequest(tablePath, tableDescriptor, false)).get(); |
| 675 | + |
| 676 | + // add column |
| 677 | + adminGateway |
| 678 | + .alterTable( |
| 679 | + newAlterTableRequest( |
| 680 | + tablePath, Collections.emptyList(), alterTableAddColumns(), false)) |
| 681 | + .get(); |
| 682 | + |
| 683 | + // restart coordinatorServer |
| 684 | + FLUSS_CLUSTER_EXTENSION.stopCoordinatorServer(); |
| 685 | + FLUSS_CLUSTER_EXTENSION.startCoordinatorServer(); |
| 686 | + |
| 687 | + // check metadata response |
| 688 | + MetadataResponse metadataResponse = |
| 689 | + gateway.metadata(newMetadataRequest(Collections.singletonList(tablePath))).get(); |
| 690 | + assertThat(metadataResponse.getTableMetadatasCount()).isEqualTo(1); |
| 691 | + PbTableMetadata pbTableMetadata = metadataResponse.getTableMetadataAt(0); |
| 692 | + assertThat(pbTableMetadata.getSchemaId()).isEqualTo(2); |
| 693 | + TableInfo tableInfo = |
| 694 | + TableInfo.of( |
| 695 | + tablePath, |
| 696 | + pbTableMetadata.getTableId(), |
| 697 | + pbTableMetadata.getSchemaId(), |
| 698 | + TableDescriptor.fromJsonBytes(pbTableMetadata.getTableJson()), |
| 699 | + pbTableMetadata.getCreatedTime(), |
| 700 | + pbTableMetadata.getModifiedTime()); |
| 701 | + List<Schema.Column> columns = tableInfo.getSchema().getColumns(); |
| 702 | + assertThat(columns.size()).isEqualTo(3); |
| 703 | + } |
| 704 | + |
658 | 705 | private void checkBucketMetadata(int expectBucketCount, List<PbBucketMetadata> bucketMetadata) { |
659 | 706 | Set<Integer> liveServers = |
660 | 707 | FLUSS_CLUSTER_EXTENSION.getTabletServerNodes().stream() |
@@ -781,6 +828,20 @@ private static List<PbAlterConfig> alterTableProperties( |
781 | 828 | return res; |
782 | 829 | } |
783 | 830 |
|
| 831 | + private static List<PbAddColumn> alterTableAddColumns() { |
| 832 | + List<PbAddColumn> addColumns = new ArrayList<>(); |
| 833 | + PbAddColumn newColumn = new PbAddColumn(); |
| 834 | + newColumn |
| 835 | + .setColumnName("new_column") |
| 836 | + .setDataTypeJson( |
| 837 | + JsonSerdeUtils.writeValueAsBytes( |
| 838 | + DataTypes.STRING(), DataTypeJsonSerde.INSTANCE)) |
| 839 | + .setComment("new_column") |
| 840 | + .setColumnPositionType(0); |
| 841 | + addColumns.add(newColumn); |
| 842 | + return addColumns; |
| 843 | + } |
| 844 | + |
784 | 845 | private static Schema newPkSchema() { |
785 | 846 | return Schema.newBuilder() |
786 | 847 | .column("a", DataTypes.INT()) |
|
0 commit comments