diff --git a/paimon-core/src/main/java/org/apache/paimon/rest/RESTCatalog.java b/paimon-core/src/main/java/org/apache/paimon/rest/RESTCatalog.java index b98b0e7078f8..e0b3dccdd56b 100644 --- a/paimon-core/src/main/java/org/apache/paimon/rest/RESTCatalog.java +++ b/paimon-core/src/main/java/org/apache/paimon/rest/RESTCatalog.java @@ -39,6 +39,7 @@ import org.apache.paimon.rest.exceptions.ForbiddenException; import org.apache.paimon.rest.exceptions.NoSuchResourceException; import org.apache.paimon.rest.requests.AlterDatabaseRequest; +import org.apache.paimon.rest.requests.AlterTableRequest; import org.apache.paimon.rest.requests.CreateDatabaseRequest; import org.apache.paimon.rest.requests.CreateTableRequest; import org.apache.paimon.rest.requests.RenameTableRequest; @@ -302,7 +303,13 @@ public void createTable(Identifier identifier, Schema schema, boolean ignoreIfEx public void renameTable(Identifier fromTable, Identifier toTable, boolean ignoreIfNotExists) throws TableNotExistException, TableAlreadyExistException { try { - renameTable(fromTable, toTable); + RenameTableRequest request = new RenameTableRequest(toTable); + client.post( + resourcePaths.renameTable( + fromTable.getDatabaseName(), fromTable.getTableName()), + request, + GetTableResponse.class, + headers()); } catch (NoSuchResourceException e) { if (!ignoreIfNotExists) { throw new TableNotExistException(fromTable); @@ -318,7 +325,20 @@ public void renameTable(Identifier fromTable, Identifier toTable, boolean ignore public void alterTable( Identifier identifier, List changes, boolean ignoreIfNotExists) throws TableNotExistException, ColumnAlreadyExistException, ColumnNotExistException { - throw new UnsupportedOperationException("TODO"); + try { + AlterTableRequest request = new AlterTableRequest(changes); + client.post( + resourcePaths.table(identifier.getDatabaseName(), identifier.getTableName()), + request, + GetTableResponse.class, + headers()); + } catch (NoSuchResourceException e) { + if (!ignoreIfNotExists) { + throw new TableNotExistException(identifier); + } + } catch (ForbiddenException e) { + throw new TableNoPermissionException(identifier, e); + } } @Override @@ -376,16 +396,6 @@ Map fetchOptionsFromServer( return response.merge(clientProperties); } - @VisibleForTesting - void renameTable(Identifier fromTable, Identifier newIdentifier) { - RenameTableRequest request = new RenameTableRequest(newIdentifier); - client.post( - resourcePaths.table(fromTable.getDatabaseName(), fromTable.getTableName()), - request, - GetTableResponse.class, - headers()); - } - @VisibleForTesting Table getDataOrFormatTable(Identifier identifier) throws TableNotExistException { Preconditions.checkArgument(identifier.getSystemTableName() == null); diff --git a/paimon-core/src/main/java/org/apache/paimon/rest/ResourcePaths.java b/paimon-core/src/main/java/org/apache/paimon/rest/ResourcePaths.java index 567dfea49046..f006713fe2b6 100644 --- a/paimon-core/src/main/java/org/apache/paimon/rest/ResourcePaths.java +++ b/paimon-core/src/main/java/org/apache/paimon/rest/ResourcePaths.java @@ -71,4 +71,15 @@ public String table(String databaseName, String tableName) { .add(tableName) .toString(); } + + public String renameTable(String databaseName, String tableName) { + return SLASH.add("v1") + .add(prefix) + .add("databases") + .add(databaseName) + .add("tables") + .add(tableName) + .add("rename") + .toString(); + } } diff --git a/paimon-core/src/main/java/org/apache/paimon/rest/requests/AlterTableRequest.java b/paimon-core/src/main/java/org/apache/paimon/rest/requests/AlterTableRequest.java new file mode 100644 index 000000000000..32ec62c5eea5 --- /dev/null +++ b/paimon-core/src/main/java/org/apache/paimon/rest/requests/AlterTableRequest.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.paimon.rest.requests; + +import org.apache.paimon.rest.RESTRequest; +import org.apache.paimon.schema.SchemaChange; + +import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonCreator; +import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonGetter; +import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** Request for altering table. */ +@JsonIgnoreProperties(ignoreUnknown = true) +public class AlterTableRequest implements RESTRequest { + + private static final String FIELD_NEW_UPDATE = "changes"; + + @JsonProperty(FIELD_NEW_UPDATE) + private final List changes; + + @JsonCreator + public AlterTableRequest(@JsonProperty(FIELD_NEW_UPDATE) List changes) { + this.changes = changes; + } + + @JsonGetter(FIELD_NEW_UPDATE) + public List getChanges() { + return changes; + } +} diff --git a/paimon-core/src/main/java/org/apache/paimon/schema/SchemaChange.java b/paimon-core/src/main/java/org/apache/paimon/schema/SchemaChange.java index 5f6b10457541..90bc9abc0aae 100644 --- a/paimon-core/src/main/java/org/apache/paimon/schema/SchemaChange.java +++ b/paimon-core/src/main/java/org/apache/paimon/schema/SchemaChange.java @@ -25,6 +25,8 @@ import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonGetter; import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonIgnoreProperties; import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonSubTypes; +import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.annotation.JsonTypeInfo; import javax.annotation.Nullable; @@ -38,6 +40,42 @@ * @since 0.4.0 */ @Public +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.PROPERTY, + property = SchemaChange.Actions.FIELD_ACTION) +@JsonSubTypes({ + @JsonSubTypes.Type( + value = SchemaChange.SetOption.class, + name = SchemaChange.Actions.SET_OPTION_ACTION), + @JsonSubTypes.Type( + value = SchemaChange.RemoveOption.class, + name = SchemaChange.Actions.REMOVE_OPTION_ACTION), + @JsonSubTypes.Type( + value = SchemaChange.UpdateComment.class, + name = SchemaChange.Actions.UPDATE_COMMENT_ACTION), + @JsonSubTypes.Type( + value = SchemaChange.AddColumn.class, + name = SchemaChange.Actions.ADD_COLUMN_ACTION), + @JsonSubTypes.Type( + value = SchemaChange.RenameColumn.class, + name = SchemaChange.Actions.RENAME_COLUMN_ACTION), + @JsonSubTypes.Type( + value = SchemaChange.DropColumn.class, + name = SchemaChange.Actions.DROP_COLUMN_ACTION), + @JsonSubTypes.Type( + value = SchemaChange.UpdateColumnType.class, + name = SchemaChange.Actions.UPDATE_COLUMN_TYPE_ACTION), + @JsonSubTypes.Type( + value = SchemaChange.UpdateColumnNullability.class, + name = SchemaChange.Actions.UPDATE_COLUMN_NULLABILITY_ACTION), + @JsonSubTypes.Type( + value = SchemaChange.UpdateColumnComment.class, + name = SchemaChange.Actions.UPDATE_COLUMN_COMMENT_ACTION), + @JsonSubTypes.Type( + value = SchemaChange.UpdateColumnPosition.class, + name = SchemaChange.Actions.UPDATE_COLUMN_POSITION_ACTION), +}) public interface SchemaChange extends Serializable { static SchemaChange setOption(String key, String value) { @@ -124,18 +162,28 @@ final class SetOption implements SchemaChange { private static final long serialVersionUID = 1L; + private static final String FIELD_KEY = "key"; + private static final String FIELD_VALUE = "value"; + + @JsonProperty(FIELD_KEY) private final String key; + + @JsonProperty(FIELD_VALUE) private final String value; - private SetOption(String key, String value) { + @JsonCreator + private SetOption( + @JsonProperty(FIELD_KEY) String key, @JsonProperty(FIELD_VALUE) String value) { this.key = key; this.value = value; } + @JsonGetter(FIELD_KEY) public String key() { return key; } + @JsonGetter(FIELD_VALUE) public String value() { return value; } @@ -163,12 +211,16 @@ final class RemoveOption implements SchemaChange { private static final long serialVersionUID = 1L; + private static final String FIELD_KEY = "key"; + + @JsonProperty(FIELD_KEY) private final String key; - private RemoveOption(String key) { + private RemoveOption(@JsonProperty(FIELD_KEY) String key) { this.key = key; } + @JsonGetter(FIELD_KEY) public String key() { return key; } @@ -196,13 +248,17 @@ final class UpdateComment implements SchemaChange { private static final long serialVersionUID = 1L; + private static final String FIELD_COMMENT = "comment"; + // If comment is null, means to remove comment + @JsonProperty(FIELD_COMMENT) private final @Nullable String comment; - private UpdateComment(@Nullable String comment) { + private UpdateComment(@JsonProperty(FIELD_COMMENT) @Nullable String comment) { this.comment = comment; } + @JsonGetter(FIELD_COMMENT) public @Nullable String comment() { return comment; } @@ -467,13 +523,17 @@ public int hashCode() { final class UpdateColumnPosition implements SchemaChange { private static final long serialVersionUID = 1L; + private static final String FIELD_MOVE = "move"; + @JsonProperty(FIELD_MOVE) private final Move move; - private UpdateColumnPosition(Move move) { + @JsonCreator + private UpdateColumnPosition(@JsonProperty(FIELD_MOVE) Move move) { this.move = move; } + @JsonGetter(FIELD_MOVE) public Move move() { return move; } @@ -525,11 +585,11 @@ public static Move last(String fieldName) { private static final long serialVersionUID = 1L; - private static final String FIELD_FILED_NAMES = "fieldName"; + private static final String FIELD_FILED_NAME = "fieldName"; private static final String FIELD_REFERENCE_FIELD_NAME = "referenceFieldName"; private static final String FIELD_TYPE = "type"; - @JsonProperty(FIELD_FILED_NAMES) + @JsonProperty(FIELD_FILED_NAME) private final String fieldName; @JsonProperty(FIELD_REFERENCE_FIELD_NAME) @@ -540,7 +600,7 @@ public static Move last(String fieldName) { @JsonCreator public Move( - @JsonProperty(FIELD_FILED_NAMES) String fieldName, + @JsonProperty(FIELD_FILED_NAME) String fieldName, @JsonProperty(FIELD_REFERENCE_FIELD_NAME) String referenceFieldName, @JsonProperty(FIELD_TYPE) MoveType type) { this.fieldName = fieldName; @@ -548,7 +608,7 @@ public Move( this.type = type; } - @JsonGetter(FIELD_FILED_NAMES) + @JsonGetter(FIELD_FILED_NAME) public String fieldName() { return fieldName; } @@ -690,4 +750,21 @@ public int hashCode() { return result; } } + + /** Actions for schema changes: identify for schema change. */ + class Actions { + public static final String FIELD_ACTION = "action"; + public static final String SET_OPTION_ACTION = "setOption"; + public static final String REMOVE_OPTION_ACTION = "removeOption"; + public static final String UPDATE_COMMENT_ACTION = "updateComment"; + public static final String ADD_COLUMN_ACTION = "addColumn"; + public static final String RENAME_COLUMN_ACTION = "renameColumn"; + public static final String DROP_COLUMN_ACTION = "dropColumn"; + public static final String UPDATE_COLUMN_TYPE_ACTION = "updateColumnType"; + public static final String UPDATE_COLUMN_NULLABILITY_ACTION = "updateColumnNullability"; + public static final String UPDATE_COLUMN_COMMENT_ACTION = "updateColumnComment"; + public static final String UPDATE_COLUMN_POSITION_ACTION = "updateColumnPosition"; + + private Actions() {} + } } diff --git a/paimon-core/src/test/java/org/apache/paimon/rest/MockRESTMessage.java b/paimon-core/src/test/java/org/apache/paimon/rest/MockRESTMessage.java index 6a9f2df7516c..96d0c9d7c724 100644 --- a/paimon-core/src/test/java/org/apache/paimon/rest/MockRESTMessage.java +++ b/paimon-core/src/test/java/org/apache/paimon/rest/MockRESTMessage.java @@ -20,6 +20,7 @@ import org.apache.paimon.catalog.Identifier; import org.apache.paimon.rest.requests.AlterDatabaseRequest; +import org.apache.paimon.rest.requests.AlterTableRequest; import org.apache.paimon.rest.requests.CreateDatabaseRequest; import org.apache.paimon.rest.requests.CreateTableRequest; import org.apache.paimon.rest.requests.RenameTableRequest; @@ -126,11 +127,17 @@ public static RenameTableRequest renameRequest(String toTableName) { return new RenameTableRequest(newIdentifier); } + public static AlterTableRequest alterTableRequest() { + return new AlterTableRequest(getChanges()); + } + public static List getChanges() { // add option SchemaChange addOption = SchemaChange.setOption("snapshot.time-retained", "2h"); // remove option SchemaChange removeOption = SchemaChange.removeOption("compaction.max.file-num"); + // update comment + SchemaChange updateComment = SchemaChange.updateComment(null); // add column SchemaChange addColumn = SchemaChange.addColumn("col1_after", DataTypes.ARRAY(DataTypes.STRING())); @@ -179,6 +186,7 @@ public static List getChanges() { List schemaChanges = new ArrayList<>(); schemaChanges.add(addOption); schemaChanges.add(removeOption); + schemaChanges.add(updateComment); schemaChanges.add(addColumn); schemaChanges.add(addColumnMap); schemaChanges.add(addColumnRowType); diff --git a/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogTest.java b/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogTest.java index 95a991a74a68..01555adc3df4 100644 --- a/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogTest.java +++ b/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogTest.java @@ -32,6 +32,7 @@ import org.apache.paimon.rest.responses.GetTableResponse; import org.apache.paimon.rest.responses.ListDatabasesResponse; import org.apache.paimon.rest.responses.ListTablesResponse; +import org.apache.paimon.schema.SchemaChange; import org.apache.paimon.table.Table; import org.apache.paimon.shade.jackson2.com.fasterxml.jackson.core.JsonProcessingException; @@ -55,6 +56,8 @@ import static org.junit.Assert.assertThrows; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; @@ -279,7 +282,7 @@ public void testRenameTable() throws Exception { Identifier.create(databaseName, fromTableName), Identifier.create(databaseName, toTableName), true)); - verify(mockRestCatalog, times(1)).renameTable(any(), any()); + verify(mockRestCatalog, times(1)).renameTable(any(), any(), anyBoolean()); } @Test @@ -312,6 +315,31 @@ public void testRenameTableWhenToTableAlreadyExist() throws Exception { false)); } + @Test + public void testAlterTable() throws Exception { + String databaseName = MockRESTMessage.databaseName(); + List changes = MockRESTMessage.getChanges(); + GetTableResponse response = MockRESTMessage.getTableResponse(); + mockResponse(mapper.writeValueAsString(response), 200); + assertDoesNotThrow( + () -> + mockRestCatalog.alterTable( + Identifier.create(databaseName, "t1"), changes, true)); + verify(mockRestCatalog, times(1)).alterTable(any(), anyList(), anyBoolean()); + } + + @Test + public void testAlterTableWhenTableNotExistAndIgnoreIfNotExistsIsFalse() throws Exception { + String databaseName = MockRESTMessage.databaseName(); + List changes = MockRESTMessage.getChanges(); + mockResponse("", 404); + assertThrows( + Catalog.TableNotExistException.class, + () -> + mockRestCatalog.alterTable( + Identifier.create(databaseName, "t1"), changes, false)); + } + @Test public void testDropTable() throws Exception { String databaseName = MockRESTMessage.databaseName(); diff --git a/paimon-core/src/test/java/org/apache/paimon/rest/RESTObjectMapperTest.java b/paimon-core/src/test/java/org/apache/paimon/rest/RESTObjectMapperTest.java index c2d67fd46e1e..26b3db615d11 100644 --- a/paimon-core/src/test/java/org/apache/paimon/rest/RESTObjectMapperTest.java +++ b/paimon-core/src/test/java/org/apache/paimon/rest/RESTObjectMapperTest.java @@ -19,6 +19,7 @@ package org.apache.paimon.rest; import org.apache.paimon.rest.requests.AlterDatabaseRequest; +import org.apache.paimon.rest.requests.AlterTableRequest; import org.apache.paimon.rest.requests.CreateDatabaseRequest; import org.apache.paimon.rest.requests.CreateTableRequest; import org.apache.paimon.rest.requests.RenameTableRequest; @@ -184,4 +185,12 @@ public void listTablesResponseParseTest() throws Exception { ListTablesResponse parseData = mapper.readValue(responseStr, ListTablesResponse.class); assertEquals(response.getTables(), parseData.getTables()); } + + @Test + public void alterTableRequestParseTest() throws Exception { + AlterTableRequest request = MockRESTMessage.alterTableRequest(); + String requestStr = mapper.writeValueAsString(request); + AlterTableRequest parseData = mapper.readValue(requestStr, AlterTableRequest.class); + assertEquals(parseData.getChanges().size(), parseData.getChanges().size()); + } } diff --git a/paimon-open-api/rest-catalog-open-api.yaml b/paimon-open-api/rest-catalog-open-api.yaml index de0faeeb4a09..7fefd0254b1b 100644 --- a/paimon-open-api/rest-catalog-open-api.yaml +++ b/paimon-open-api/rest-catalog-open-api.yaml @@ -176,8 +176,8 @@ paths: post: tags: - table - summary: Rename table - operationId: renameTable + summary: Alter table + operationId: alterTable parameters: - name: prefix in: path @@ -198,7 +198,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RenameTableRequest' + $ref: '#/components/schemas/AlterTableRequest' responses: "200": description: OK @@ -206,6 +206,18 @@ paths: application/json: schema: $ref: '#/components/schemas/GetTableResponse' + "404": + description: Resource not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + "409": + description: Resource has exist + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' "500": description: Internal Server Error delete: @@ -233,6 +245,54 @@ paths: $ref: '#/components/schemas/ErrorResponse' "500": description: Internal Server Error + /v1/{prefix}/databases/{database}/tables/{table}/rename: + post: + tags: + - table + summary: Rename table + operationId: renameTable + parameters: + - name: prefix + in: path + required: true + schema: + type: string + - name: database + in: path + required: true + schema: + type: string + - name: table + in: path + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/RenameTableRequest' + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/GetTableResponse' + "404": + description: Resource not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + "409": + description: Resource has exist + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + "500": + description: Internal Server Error /v1/{prefix}/databases/{database}/properties: post: tags: @@ -394,9 +454,53 @@ components: description: type: string DataType: - anyOf: - - type: string - - type: object + oneOf: + - $ref: '#/components/schemas/PrimitiveType' + - $ref: '#/components/schemas/ArrayType' + - $ref: '#/components/schemas/MultisetType' + - $ref: '#/components/schemas/MapType' + - $ref: '#/components/schemas/RowType' + PrimitiveType: + type: string + ArrayType: + type: object + properties: + type: + type: string + pattern: ^ARRAY.* + element: + type: + $ref: '#/components/schemas/DataType' + MultisetType: + type: object + properties: + type: + type: string + pattern: ^MULTISET.* + element: + type: + $ref: '#/components/schemas/DataType' + MapType: + type: object + properties: + type: + type: string + pattern: ^MAP.* + key: + type: + $ref: '#/components/schemas/DataType' + value: + type: + $ref: '#/components/schemas/DataType' + RowType: + type: object + properties: + type: + type: string + pattern: ^ROW.* + fields: + type: + $ref: '#/components/schemas/DataField' Identifier: type: object properties: @@ -437,6 +541,144 @@ components: format: int64 schema: $ref: '#/components/schemas/Schema' + AlterTableRequest: + type: object + properties: + changes: + type: array + items: + $ref: '#/components/schemas/SchemaChange' + SchemaChange: + anyOf: + - $ref: '#/components/schemas/SetOption' + - $ref: '#/components/schemas/RemoveOption' + - $ref: '#/components/schemas/UpdateComment' + - $ref: '#/components/schemas/AddColumn' + - $ref: '#/components/schemas/RenameColumn' + - $ref: '#/components/schemas/DropColumn' + - $ref: '#/components/schemas/UpdateColumnComment' + - $ref: '#/components/schemas/UpdateColumnType' + - $ref: '#/components/schemas/UpdateColumnPosition' + - $ref: '#/components/schemas/UpdateColumnNullability' + SetOption: + type: object + properties: + action: + type: string + enum: ["setOption"] + key: + type: string + value: + type: string + RemoveOption: + type: object + properties: + action: + type: string + enum: ["removeOption"] + key: + type: string + UpdateComment: + type: object + properties: + action: + type: string + enum: ["updateComment"] + comment: + type: string + AddColumn: + type: object + properties: + action: + type: string + enum: ["addColumn"] + fieldNames: + type: array + items: + type: string + dataType: + $ref: '#/components/schemas/DataType' + comment: + type: string + move: + $ref: '#/components/schemas/Move' + RenameColumn: + type: object + properties: + action: + type: string + enum: ["renameColumn"] + fieldNames: + type: array + items: + type: string + newName: + type: string + DropColumn: + type: object + properties: + action: + type: string + enum: ["dropColumn"] + fieldNames: + type: array + items: + type: string + UpdateColumnComment: + type: object + properties: + action: + type: string + enum: [ "updateColumnComment" ] + fieldNames: + type: array + items: + type: string + newComment: + type: string + UpdateColumnType: + type: object + properties: + action: + type: string + enum: [ "updateColumnType" ] + fieldNames: + type: array + items: + type: string + newDataType: + $ref: '#/components/schemas/DataType' + keepNullability: + type: boolean + UpdateColumnPosition: + type: object + properties: + action: + type: string + enum: [ "updateColumnPosition" ] + move: + $ref: '#/components/schemas/Move' + UpdateColumnNullability: + type: object + properties: + action: + type: string + enum: [ "update_column_nullability" ] + fieldNames: + type: array + items: + type: string + newNullability: + type: boolean + Move: + type: object + properties: + fieldName: + type: string + referenceFieldName: + type: string + type: + type: string RenameTableRequest: type: object properties: diff --git a/paimon-open-api/src/main/java/org/apache/paimon/open/api/RESTCatalogController.java b/paimon-open-api/src/main/java/org/apache/paimon/open/api/RESTCatalogController.java index 3ea8faee8c52..179c23ce46f8 100644 --- a/paimon-open-api/src/main/java/org/apache/paimon/open/api/RESTCatalogController.java +++ b/paimon-open-api/src/main/java/org/apache/paimon/open/api/RESTCatalogController.java @@ -20,6 +20,7 @@ import org.apache.paimon.rest.ResourcePaths; import org.apache.paimon.rest.requests.AlterDatabaseRequest; +import org.apache.paimon.rest.requests.AlterTableRequest; import org.apache.paimon.rest.requests.CreateDatabaseRequest; import org.apache.paimon.rest.requests.CreateTableRequest; import org.apache.paimon.rest.requests.RenameTableRequest; @@ -104,11 +105,7 @@ public ListDatabasesResponse listDatabases(@PathVariable String prefix) { @ApiResponse( responseCode = "409", description = "Resource has exist", - content = { - @Content( - schema = @Schema(implementation = ErrorResponse.class), - mediaType = "application/json") - }), + content = {@Content(schema = @Schema(implementation = ErrorResponse.class))}), @ApiResponse( responseCode = "500", content = {@Content(schema = @Schema())}) @@ -170,6 +167,10 @@ public void dropDatabase(@PathVariable String prefix, @PathVariable String datab responseCode = "404", description = "Resource not found", content = {@Content(schema = @Schema(implementation = ErrorResponse.class))}), + @ApiResponse( + responseCode = "409", + description = "Resource has exist", + content = {@Content(schema = @Schema(implementation = ErrorResponse.class))}), @ApiResponse( responseCode = "500", content = {@Content(schema = @Schema())}) @@ -213,6 +214,10 @@ public ListTablesResponse listTables( responseCode = "404", description = "Resource not found", content = {@Content(schema = @Schema(implementation = ErrorResponse.class))}), + @ApiResponse( + responseCode = "409", + description = "Resource has exist", + content = {@Content(schema = @Schema(implementation = ErrorResponse.class))}), @ApiResponse( responseCode = "500", content = {@Content(schema = @Schema())}) @@ -261,22 +266,26 @@ public GetTableResponse createTable( } @Operation( - summary = "Update table", + summary = "Alter table", tags = {"table"}) @ApiResponses({ @ApiResponse( responseCode = "200", content = {@Content(schema = @Schema(implementation = GetTableResponse.class))}), + @ApiResponse( + responseCode = "404", + description = "Resource not found", + content = {@Content(schema = @Schema(implementation = ErrorResponse.class))}), @ApiResponse( responseCode = "500", content = {@Content(schema = @Schema())}) }) @PostMapping("/v1/{prefix}/databases/{database}/tables/{table}") - public GetTableResponse renameTable( + public GetTableResponse alterTable( @PathVariable String prefix, @PathVariable String database, @PathVariable String table, - @RequestBody RenameTableRequest request) { + @RequestBody AlterTableRequest request) { return new GetTableResponse( "", 1, @@ -305,4 +314,36 @@ public void dropTable( @PathVariable String prefix, @PathVariable String database, @PathVariable String table) {} + + @Operation( + summary = "Rename table", + tags = {"table"}) + @ApiResponses({ + @ApiResponse( + responseCode = "200", + content = {@Content(schema = @Schema(implementation = GetTableResponse.class))}), + @ApiResponse( + responseCode = "404", + description = "Resource not found", + content = {@Content(schema = @Schema(implementation = ErrorResponse.class))}), + @ApiResponse( + responseCode = "500", + content = {@Content(schema = @Schema())}) + }) + @PostMapping("/v1/{prefix}/databases/{database}/tables/{table}/rename") + public GetTableResponse renameTable( + @PathVariable String prefix, + @PathVariable String database, + @PathVariable String table, + @RequestBody RenameTableRequest request) { + return new GetTableResponse( + "", + 1, + new org.apache.paimon.schema.Schema( + ImmutableList.of(), + ImmutableList.of(), + ImmutableList.of(), + new HashMap<>(), + "comment")); + } }