Skip to content

Commit 8821b04

Browse files
authored
[rest] Optimize partition methods to let rest return table not partitioned (#4979)
1 parent f3e0a0d commit 8821b04

File tree

5 files changed

+103
-76
lines changed

5 files changed

+103
-76
lines changed

paimon-core/src/main/java/org/apache/paimon/rest/DefaultErrorHandler.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@
2323
import org.apache.paimon.rest.exceptions.ForbiddenException;
2424
import org.apache.paimon.rest.exceptions.NoSuchResourceException;
2525
import org.apache.paimon.rest.exceptions.NotAuthorizedException;
26+
import org.apache.paimon.rest.exceptions.NotImplementedException;
2627
import org.apache.paimon.rest.exceptions.RESTException;
2728
import org.apache.paimon.rest.exceptions.ServiceFailureException;
2829
import org.apache.paimon.rest.exceptions.ServiceUnavailableException;
29-
import org.apache.paimon.rest.exceptions.UnsupportedOperationException;
3030
import org.apache.paimon.rest.responses.ErrorResponse;
3131

3232
/** Default error handler. */
@@ -61,7 +61,7 @@ public void accept(ErrorResponse error) {
6161
case 500:
6262
throw new ServiceFailureException("Server error: %s", message);
6363
case 501:
64-
throw new UnsupportedOperationException(message);
64+
throw new NotImplementedException(message);
6565
case 503:
6666
throw new ServiceUnavailableException("Service unavailable: %s", message);
6767
default:

paimon-core/src/main/java/org/apache/paimon/rest/RESTCatalog.java

+55-70
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.apache.paimon.rest.exceptions.BadRequestException;
3737
import org.apache.paimon.rest.exceptions.ForbiddenException;
3838
import org.apache.paimon.rest.exceptions.NoSuchResourceException;
39+
import org.apache.paimon.rest.exceptions.NotImplementedException;
3940
import org.apache.paimon.rest.exceptions.ServiceFailureException;
4041
import org.apache.paimon.rest.requests.AlterDatabaseRequest;
4142
import org.apache.paimon.rest.requests.AlterPartitionsRequest;
@@ -84,7 +85,6 @@
8485
import java.util.Set;
8586
import java.util.concurrent.ScheduledExecutorService;
8687

87-
import static org.apache.paimon.CoreOptions.METASTORE_PARTITIONED_TABLE;
8888
import static org.apache.paimon.CoreOptions.createCommitUser;
8989
import static org.apache.paimon.catalog.CatalogUtils.checkNotBranch;
9090
import static org.apache.paimon.catalog.CatalogUtils.checkNotSystemDatabase;
@@ -392,7 +392,7 @@ public void alterTable(
392392
throw new ColumnAlreadyExistException(identifier, e.resourceName());
393393
} catch (ForbiddenException e) {
394394
throw new TableNoPermissionException(identifier, e);
395-
} catch (org.apache.paimon.rest.exceptions.UnsupportedOperationException e) {
395+
} catch (NotImplementedException e) {
396396
throw new UnsupportedOperationException(e.getMessage());
397397
} catch (ServiceFailureException e) {
398398
throw new IllegalStateException(e.getMessage());
@@ -422,38 +422,35 @@ public void dropTable(Identifier identifier, boolean ignoreIfNotExists)
422422
@Override
423423
public void createPartitions(Identifier identifier, List<Map<String, String>> partitions)
424424
throws TableNotExistException {
425-
Table table = getTable(identifier);
426-
if (isMetaStorePartitionedTable(table)) {
427-
try {
428-
CreatePartitionsRequest request = new CreatePartitionsRequest(partitions);
429-
client.post(
430-
resourcePaths.partitions(
431-
identifier.getDatabaseName(), identifier.getTableName()),
432-
request,
433-
headers());
434-
} catch (NoSuchResourceException e) {
435-
throw new TableNotExistException(identifier);
436-
}
425+
try {
426+
CreatePartitionsRequest request = new CreatePartitionsRequest(partitions);
427+
client.post(
428+
resourcePaths.partitions(
429+
identifier.getDatabaseName(), identifier.getTableName()),
430+
request,
431+
headers());
432+
} catch (NoSuchResourceException e) {
433+
throw new TableNotExistException(identifier);
434+
} catch (NotImplementedException ignored) {
435+
// not a metastore partitioned table
437436
}
438437
}
439438

440439
@Override
441440
public void dropPartitions(Identifier identifier, List<Map<String, String>> partitions)
442441
throws TableNotExistException {
443-
Table table = getTable(identifier);
444-
if (isMetaStorePartitionedTable(table)) {
445-
try {
446-
DropPartitionsRequest request = new DropPartitionsRequest(partitions);
447-
client.post(
448-
resourcePaths.dropPartitions(
449-
identifier.getDatabaseName(), identifier.getTableName()),
450-
request,
451-
headers());
452-
} catch (NoSuchResourceException e) {
453-
throw new TableNotExistException(identifier);
454-
}
455-
} else {
456-
FileStoreTable fileStoreTable = (FileStoreTable) table;
442+
try {
443+
DropPartitionsRequest request = new DropPartitionsRequest(partitions);
444+
client.post(
445+
resourcePaths.dropPartitions(
446+
identifier.getDatabaseName(), identifier.getTableName()),
447+
request,
448+
headers());
449+
} catch (NoSuchResourceException e) {
450+
throw new TableNotExistException(identifier);
451+
} catch (NotImplementedException ignored) {
452+
// not a metastore partitioned table
453+
FileStoreTable fileStoreTable = (FileStoreTable) getTable(identifier);
457454
try (FileStoreCommit commit =
458455
fileStoreTable
459456
.store()
@@ -468,65 +465,58 @@ public void dropPartitions(Identifier identifier, List<Map<String, String>> part
468465
@Override
469466
public void alterPartitions(Identifier identifier, List<Partition> partitions)
470467
throws TableNotExistException {
471-
Table table = getTable(identifier);
472-
if (isMetaStorePartitionedTable(table)) {
473-
try {
474-
AlterPartitionsRequest request = new AlterPartitionsRequest(partitions);
475-
client.post(
476-
resourcePaths.alterPartitions(
477-
identifier.getDatabaseName(), identifier.getTableName()),
478-
request,
479-
headers());
480-
} catch (NoSuchResourceException e) {
481-
throw new TableNotExistException(identifier);
482-
}
468+
try {
469+
AlterPartitionsRequest request = new AlterPartitionsRequest(partitions);
470+
client.post(
471+
resourcePaths.alterPartitions(
472+
identifier.getDatabaseName(), identifier.getTableName()),
473+
request,
474+
headers());
475+
} catch (NoSuchResourceException e) {
476+
throw new TableNotExistException(identifier);
477+
} catch (NotImplementedException ignored) {
478+
// not a metastore partitioned table
483479
}
484480
}
485481

486482
@Override
487483
public void markDonePartitions(Identifier identifier, List<Map<String, String>> partitions)
488484
throws TableNotExistException {
489-
Table table = getTable(identifier);
490-
if (isMetaStorePartitionedTable(table)) {
491-
try {
492-
MarkDonePartitionsRequest request = new MarkDonePartitionsRequest(partitions);
493-
client.post(
494-
resourcePaths.markDonePartitions(
495-
identifier.getDatabaseName(), identifier.getTableName()),
496-
request,
497-
headers());
498-
} catch (NoSuchResourceException e) {
499-
throw new TableNotExistException(identifier);
500-
}
485+
try {
486+
MarkDonePartitionsRequest request = new MarkDonePartitionsRequest(partitions);
487+
client.post(
488+
resourcePaths.markDonePartitions(
489+
identifier.getDatabaseName(), identifier.getTableName()),
490+
request,
491+
headers());
492+
} catch (NoSuchResourceException e) {
493+
throw new TableNotExistException(identifier);
494+
} catch (NotImplementedException ignored) {
495+
// not a metastore partitioned table
501496
}
502497
}
503498

504499
@Override
505500
public List<Partition> listPartitions(Identifier identifier) throws TableNotExistException {
506-
Table table = getTable(identifier);
507-
if (!isMetaStorePartitionedTable(table)) {
508-
return listPartitionsFromFileSystem(table);
509-
}
510-
511-
ListPartitionsResponse response;
512501
try {
513-
response =
502+
ListPartitionsResponse response =
514503
client.get(
515504
resourcePaths.partitions(
516505
identifier.getDatabaseName(), identifier.getTableName()),
517506
ListPartitionsResponse.class,
518507
headers());
508+
if (response == null || response.getPartitions() == null) {
509+
return Collections.emptyList();
510+
}
511+
return response.getPartitions();
519512
} catch (NoSuchResourceException e) {
520513
throw new TableNotExistException(identifier);
521514
} catch (ForbiddenException e) {
522515
throw new TableNoPermissionException(identifier, e);
516+
} catch (NotImplementedException e) {
517+
// not a metastore partitioned table
518+
return listPartitionsFromFileSystem(getTable(identifier));
523519
}
524-
525-
if (response == null || response.getPartitions() == null) {
526-
return Collections.emptyList();
527-
}
528-
529-
return response.getPartitions();
530520
}
531521

532522
@Override
@@ -626,11 +616,6 @@ public void close() throws Exception {
626616
}
627617
}
628618

629-
private boolean isMetaStorePartitionedTable(Table table) {
630-
Options options = Options.fromMap(table.options());
631-
return Boolean.TRUE.equals(options.get(METASTORE_PARTITIONED_TABLE));
632-
}
633-
634619
private Map<String, String> headers() {
635620
return catalogAuth.getHeaders();
636621
}

paimon-core/src/main/java/org/apache/paimon/rest/exceptions/UnsupportedOperationException.java paimon-core/src/main/java/org/apache/paimon/rest/exceptions/NotImplementedException.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818

1919
package org.apache.paimon.rest.exceptions;
2020

21-
/** Exception thrown on HTTP 501 - UnsupportedOperationException. */
22-
public class UnsupportedOperationException extends RESTException {
21+
/** Exception thrown on HTTP 501 - NotImplementedException. */
22+
public class NotImplementedException extends RESTException {
2323

24-
public UnsupportedOperationException(String message, Object... args) {
24+
public NotImplementedException(String message, Object... args) {
2525
super(String.format(message, args));
2626
}
2727
}

paimon-core/src/test/java/org/apache/paimon/rest/DefaultErrorHandlerTest.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.apache.paimon.rest.exceptions.ForbiddenException;
2424
import org.apache.paimon.rest.exceptions.NoSuchResourceException;
2525
import org.apache.paimon.rest.exceptions.NotAuthorizedException;
26+
import org.apache.paimon.rest.exceptions.NotImplementedException;
2627
import org.apache.paimon.rest.exceptions.RESTException;
2728
import org.apache.paimon.rest.exceptions.ServiceFailureException;
2829
import org.apache.paimon.rest.exceptions.ServiceUnavailableException;
@@ -70,7 +71,7 @@ public void testHandleErrorResponse() {
7071
ServiceFailureException.class,
7172
() -> defaultErrorHandler.accept(generateErrorResponse(500)));
7273
assertThrows(
73-
org.apache.paimon.rest.exceptions.UnsupportedOperationException.class,
74+
NotImplementedException.class,
7475
() -> defaultErrorHandler.accept(generateErrorResponse(501)));
7576
assertThrows(
7677
RESTException.class, () -> defaultErrorHandler.accept(generateErrorResponse(502)));

paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogServer.java

+41
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
package org.apache.paimon.rest;
2020

21+
import org.apache.paimon.CoreOptions;
2122
import org.apache.paimon.catalog.Catalog;
2223
import org.apache.paimon.catalog.CatalogContext;
2324
import org.apache.paimon.catalog.Database;
@@ -68,6 +69,7 @@
6869

6970
import java.io.IOException;
7071
import java.util.List;
72+
import java.util.Optional;
7173
import java.util.UUID;
7274

7375
import static org.apache.paimon.rest.RESTObjectMapper.OBJECT_MAPPER;
@@ -178,6 +180,11 @@ public MockResponse dispatch(RecordedRequest request) {
178180
if (isDropPartitions) {
179181
String tableName = resources[2];
180182
Identifier identifier = Identifier.create(databaseName, tableName);
183+
Optional<MockResponse> error =
184+
checkTablePartitioned(catalog, identifier);
185+
if (error.isPresent()) {
186+
return error.get();
187+
}
181188
DropPartitionsRequest dropPartitionsRequest =
182189
OBJECT_MAPPER.readValue(
183190
request.getBody().readUtf8(),
@@ -188,6 +195,11 @@ public MockResponse dispatch(RecordedRequest request) {
188195
} else if (isAlterPartitions) {
189196
String tableName = resources[2];
190197
Identifier identifier = Identifier.create(databaseName, tableName);
198+
Optional<MockResponse> error =
199+
checkTablePartitioned(catalog, identifier);
200+
if (error.isPresent()) {
201+
return error.get();
202+
}
191203
AlterPartitionsRequest alterPartitionsRequest =
192204
OBJECT_MAPPER.readValue(
193205
request.getBody().readUtf8(),
@@ -198,6 +210,11 @@ public MockResponse dispatch(RecordedRequest request) {
198210
} else if (isMarkDonePartitions) {
199211
String tableName = resources[2];
200212
Identifier identifier = Identifier.create(databaseName, tableName);
213+
Optional<MockResponse> error =
214+
checkTablePartitioned(catalog, identifier);
215+
if (error.isPresent()) {
216+
return error.get();
217+
}
201218
MarkDonePartitionsRequest markDonePartitionsRequest =
202219
OBJECT_MAPPER.readValue(
203220
request.getBody().readUtf8(),
@@ -207,6 +224,12 @@ public MockResponse dispatch(RecordedRequest request) {
207224
return new MockResponse().setResponseCode(200);
208225
} else if (isPartitions) {
209226
String tableName = resources[2];
227+
Optional<MockResponse> error =
228+
checkTablePartitioned(
229+
catalog, Identifier.create(databaseName, tableName));
230+
if (error.isPresent()) {
231+
return error.get();
232+
}
210233
return partitionsApiHandler(catalog, request, databaseName, tableName);
211234
} else if (isTableToken) {
212235
GetTableTokenResponse getTableTokenResponse =
@@ -326,6 +349,24 @@ public MockResponse dispatch(RecordedRequest request) {
326349
};
327350
}
328351

352+
private static Optional<MockResponse> checkTablePartitioned(
353+
Catalog catalog, Identifier identifier) {
354+
Table table;
355+
try {
356+
table = catalog.getTable(identifier);
357+
} catch (Catalog.TableNotExistException e) {
358+
return Optional.of(
359+
mockResponse(
360+
new ErrorResponse(ErrorResponseResourceType.TABLE, null, "", 404),
361+
404));
362+
}
363+
boolean partitioned = CoreOptions.fromMap(table.options()).partitionedTableInMetastore();
364+
if (!partitioned) {
365+
return Optional.of(mockResponse(new ErrorResponse(null, null, "", 501), 501));
366+
}
367+
return Optional.empty();
368+
}
369+
329370
private static MockResponse commitTableApiHandler(
330371
Catalog catalog, RecordedRequest request, String databaseName, String tableName)
331372
throws Exception {

0 commit comments

Comments
 (0)