This is an automated email from the ASF dual-hosted git repository.
lzljs3620320 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git
The following commit(s) were added to refs/heads/master by this push:
new 4edc41b7a0 [core] RestCatalog: support ListObjectsByPattern (#5530)
4edc41b7a0 is described below
commit 4edc41b7a0b34c7b65e4368b13f5e215025b7362
Author: XiaoHongbo <[email protected]>
AuthorDate: Mon Apr 28 21:15:53 2025 +0800
[core] RestCatalog: support ListObjectsByPattern (#5530)
---
.../org/apache/paimon/catalog/AbstractCatalog.java | 15 +-
.../java/org/apache/paimon/catalog/Catalog.java | 71 +++++-
.../org/apache/paimon/catalog/CatalogUtils.java | 10 +
.../org/apache/paimon/catalog/DelegateCatalog.java | 28 ++-
.../java/org/apache/paimon/rest/RESTCatalog.java | 63 ++++-
.../main/java/org/apache/paimon/rest/RESTUtil.java | 31 +++
.../org/apache/paimon/catalog/CatalogTestBase.java | 101 +++++---
.../apache/paimon/rest/MockRESTCatalogTest.java | 5 +-
.../org/apache/paimon/rest/RESTCatalogServer.java | 116 +++++++--
.../org/apache/paimon/rest/RESTCatalogTest.java | 276 +++++++++++++++++----
.../java/org/apache/paimon/hive/HiveCatalog.java | 17 +-
paimon-open-api/rest-catalog-open-api.yaml | 25 ++
.../paimon/open/api/RESTCatalogController.java | 50 +++-
13 files changed, 653 insertions(+), 155 deletions(-)
diff --git
a/paimon-core/src/main/java/org/apache/paimon/catalog/AbstractCatalog.java
b/paimon-core/src/main/java/org/apache/paimon/catalog/AbstractCatalog.java
index eef17df5c2..79d963718d 100644
--- a/paimon-core/src/main/java/org/apache/paimon/catalog/AbstractCatalog.java
+++ b/paimon-core/src/main/java/org/apache/paimon/catalog/AbstractCatalog.java
@@ -179,8 +179,12 @@ public abstract class AbstractCatalog implements Catalog {
@Override
public PagedList<Partition> listPartitionsPaged(
- Identifier identifier, Integer maxResults, String pageToken)
+ Identifier identifier,
+ Integer maxResults,
+ String pageToken,
+ String partitionNamePattern)
throws TableNotExistException {
+ CatalogUtils.validateNamePattern(this, partitionNamePattern);
return new PagedList<>(listPartitions(identifier), null);
}
@@ -242,15 +246,17 @@ public abstract class AbstractCatalog implements Catalog {
@Override
public PagedList<String> listTablesPaged(
- String databaseName, Integer maxResults, String pageToken)
+ String databaseName, Integer maxResults, String pageToken, String
tableNamePattern)
throws DatabaseNotExistException {
+ CatalogUtils.validateNamePattern(this, tableNamePattern);
return new PagedList<>(listTables(databaseName), null);
}
@Override
public PagedList<Table> listTableDetailsPaged(
- String databaseName, Integer maxResults, String pageToken)
+ String databaseName, Integer maxResults, String pageToken, String
tableNamePattern)
throws DatabaseNotExistException {
+ CatalogUtils.validateNamePattern(this, tableNamePattern);
if (isSystemDatabase(databaseName)) {
List<Table> systemTables =
SystemTableLoader.loadGlobalTableNames().stream()
@@ -283,7 +289,8 @@ public abstract class AbstractCatalog implements Catalog {
protected PagedList<Table> listTableDetailsPagedImpl(
String databaseName, Integer maxResults, String pageToken)
throws DatabaseNotExistException {
- PagedList<String> pagedTableNames = listTablesPaged(databaseName,
maxResults, pageToken);
+ PagedList<String> pagedTableNames =
+ listTablesPaged(databaseName, maxResults, pageToken, null);
return new PagedList<>(
pagedTableNames.getElements().stream()
.map(
diff --git a/paimon-core/src/main/java/org/apache/paimon/catalog/Catalog.java
b/paimon-core/src/main/java/org/apache/paimon/catalog/Catalog.java
index 7d47459a26..743a2ae760 100644
--- a/paimon-core/src/main/java/org/apache/paimon/catalog/Catalog.java
+++ b/paimon-core/src/main/java/org/apache/paimon/catalog/Catalog.java
@@ -164,13 +164,19 @@ public interface Catalog extends AutoCloseable {
* max results.
* @param pageToken Optional parameter indicating the next page token
allows list to be start
* from a specific point.
+ * @param tableNamePattern A sql LIKE pattern (% and _) for table names.
All tables will be
+ * returned if not set or empty. Currently, only prefix matching is
supported. Note please
+ * escape the underline if you want to match it exactly.
* @return a list of the names of tables with provided page size in this
database and next page
* token, or a list of the names of all tables in this database if the
catalog does not
* {@link #supportsListObjectsPaged()}.
* @throws DatabaseNotExistException if the database does not exist
*/
PagedList<String> listTablesPaged(
- String databaseName, @Nullable Integer maxResults, @Nullable
String pageToken)
+ String databaseName,
+ @Nullable Integer maxResults,
+ @Nullable String pageToken,
+ @Nullable String tableNamePattern)
throws DatabaseNotExistException;
/**
@@ -185,13 +191,19 @@ public interface Catalog extends AutoCloseable {
* max results.
* @param pageToken Optional parameter indicating the next page token
allows list to be start
* from a specific point.
+ * @param tableNamePattern A sql LIKE pattern (% and _) for table names.
All table details will
+ * be returned if not set or empty. Currently, only prefix matching is
supported. Note
+ * please escape the underline if you want to match it exactly.
* @return a list of the table details with provided page size in this
database and next page
* token, or a list of the details of all tables in this database if
the catalog does not
* {@link #supportsListObjectsPaged()}.
* @throws DatabaseNotExistException if the database does not exist
*/
PagedList<Table> listTableDetailsPaged(
- String databaseName, @Nullable Integer maxResults, @Nullable
String pageToken)
+ String databaseName,
+ @Nullable Integer maxResults,
+ @Nullable String pageToken,
+ @Nullable String tableNamePattern)
throws DatabaseNotExistException;
/**
@@ -310,13 +322,19 @@ public interface Catalog extends AutoCloseable {
* max results.
* @param pageToken Optional parameter indicating the next page token
allows list to be start
* from a specific point.
+ * @param partitionNamePattern A sql LIKE pattern (% and _) for partition
names. All partitions
+ * will be * returned if not set or empty. Currently, only prefix
matching is supported.
+ * Note please * escape the underline if you want to match it exactly.
* @return a list of the partitions with provided page size(@param
maxResults) in this table and
* next page token, or a list of all partitions of the table if the
catalog does not {@link
* #supportsListObjectsPaged()}.
* @throws TableNotExistException if the table does not exist
*/
PagedList<Partition> listPartitionsPaged(
- Identifier identifier, @Nullable Integer maxResults, @Nullable
String pageToken)
+ Identifier identifier,
+ @Nullable Integer maxResults,
+ @Nullable String pageToken,
+ @Nullable String partitionNamePattern)
throws TableNotExistException;
// ======================= view methods ===============================
@@ -380,13 +398,19 @@ public interface Catalog extends AutoCloseable {
* max results.
* @param pageToken Optional parameter indicating the next page token
allows list to be start
* from a specific point.
+ * @param viewNamePattern A sql LIKE pattern (% and _) for view names. All
views will be
+ * returned if not set or empty. Currently, only prefix matching is
supported. Note please
+ * escape the underline if you want to match it exactly.
* @return a list of the names of views with provided page size in this
database and next page
* token, or a list of the names of all views in this database if the
catalog does not
* {@link #supportsListObjectsPaged()}.
* @throws DatabaseNotExistException if the database does not exist
*/
default PagedList<String> listViewsPaged(
- String databaseName, @Nullable Integer maxResults, @Nullable
String pageToken)
+ String databaseName,
+ @Nullable Integer maxResults,
+ @Nullable String pageToken,
+ @Nullable String viewNamePattern)
throws DatabaseNotExistException {
return new PagedList<>(listViews(databaseName), null);
}
@@ -401,13 +425,19 @@ public interface Catalog extends AutoCloseable {
* max results.
* @param pageToken Optional parameter indicating the next page token
allows list to be start
* from a specific point.
+ * @param viewNamePattern A sql LIKE pattern (% and _) for view names. All
view details will be
+ * returned if not set or empty. Currently, only prefix matching is
supported. Note please
+ * escape the underline if you want to match it exactly.
* @return a list of the view details with provided page size (@param
maxResults) in this
* database and next page token, or a list of the details of all views
in this database if
* the catalog does not {@link #supportsListObjectsPaged()}.
* @throws DatabaseNotExistException if the database does not exist
*/
default PagedList<View> listViewDetailsPaged(
- String databaseName, @Nullable Integer maxResults, @Nullable
String pageToken)
+ String databaseName,
+ @Nullable Integer maxResults,
+ @Nullable String pageToken,
+ @Nullable String viewNamePattern)
throws DatabaseNotExistException {
return new PagedList<>(Collections.emptyList(), null);
}
@@ -467,21 +497,38 @@ public interface Catalog extends AutoCloseable {
}
/**
- * Whether this catalog supports version management for tables. If not,
corresponding methods
- * will fall back to listing all objects. For example, {@link
#listTablesPaged(String, Integer,
+ * Whether this catalog supports list objects paged. If not, corresponding
methods will fall
+ * back to listing all objects. For example, {@link
#listTablesPaged(String, Integer, String,
* String)} would fall back to {@link #listTables(String)}.
*
* <ul>
* <li>{@link #listDatabasesPaged(Integer, String)}.
- * <li>{@link #listTablesPaged(String, Integer, String)}.
- * <li>{@link #listTableDetailsPaged(String, Integer, String)}.
- * <li>{@link #listViewsPaged(String, Integer, String)}.
- * <li>{@link #listViewDetailsPaged(String, Integer, String)}.
- * <li>{@link #listPartitionsPaged(Identifier, Integer, String)}.
+ * <li>{@link #listTablesPaged(String, Integer, String, String)}.
+ * <li>{@link #listTableDetailsPaged(String, Integer, String, String)}.
+ * <li>{@link #listViewsPaged(String, Integer, String, String)}.
+ * <li>{@link #listViewDetailsPaged(String, Integer, String, String)}.
+ * <li>{@link #listPartitionsPaged(Identifier, Integer, String, String)}.
* </ul>
*/
boolean supportsListObjectsPaged();
+ /**
+ * Whether this catalog supports name pattern filter when list objects
paged. If not,
+ * corresponding methods will throw exception if name pattern provided.
+ *
+ * <ul>
+ * <li>{@link #listDatabasesPaged(Integer, String)}.
+ * <li>{@link #listTablesPaged(String, Integer, String, String)}.
+ * <li>{@link #listTableDetailsPaged(String, Integer, String, String)}.
+ * <li>{@link #listViewsPaged(String, Integer, String, String)}.
+ * <li>{@link #listViewDetailsPaged(String, Integer, String, String)}.
+ * <li>{@link #listPartitionsPaged(Identifier, Integer, String, String)}.
+ * </ul>
+ */
+ default boolean supportsListByPattern() {
+ return false;
+ }
+
// ==================== Version management methods
==========================
/**
diff --git
a/paimon-core/src/main/java/org/apache/paimon/catalog/CatalogUtils.java
b/paimon-core/src/main/java/org/apache/paimon/catalog/CatalogUtils.java
index bdbfe41587..37346aac94 100644
--- a/paimon-core/src/main/java/org/apache/paimon/catalog/CatalogUtils.java
+++ b/paimon-core/src/main/java/org/apache/paimon/catalog/CatalogUtils.java
@@ -45,6 +45,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.function.Function;
import static org.apache.paimon.CoreOptions.PARTITION_DEFAULT_NAME;
@@ -137,6 +138,15 @@ public class CatalogUtils {
CoreOptions.AUTO_CREATE.key(), Boolean.FALSE));
}
+ public static void validateNamePattern(Catalog catalog, String
namePattern) {
+ if (Objects.nonNull(namePattern) && !catalog.supportsListByPattern()) {
+ throw new UnsupportedOperationException(
+ String.format(
+ "Current catalog %s does not support name pattern
filter.",
+ catalog.getClass().getSimpleName()));
+ }
+ }
+
public static List<Partition> listPartitionsFromFileSystem(Table table) {
Options options = Options.fromMap(table.options());
InternalRowPartitionComputer computer =
diff --git
a/paimon-core/src/main/java/org/apache/paimon/catalog/DelegateCatalog.java
b/paimon-core/src/main/java/org/apache/paimon/catalog/DelegateCatalog.java
index af64463fb5..d45e92ab24 100644
--- a/paimon-core/src/main/java/org/apache/paimon/catalog/DelegateCatalog.java
+++ b/paimon-core/src/main/java/org/apache/paimon/catalog/DelegateCatalog.java
@@ -99,16 +99,16 @@ public abstract class DelegateCatalog implements Catalog {
@Override
public PagedList<String> listTablesPaged(
- String databaseName, Integer maxResults, String pageToken)
+ String databaseName, Integer maxResults, String pageToken, String
tableNamePattern)
throws DatabaseNotExistException {
- return wrapped.listTablesPaged(databaseName, maxResults, pageToken);
+ return wrapped.listTablesPaged(databaseName, maxResults, pageToken,
tableNamePattern);
}
@Override
public PagedList<Table> listTableDetailsPaged(
- String databaseName, Integer maxResults, String pageToken)
+ String databaseName, Integer maxResults, String pageToken, String
tableNamePattern)
throws DatabaseNotExistException {
- return wrapped.listTableDetailsPaged(databaseName, maxResults,
pageToken);
+ return wrapped.listTableDetailsPaged(databaseName, maxResults,
pageToken, tableNamePattern);
}
@Override
@@ -141,6 +141,11 @@ public abstract class DelegateCatalog implements Catalog {
return wrapped.supportsListObjectsPaged();
}
+ @Override
+ public boolean supportsListByPattern() {
+ return wrapped.supportsListByPattern();
+ }
+
@Override
public boolean supportsVersionManagement() {
return wrapped.supportsVersionManagement();
@@ -239,16 +244,16 @@ public abstract class DelegateCatalog implements Catalog {
@Override
public PagedList<String> listViewsPaged(
- String databaseName, Integer maxResults, String pageToken)
+ String databaseName, Integer maxResults, String pageToken, String
tableNamePattern)
throws DatabaseNotExistException {
- return wrapped.listViewsPaged(databaseName, maxResults, pageToken);
+ return wrapped.listViewsPaged(databaseName, maxResults, pageToken,
tableNamePattern);
}
@Override
public PagedList<View> listViewDetailsPaged(
- String databaseName, Integer maxResults, String pageToken)
+ String databaseName, Integer maxResults, String pageToken, String
tableNamePattern)
throws DatabaseNotExistException {
- return wrapped.listViewDetailsPaged(databaseName, maxResults,
pageToken);
+ return wrapped.listViewDetailsPaged(databaseName, maxResults,
pageToken, tableNamePattern);
}
@Override
@@ -270,9 +275,12 @@ public abstract class DelegateCatalog implements Catalog {
@Override
public PagedList<Partition> listPartitionsPaged(
- Identifier identifier, Integer maxResults, String pageToken)
+ Identifier identifier,
+ Integer maxResults,
+ String pageToken,
+ String partitionNamePattern)
throws TableNotExistException {
- return wrapped.listPartitionsPaged(identifier, maxResults, pageToken);
+ return wrapped.listPartitionsPaged(identifier, maxResults, pageToken,
partitionNamePattern);
}
@Override
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 53336f5f2c..50c8ebbe65 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
@@ -129,6 +129,10 @@ public class RESTCatalog implements Catalog {
public static final String PAGE_TOKEN = "pageToken";
public static final String QUERY_PARAMETER_WAREHOUSE_KEY = "warehouse";
+ public static final String TABLE_NAME_PATTERN = "tableNamePattern";
+ public static final String VIEW_NAME_PATTERN = "viewNamePattern";
+ public static final String PARTITION_NAME_PATTERN = "partitionNamePattern";
+
private final RESTClient client;
private final ResourcePaths resourcePaths;
private final CatalogContext context;
@@ -314,13 +318,17 @@ public class RESTCatalog implements Catalog {
@Override
public PagedList<String> listTablesPaged(
- String databaseName, @Nullable Integer maxResults, @Nullable
String pageToken)
+ String databaseName,
+ @Nullable Integer maxResults,
+ @Nullable String pageToken,
+ @Nullable String tableNamePattern)
throws DatabaseNotExistException {
try {
ListTablesResponse response =
client.get(
resourcePaths.tables(databaseName),
- buildPagedQueryParams(maxResults, pageToken),
+ buildPagedQueryParams(
+ maxResults, pageToken, TABLE_NAME_PATTERN,
tableNamePattern),
ListTablesResponse.class,
restAuthFunction);
List<String> tables = response.getTables();
@@ -335,13 +343,17 @@ public class RESTCatalog implements Catalog {
@Override
public PagedList<Table> listTableDetailsPaged(
- String db, @Nullable Integer maxResults, @Nullable String
pageToken)
+ String db,
+ @Nullable Integer maxResults,
+ @Nullable String pageToken,
+ @Nullable String tableNamePattern)
throws DatabaseNotExistException {
try {
ListTableDetailsResponse response =
client.get(
resourcePaths.tableDetails(db),
- buildPagedQueryParams(maxResults, pageToken),
+ buildPagedQueryParams(
+ maxResults, pageToken, TABLE_NAME_PATTERN,
tableNamePattern),
ListTableDetailsResponse.class,
restAuthFunction);
List<GetTableResponse> tables = response.getTableDetails();
@@ -396,6 +408,11 @@ public class RESTCatalog implements Catalog {
return true;
}
+ @Override
+ public boolean supportsListByPattern() {
+ return true;
+ }
+
@Override
public boolean supportsVersionManagement() {
return true;
@@ -650,14 +667,21 @@ public class RESTCatalog implements Catalog {
@Override
public PagedList<Partition> listPartitionsPaged(
- Identifier identifier, @Nullable Integer maxResults, @Nullable
String pageToken)
+ Identifier identifier,
+ @Nullable Integer maxResults,
+ @Nullable String pageToken,
+ @Nullable String partitionNamePattern)
throws TableNotExistException {
try {
ListPartitionsResponse response =
client.get(
resourcePaths.partitions(
identifier.getDatabaseName(),
identifier.getObjectName()),
- buildPagedQueryParams(maxResults, pageToken),
+ buildPagedQueryParams(
+ maxResults,
+ pageToken,
+ PARTITION_NAME_PATTERN,
+ partitionNamePattern),
ListPartitionsResponse.class,
restAuthFunction);
List<Partition> partitions = response.getPartitions();
@@ -848,13 +872,17 @@ public class RESTCatalog implements Catalog {
@Override
public PagedList<String> listViewsPaged(
- String databaseName, @Nullable Integer maxResults, @Nullable
String pageToken)
+ String databaseName,
+ @Nullable Integer maxResults,
+ @Nullable String pageToken,
+ @Nullable String viewNamePattern)
throws DatabaseNotExistException {
try {
ListViewsResponse response =
client.get(
resourcePaths.views(databaseName),
- buildPagedQueryParams(maxResults, pageToken),
+ buildPagedQueryParams(
+ maxResults, pageToken, VIEW_NAME_PATTERN,
viewNamePattern),
ListViewsResponse.class,
restAuthFunction);
List<String> views = response.getViews();
@@ -869,13 +897,17 @@ public class RESTCatalog implements Catalog {
@Override
public PagedList<View> listViewDetailsPaged(
- String db, @Nullable Integer maxResults, @Nullable String
pageToken)
+ String db,
+ @Nullable Integer maxResults,
+ @Nullable String pageToken,
+ @Nullable String viewNamePattern)
throws DatabaseNotExistException {
try {
ListViewDetailsResponse response =
client.get(
resourcePaths.viewDetails(db),
- buildPagedQueryParams(maxResults, pageToken),
+ buildPagedQueryParams(
+ maxResults, pageToken, VIEW_NAME_PATTERN,
viewNamePattern),
ListViewDetailsResponse.class,
restAuthFunction);
List<GetViewResponse> views = response.getViewDetails();
@@ -1032,6 +1064,14 @@ public class RESTCatalog implements Catalog {
private Map<String, String> buildPagedQueryParams(
@Nullable Integer maxResults, @Nullable String pageToken) {
+ return buildPagedQueryParams(maxResults, pageToken, null, null);
+ }
+
+ private Map<String, String> buildPagedQueryParams(
+ @Nullable Integer maxResults,
+ @Nullable String pageToken,
+ @Nullable String namePatternKey,
+ @Nullable String namePatternValue) {
Map<String, String> queryParams = Maps.newHashMap();
if (Objects.nonNull(maxResults) && maxResults > 0) {
queryParams.put(MAX_RESULTS, maxResults.toString());
@@ -1039,6 +1079,9 @@ public class RESTCatalog implements Catalog {
if (Objects.nonNull(pageToken)) {
queryParams.put(PAGE_TOKEN, pageToken);
}
+ if (Objects.nonNull(namePatternValue)) {
+ queryParams.put(namePatternKey, namePatternValue);
+ }
return queryParams;
}
}
diff --git a/paimon-core/src/main/java/org/apache/paimon/rest/RESTUtil.java
b/paimon-core/src/main/java/org/apache/paimon/rest/RESTUtil.java
index 73b90f4ed8..dd42394d04 100644
--- a/paimon-core/src/main/java/org/apache/paimon/rest/RESTUtil.java
+++ b/paimon-core/src/main/java/org/apache/paimon/rest/RESTUtil.java
@@ -97,4 +97,35 @@ public class RESTUtil {
e);
}
}
+
+ public static void validatePrefixSqlPattern(String pattern) {
+ if (pattern != null && !pattern.isEmpty()) {
+ boolean escaped = false;
+ boolean inWildcardZone = false;
+
+ for (int i = 0; i < pattern.length(); i++) {
+ char c = pattern.charAt(i);
+
+ if (escaped) {
+ escaped = false;
+ continue;
+ }
+
+ if (c == '\\') {
+ escaped = true;
+ continue;
+ }
+
+ if (c == '%' || c == '_') {
+ inWildcardZone = true;
+ } else {
+ if (inWildcardZone) {
+ throw new IllegalArgumentException(
+ "Can only support sql like prefix query now. "
+ + "Note please escape the underline if
you want to match it exactly");
+ }
+ }
+ }
+ }
+ }
}
diff --git
a/paimon-core/src/test/java/org/apache/paimon/catalog/CatalogTestBase.java
b/paimon-core/src/test/java/org/apache/paimon/catalog/CatalogTestBase.java
index 90641edfe8..293692a906 100644
--- a/paimon-core/src/test/java/org/apache/paimon/catalog/CatalogTestBase.java
+++ b/paimon-core/src/test/java/org/apache/paimon/catalog/CatalogTestBase.java
@@ -75,6 +75,7 @@ import static
org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
/** Base test class of paimon catalog in {@link Catalog}. */
public abstract class CatalogTestBase {
@@ -275,7 +276,7 @@ public abstract class CatalogTestBase {
// List tables paged returns an empty list when there are no tables in
the database
String databaseName = "tables_paged_db";
catalog.createDatabase(databaseName, false);
- PagedList<String> pagedTables = catalog.listTablesPaged(databaseName,
null, null);
+ PagedList<String> pagedTables = catalog.listTablesPaged(databaseName,
null, null, null);
assertThat(pagedTables.getElements()).isEmpty();
assertNull(pagedTables.getNextPageToken());
@@ -288,22 +289,22 @@ public abstract class CatalogTestBase {
// List tables paged returns a list with the names of all tables in
the database in all
// catalogs except RestCatalog
// even if the maxResults or pageToken is not null
- pagedTables = catalog.listTablesPaged(databaseName, null, null);
+ pagedTables = catalog.listTablesPaged(databaseName, null, null, null);
assertPagedTables(pagedTables, tableNames);
int maxResults = 2;
- pagedTables = catalog.listTablesPaged(databaseName, maxResults, null);
+ pagedTables = catalog.listTablesPaged(databaseName, maxResults, null,
null);
assertPagedTables(pagedTables, tableNames);
String pageToken = "table1";
- pagedTables = catalog.listTablesPaged(databaseName, maxResults,
pageToken);
+ pagedTables = catalog.listTablesPaged(databaseName, maxResults,
pageToken, null);
assertPagedTables(pagedTables, tableNames);
maxResults = 8;
- pagedTables = catalog.listTablesPaged(databaseName, maxResults, null);
+ pagedTables = catalog.listTablesPaged(databaseName, maxResults, null,
null);
assertPagedTables(pagedTables, tableNames);
- pagedTables = catalog.listTablesPaged(databaseName, maxResults,
pageToken);
+ pagedTables = catalog.listTablesPaged(databaseName, maxResults,
pageToken, null);
assertPagedTables(pagedTables, tableNames);
// List tables throws DatabaseNotExistException when the database does
not exist
@@ -312,7 +313,7 @@ public abstract class CatalogTestBase {
.isThrownBy(
() ->
catalog.listTablesPaged(
- "non_existing_db", finalMaxResults,
pageToken));
+ "non_existing_db", finalMaxResults,
pageToken, null));
}
@Test
@@ -321,7 +322,7 @@ public abstract class CatalogTestBase {
String databaseName = "table_details_paged_db";
catalog.createDatabase(databaseName, false);
PagedList<Table> pagedTableDetails =
- catalog.listTableDetailsPaged(databaseName, null, null);
+ catalog.listTableDetailsPaged(databaseName, null, null, null);
assertThat(pagedTableDetails.getElements()).isEmpty();
assertNull(pagedTableDetails.getNextPageToken());
@@ -334,26 +335,28 @@ public abstract class CatalogTestBase {
Identifier.create(databaseName, tableName),
DEFAULT_TABLE_SCHEMA, false);
}
- pagedTableDetails = catalog.listTableDetailsPaged(databaseName, null,
null);
+ pagedTableDetails = catalog.listTableDetailsPaged(databaseName, null,
null, null);
assertPagedTableDetails(pagedTableDetails, tableNames.length,
tableNames);
assertNull(pagedTableDetails.getNextPageToken());
int maxResults = 2;
- pagedTableDetails = catalog.listTableDetailsPaged(databaseName,
maxResults, null);
+ pagedTableDetails = catalog.listTableDetailsPaged(databaseName,
maxResults, null, null);
assertPagedTableDetails(pagedTableDetails, tableNames.length,
tableNames);
assertNull(pagedTableDetails.getNextPageToken());
String pageToken = "table1";
- pagedTableDetails = catalog.listTableDetailsPaged(databaseName,
maxResults, pageToken);
+ pagedTableDetails =
+ catalog.listTableDetailsPaged(databaseName, maxResults,
pageToken, null);
assertPagedTableDetails(pagedTableDetails, tableNames.length,
tableNames);
assertNull(pagedTableDetails.getNextPageToken());
maxResults = 8;
- pagedTableDetails = catalog.listTableDetailsPaged(databaseName,
maxResults, null);
+ pagedTableDetails = catalog.listTableDetailsPaged(databaseName,
maxResults, null, null);
assertPagedTableDetails(pagedTableDetails, tableNames.length,
tableNames);
assertNull(pagedTableDetails.getNextPageToken());
- pagedTableDetails = catalog.listTableDetailsPaged(databaseName,
maxResults, pageToken);
+ pagedTableDetails =
+ catalog.listTableDetailsPaged(databaseName, maxResults,
pageToken, null);
assertPagedTableDetails(pagedTableDetails, tableNames.length,
tableNames);
assertNull(pagedTableDetails.getNextPageToken());
@@ -363,7 +366,7 @@ public abstract class CatalogTestBase {
.isThrownBy(
() ->
catalog.listTableDetailsPaged(
- "non_existing_db", finalMaxResults,
pageToken));
+ "non_existing_db", finalMaxResults,
pageToken, null));
}
@Test
@@ -1100,7 +1103,7 @@ public abstract class CatalogTestBase {
// List views returns an empty list when there are no views in the
database
String databaseName = "views_paged_db";
catalog.createDatabase(databaseName, false);
- PagedList<String> pagedViews = catalog.listViewsPaged(databaseName,
null, null);
+ PagedList<String> pagedViews = catalog.listViewsPaged(databaseName,
null, null, null);
assertThat(pagedViews.getElements()).isEmpty();
assertNull(pagedViews.getNextPageToken());
@@ -1113,22 +1116,22 @@ public abstract class CatalogTestBase {
catalog.createView(Identifier.create(databaseName, viewName),
view, false);
}
- pagedViews = catalog.listViewsPaged(databaseName, null, null);
+ pagedViews = catalog.listViewsPaged(databaseName, null, null, null);
assertPagedViews(pagedViews, viewNames);
int maxResults = 2;
- pagedViews = catalog.listViewsPaged(databaseName, maxResults, null);
+ pagedViews = catalog.listViewsPaged(databaseName, maxResults, null,
null);
assertPagedViews(pagedViews, viewNames);
String pageToken = "view1";
- pagedViews = catalog.listViewsPaged(databaseName, maxResults,
pageToken);
+ pagedViews = catalog.listViewsPaged(databaseName, maxResults,
pageToken, null);
assertPagedViews(pagedViews, viewNames);
maxResults = 8;
- pagedViews = catalog.listViewsPaged(databaseName, maxResults, null);
+ pagedViews = catalog.listViewsPaged(databaseName, maxResults, null,
null);
assertPagedViews(pagedViews, viewNames);
- pagedViews = catalog.listViewsPaged(databaseName, maxResults,
pageToken);
+ pagedViews = catalog.listViewsPaged(databaseName, maxResults,
pageToken, null);
assertPagedViews(pagedViews, viewNames);
// List views throws DatabaseNotExistException when the database does
not exist
@@ -1137,7 +1140,13 @@ public abstract class CatalogTestBase {
.isThrownBy(
() ->
catalog.listViewsPaged(
- "non_existing_db", finalMaxResults,
pageToken));
+ "non_existing_db", finalMaxResults,
pageToken, null));
+
+ assertThatExceptionOfType(UnsupportedOperationException.class)
+ .isThrownBy(
+ () ->
+ catalog.listViewsPaged(
+ databaseName, finalMaxResults,
pageToken, "view%"));
}
@Test
@@ -1150,7 +1159,7 @@ public abstract class CatalogTestBase {
String databaseName = "view_details_paged_db";
catalog.createDatabase(databaseName, false);
PagedList<View> pagedViewDetailsPaged =
- catalog.listViewDetailsPaged(databaseName, null, null);
+ catalog.listViewDetailsPaged(databaseName, null, null, null);
assertThat(pagedViewDetailsPaged.getElements()).isEmpty();
assertNull(pagedViewDetailsPaged.getNextPageToken());
@@ -1163,26 +1172,28 @@ public abstract class CatalogTestBase {
catalog.createView(Identifier.create(databaseName, viewName),
view, false);
}
- pagedViewDetailsPaged = catalog.listViewDetailsPaged(databaseName,
null, null);
+ pagedViewDetailsPaged = catalog.listViewDetailsPaged(databaseName,
null, null, null);
assertPagedViewDetails(pagedViewDetailsPaged, view, viewNames.length,
viewNames);
assertNull(pagedViewDetailsPaged.getNextPageToken());
int maxResults = 2;
- pagedViewDetailsPaged = catalog.listViewDetailsPaged(databaseName,
maxResults, null);
+ pagedViewDetailsPaged = catalog.listViewDetailsPaged(databaseName,
maxResults, null, null);
assertPagedViewDetails(pagedViewDetailsPaged, view, viewNames.length,
viewNames);
assertNull(pagedViewDetailsPaged.getNextPageToken());
String pageToken = "view1";
- pagedViewDetailsPaged = catalog.listViewDetailsPaged(databaseName,
maxResults, pageToken);
+ pagedViewDetailsPaged =
+ catalog.listViewDetailsPaged(databaseName, maxResults,
pageToken, null);
assertPagedViewDetails(pagedViewDetailsPaged, view, viewNames.length,
viewNames);
assertNull(pagedViewDetailsPaged.getNextPageToken());
maxResults = 8;
- pagedViewDetailsPaged = catalog.listViewDetailsPaged(databaseName,
maxResults, null);
+ pagedViewDetailsPaged = catalog.listViewDetailsPaged(databaseName,
maxResults, null, null);
assertPagedViewDetails(pagedViewDetailsPaged, view, viewNames.length,
viewNames);
assertNull(pagedViewDetailsPaged.getNextPageToken());
- pagedViewDetailsPaged = catalog.listViewDetailsPaged(databaseName,
maxResults, pageToken);
+ pagedViewDetailsPaged =
+ catalog.listViewDetailsPaged(databaseName, maxResults,
pageToken, null);
assertPagedViewDetails(pagedViewDetailsPaged, view, viewNames.length,
viewNames);
assertNull(pagedViewDetailsPaged.getNextPageToken());
@@ -1192,7 +1203,7 @@ public abstract class CatalogTestBase {
.isThrownBy(
() ->
catalog.listViewDetailsPaged(
- "non_existing_db", finalMaxResults,
pageToken));
+ "non_existing_db", finalMaxResults,
pageToken, null));
}
@Test
@@ -1343,23 +1354,24 @@ public abstract class CatalogTestBase {
// List partitions paged returns a list with all partitions of the
table in all catalogs
// except RestCatalog even
// if the maxResults or pageToken is not null
- PagedList<Partition> pagedPartitions =
catalog.listPartitionsPaged(identifier, null, null);
+ PagedList<Partition> pagedPartitions =
+ catalog.listPartitionsPaged(identifier, null, null, null);
Map[] specs = partitionSpecs.toArray(new Map[0]);
assertPagedPartitions(pagedPartitions, specs.length, specs);
int maxResults = 2;
- pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
null);
+ pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
null, null);
assertPagedPartitions(pagedPartitions, specs.length, specs);
String pageToken = "dt=20250101";
- pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
pageToken);
+ pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
pageToken, null);
assertPagedPartitions(pagedPartitions, specs.length, specs);
maxResults = 8;
- pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
null);
+ pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
null, null);
assertPagedPartitions(pagedPartitions, specs.length, specs);
- pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
pageToken);
+ pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
pageToken, null);
assertPagedPartitions(pagedPartitions, specs.length, specs);
// List partitions throws TableNotExistException when the table does
not exist
@@ -1370,7 +1382,28 @@ public abstract class CatalogTestBase {
catalog.listPartitionsPaged(
Identifier.create(databaseName,
"non_existing_table"),
finalMaxResults,
- pageToken));
+ pageToken,
+ null));
+
+ assertThrows(
+ UnsupportedOperationException.class,
+ () -> catalog.listPartitionsPaged(identifier, null, null,
"dt=_0101"));
+
+ assertThrows(
+ UnsupportedOperationException.class,
+ () -> catalog.listPartitionsPaged(identifier, null, null,
"dt=0101_"));
+
+ assertThrows(
+ UnsupportedOperationException.class,
+ () -> catalog.listPartitionsPaged(identifier, null, null,
"dt=%0101"));
+
+ assertThrows(
+ UnsupportedOperationException.class,
+ () -> catalog.listPartitionsPaged(identifier, null, null,
"dt=0101%"));
+
+ assertThrows(
+ UnsupportedOperationException.class,
+ () -> catalog.listPartitionsPaged(identifier, null, null,
"dt=0101"));
}
protected boolean supportsAlterDatabase() {
diff --git
a/paimon-core/src/test/java/org/apache/paimon/rest/MockRESTCatalogTest.java
b/paimon-core/src/test/java/org/apache/paimon/rest/MockRESTCatalogTest.java
index 69ea8a5185..dab6b0fb34 100644
--- a/paimon-core/src/test/java/org/apache/paimon/rest/MockRESTCatalogTest.java
+++ b/paimon-core/src/test/java/org/apache/paimon/rest/MockRESTCatalogTest.java
@@ -156,9 +156,10 @@ class MockRESTCatalogTest extends RESTCatalogTest {
Identifier.create(databaseName, tableName),
DEFAULT_TABLE_SCHEMA, false);
}
PagedList<String> listTablesPaged =
- restCatalog.listTablesPaged(databaseName, 1, "dt=20230101");
+ restCatalog.listTablesPaged(databaseName, 1, "dt=20230101",
null);
PagedList<String> listTablesPaged2 =
- restCatalog.listTablesPaged(databaseName, 1,
listTablesPaged.getNextPageToken());
+ restCatalog.listTablesPaged(
+ databaseName, 1, listTablesPaged.getNextPageToken(),
null);
assertEquals(listTablesPaged.getElements().get(0), "dt=20230102");
assertEquals(listTablesPaged2.getElements().get(0), "dt=20230103");
}
diff --git
a/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogServer.java
b/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogServer.java
index 6173e43361..2c4cc894a7 100644
--- a/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogServer.java
+++ b/paimon-core/src/test/java/org/apache/paimon/rest/RESTCatalogServer.java
@@ -104,12 +104,18 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.apache.paimon.CoreOptions.PATH;
import static org.apache.paimon.CoreOptions.SNAPSHOT_CLEAN_EMPTY_DIRECTORIES;
import static org.apache.paimon.CoreOptions.TYPE;
import static org.apache.paimon.TableType.FORMAT_TABLE;
+import static org.apache.paimon.rest.RESTCatalog.MAX_RESULTS;
+import static org.apache.paimon.rest.RESTCatalog.PAGE_TOKEN;
+import static org.apache.paimon.rest.RESTCatalog.PARTITION_NAME_PATTERN;
+import static org.apache.paimon.rest.RESTCatalog.TABLE_NAME_PATTERN;
+import static org.apache.paimon.rest.RESTCatalog.VIEW_NAME_PATTERN;
import static org.apache.paimon.rest.RESTObjectMapper.OBJECT_MAPPER;
/** Mock REST server for testing. */
@@ -118,8 +124,6 @@ public class RESTCatalogServer {
private static final Logger LOG =
LoggerFactory.getLogger(RESTCatalogServer.class);
public static final int DEFAULT_MAX_RESULTS = 100;
- public static final String MAX_RESULTS = RESTCatalog.MAX_RESULTS;
- public static final String PAGE_TOKEN = RESTCatalog.PAGE_TOKEN;
public static final String AUTHORIZATION_HEADER_KEY = "Authorization";
private final String prefix;
@@ -834,7 +838,7 @@ public class RESTCatalogServer {
if (databaseStore.containsKey(databaseName)) {
switch (method) {
case "GET":
- List<String> tables = listTables(databaseName);
+ List<String> tables = listTables(databaseName, parameters);
return generateFinalListTablesResponse(parameters, tables);
case "POST":
CreateTableRequest requestBody =
@@ -865,17 +869,26 @@ public class RESTCatalogServer {
new ErrorResponse(ErrorResponse.RESOURCE_TYPE_DATABASE, null,
"", 404), 404);
}
- private List<String> listTables(String databaseName) {
+ private List<String> listTables(String databaseName, Map<String, String>
parameters) {
+ String tableNamePattern = parameters.get(TABLE_NAME_PATTERN);
List<String> tables = new ArrayList<>();
for (Map.Entry<String, TableMetadata> entry :
tableMetadataStore.entrySet()) {
Identifier identifier = Identifier.fromString(entry.getKey());
- if (databaseName.equals(identifier.getDatabaseName())) {
+ if (databaseName.equals(identifier.getDatabaseName())
+ && (Objects.isNull(tableNamePattern)
+ || matchNamePattern(identifier.getTableName(),
tableNamePattern))) {
tables.add(identifier.getTableName());
}
}
return tables;
}
+ private boolean matchNamePattern(String name, String pattern) {
+ RESTUtil.validatePrefixSqlPattern(pattern);
+ String regex = sqlPatternToRegex(pattern);
+ return Pattern.compile(regex).matcher(name).matches();
+ }
+
private MockResponse generateFinalListTablesResponse(
Map<String, String> parameters, List<String> tables) {
RESTResponse response;
@@ -910,7 +923,7 @@ public class RESTCatalogServer {
private MockResponse tableDetailsHandle(Map<String, String> parameters,
String databaseName) {
RESTResponse response;
- List<GetTableResponse> tableDetails = listTableDetails(databaseName);
+ List<GetTableResponse> tableDetails = listTableDetails(databaseName,
parameters);
if (!tableDetails.isEmpty()) {
int maxResults;
try {
@@ -940,11 +953,15 @@ public class RESTCatalogServer {
return mockResponse(response, 200);
}
- private List<GetTableResponse> listTableDetails(String databaseName) {
+ private List<GetTableResponse> listTableDetails(
+ String databaseName, Map<String, String> parameters) {
+ String tableNamePattern = parameters.get(TABLE_NAME_PATTERN);
List<GetTableResponse> tableDetails = new ArrayList<>();
for (Map.Entry<String, TableMetadata> entry :
tableMetadataStore.entrySet()) {
Identifier identifier = Identifier.fromString(entry.getKey());
- if (databaseName.equals(identifier.getDatabaseName())) {
+ if (databaseName.equals(identifier.getDatabaseName())
+ && (Objects.isNull(tableNamePattern)
+ || matchNamePattern(identifier.getTableName(),
tableNamePattern))) {
GetTableResponse getTableResponse =
new GetTableResponse(
entry.getValue().uuid(),
@@ -1044,15 +1061,23 @@ public class RESTCatalogServer {
}
private MockResponse partitionsApiHandle(
- String method, Map<String, String> parameters, Identifier
tableIdentifier)
- throws Exception {
+ String method, Map<String, String> parameters, Identifier
tableIdentifier) {
+ String partitionNamePattern = parameters.get(PARTITION_NAME_PATTERN);
switch (method) {
case "GET":
List<Partition> partitions = new ArrayList<>();
for (Map.Entry<String, List<Partition>> entry :
tablePartitionsStore.entrySet()) {
String objectName =
Identifier.fromString(entry.getKey()).getObjectName();
if (objectName.equals(tableIdentifier.getObjectName())) {
- partitions.addAll(entry.getValue());
+ partitions.addAll(
+ entry.getValue().stream()
+ .filter(
+ partition ->
+
Objects.isNull(partitionNamePattern)
+ ||
matchNamePattern(
+
getPagedKey(partition),
+
partitionNamePattern))
+ .collect(Collectors.toList()));
}
}
return generateFinalListPartitionsResponse(parameters,
partitions);
@@ -1187,7 +1212,7 @@ public class RESTCatalogServer {
throws Exception {
switch (method) {
case "GET":
- List<String> views = listViews(databaseName);
+ List<String> views = listViews(databaseName, parameters);
return generateFinalListViewsResponse(parameters, views);
case "POST":
CreateViewRequest requestBody =
@@ -1212,11 +1237,16 @@ public class RESTCatalogServer {
}
}
- private List<String> listViews(String databaseName) {
+ private List<String> listViews(String databaseName, Map<String, String>
parameters) {
+ String viewNamePattern = parameters.get(VIEW_NAME_PATTERN);
return viewStore.keySet().stream()
.map(Identifier::fromString)
.filter(identifier ->
identifier.getDatabaseName().equals(databaseName))
.map(Identifier::getTableName)
+ .filter(
+ viewName ->
+ (Objects.isNull(viewNamePattern)
+ || matchNamePattern(viewName,
viewNamePattern)))
.collect(Collectors.toList());
}
@@ -1256,7 +1286,7 @@ public class RESTCatalogServer {
RESTResponse response;
if ("GET".equals(method)) {
- List<GetViewResponse> viewDetails = listViewDetails(databaseName);
+ List<GetViewResponse> viewDetails = listViewDetails(databaseName,
parameters);
if (!viewDetails.isEmpty()) {
int maxResults;
@@ -1292,10 +1322,17 @@ public class RESTCatalogServer {
}
}
- private List<GetViewResponse> listViewDetails(String databaseName) {
+ private List<GetViewResponse> listViewDetails(
+ String databaseName, Map<String, String> parameters) {
+ String viewNamePattern = parameters.get(VIEW_NAME_PATTERN);
return viewStore.keySet().stream()
.map(Identifier::fromString)
.filter(identifier ->
identifier.getDatabaseName().equals(databaseName))
+ .filter(
+ identifier ->
+ (Objects.isNull(viewNamePattern)
+ || matchNamePattern(
+ identifier.getTableName(),
viewNamePattern)))
.map(
identifier -> {
View view =
viewStore.get(identifier.getFullName());
@@ -1711,15 +1748,44 @@ public class RESTCatalogServer {
}
private Map<String, String> getParameters(String query) {
- Map<String, String> parameters =
- Arrays.stream(query.split("&"))
- .map(pair -> pair.split("=", 2))
- .collect(
- Collectors.toMap(
- pair -> pair[0].trim(), // key
- pair ->
RESTUtil.decodeString(pair[1].trim()), // value
- (existing, replacement) -> existing //
handle duplicates
- ));
- return parameters;
+ return Arrays.stream(query.split("&"))
+ .map(pair -> pair.split("=", 2))
+ .collect(
+ Collectors.toMap(
+ pair -> pair[0].trim(), // key
+ pair -> RESTUtil.decodeString(pair[1].trim()),
// value
+ (existing, replacement) -> existing // handle
duplicates
+ ));
+ }
+
+ private String sqlPatternToRegex(String pattern) {
+ StringBuilder regex = new StringBuilder();
+ boolean escaped = false;
+
+ for (int i = 0; i < pattern.length(); i++) {
+ char c = pattern.charAt(i);
+
+ if (escaped) {
+ regex.append(c);
+ escaped = false;
+ continue;
+ }
+ if (c == '\\') {
+ escaped = true;
+ continue;
+ }
+ switch (c) {
+ case '%':
+ regex.append(".*");
+ break;
+ case '_':
+ regex.append(".");
+ break;
+ default:
+ regex.append(c);
+ break;
+ }
+ }
+ return "^" + regex + "$";
}
}
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 08ba3d22f0..cb8392dd96 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.partition.Partition;
import org.apache.paimon.partition.PartitionStatistics;
import org.apache.paimon.reader.RecordReader;
import org.apache.paimon.rest.auth.DLFToken;
+import org.apache.paimon.rest.exceptions.BadRequestException;
import org.apache.paimon.rest.responses.ConfigResponse;
import org.apache.paimon.schema.Schema;
import org.apache.paimon.schema.SchemaChange;
@@ -58,6 +59,7 @@ import
org.apache.paimon.shade.guava30.com.google.common.collect.Lists;
import org.apache.paimon.shade.guava30.com.google.common.collect.Maps;
import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.File;
@@ -87,6 +89,7 @@ import static
org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/** Base test class for {@link RESTCatalog}. */
public abstract class RESTCatalogTest extends CatalogTestBase {
@@ -202,10 +205,10 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
false));
assertThrows(
Catalog.DatabaseNotExistException.class,
- () -> catalog.listTablesPaged(database, 100, null));
+ () -> catalog.listTablesPaged(database, 100, null, null));
assertThrows(
Catalog.DatabaseNotExistException.class,
- () -> catalog.listTableDetailsPaged(database, 100, null));
+ () -> catalog.listTableDetailsPaged(database, 100, null,
null));
}
@Test
@@ -242,7 +245,7 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
Catalog.TableNoPermissionException.class, () ->
catalog.listPartitions(identifier));
assertThrows(
Catalog.TableNoPermissionException.class,
- () -> catalog.listPartitionsPaged(identifier, 100, null));
+ () -> catalog.listPartitionsPaged(identifier, 100, null,
null));
assertThrows(
Catalog.TableNoPermissionException.class,
() -> restCatalog.createBranch(identifier, "test_branch",
null));
@@ -312,7 +315,7 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
// List tables paged returns an empty list when there are no tables in
the database
String databaseName = "tables_paged_db";
catalog.createDatabase(databaseName, false);
- PagedList<String> pagedTables = catalog.listTablesPaged(databaseName,
null, null);
+ PagedList<String> pagedTables = catalog.listTablesPaged(databaseName,
null, null, null);
assertThat(pagedTables.getElements()).isEmpty();
assertNull(pagedTables.getNextPageToken());
@@ -324,7 +327,7 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
// when maxResults is null or 0, the page length is set to a server
configured value
String[] sortedTableNames =
Arrays.stream(tableNames).sorted().toArray(String[]::new);
- pagedTables = catalog.listTablesPaged(databaseName, null, null);
+ pagedTables = catalog.listTablesPaged(databaseName, null, null, null);
List<String> tables = pagedTables.getElements();
assertThat(tables).containsExactly(sortedTableNames);
assertNull(pagedTables.getNextPageToken());
@@ -333,7 +336,7 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
// server configured value
// when pageToken is null, will list tables from the beginning
int maxResults = 2;
- pagedTables = catalog.listTablesPaged(databaseName, maxResults, null);
+ pagedTables = catalog.listTablesPaged(databaseName, maxResults, null,
null);
tables = pagedTables.getElements();
assertEquals(maxResults, tables.size());
assertThat(tables).containsExactly("abd", "def");
@@ -341,32 +344,35 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
// when pageToken is not null, will list tables from the pageToken
(exclusive)
pagedTables =
- catalog.listTablesPaged(databaseName, maxResults,
pagedTables.getNextPageToken());
+ catalog.listTablesPaged(
+ databaseName, maxResults,
pagedTables.getNextPageToken(), null);
tables = pagedTables.getElements();
assertEquals(maxResults, tables.size());
assertThat(tables).containsExactly("opr", "table1");
assertEquals("table1", pagedTables.getNextPageToken());
pagedTables =
- catalog.listTablesPaged(databaseName, maxResults,
pagedTables.getNextPageToken());
+ catalog.listTablesPaged(
+ databaseName, maxResults,
pagedTables.getNextPageToken(), null);
tables = pagedTables.getElements();
assertEquals(maxResults, tables.size());
assertThat(tables).containsExactly("table2", "table3");
assertEquals("table3", pagedTables.getNextPageToken());
pagedTables =
- catalog.listTablesPaged(databaseName, maxResults,
pagedTables.getNextPageToken());
+ catalog.listTablesPaged(
+ databaseName, maxResults,
pagedTables.getNextPageToken(), null);
tables = pagedTables.getElements();
assertEquals(0, tables.size());
assertNull(pagedTables.getNextPageToken());
maxResults = 8;
- pagedTables = catalog.listTablesPaged(databaseName, maxResults, null);
+ pagedTables = catalog.listTablesPaged(databaseName, maxResults, null,
null);
tables = pagedTables.getElements();
assertThat(tables).containsExactly(sortedTableNames);
assertNull(pagedTables.getNextPageToken());
- pagedTables = catalog.listTablesPaged(databaseName, maxResults,
"table1");
+ pagedTables = catalog.listTablesPaged(databaseName, maxResults,
"table1", null);
tables = pagedTables.getElements();
assertEquals(2, tables.size());
assertThat(tables).containsExactly("table2", "table3");
@@ -375,6 +381,46 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
// List tables throws DatabaseNotExistException when the database does
not exist
assertThatExceptionOfType(Catalog.DatabaseNotExistException.class)
.isThrownBy(() -> catalog.listTables("non_existing_db"));
+
+ pagedTables = catalog.listTablesPaged(databaseName, null, null,
"table%");
+ tables = pagedTables.getElements();
+ assertEquals(3, tables.size());
+ assertThat(tables).containsExactly("table1", "table2", "table3");
+ assertNull(pagedTables.getNextPageToken());
+
+ pagedTables = catalog.listTablesPaged(databaseName, null, null,
"table_");
+ tables = pagedTables.getElements();
+ assertEquals(3, tables.size());
+ assertThat(tables).containsExactly("table1", "table2", "table3");
+ assertNull(pagedTables.getNextPageToken());
+
+ pagedTables = catalog.listTablesPaged(databaseName, null, null,
"table_%");
+ tables = pagedTables.getElements();
+ assertEquals(3, tables.size());
+ assertThat(tables).containsExactly("table1", "table2", "table3");
+ assertNull(pagedTables.getNextPageToken());
+
+ pagedTables = catalog.listTablesPaged(databaseName, null, null,
"table%_");
+ tables = pagedTables.getElements();
+ assertEquals(3, tables.size());
+ assertThat(tables).containsExactly("table1", "table2", "table3");
+ assertNull(pagedTables.getNextPageToken());
+
+ pagedTables = catalog.listTablesPaged(databaseName, null, null,
"table\\_");
+ Assertions.assertTrue(pagedTables.getElements().isEmpty());
+ Assertions.assertNull(pagedTables.getNextPageToken());
+
+ pagedTables = catalog.listTablesPaged(databaseName, null, null,
"tabl_");
+ Assertions.assertTrue(pagedTables.getElements().isEmpty());
+ Assertions.assertNull(pagedTables.getNextPageToken());
+
+ Assertions.assertThrows(
+ BadRequestException.class,
+ () -> catalog.listTablesPaged(databaseName, null, null,
"ta%le"));
+
+ Assertions.assertThrows(
+ BadRequestException.class,
+ () -> catalog.listTablesPaged(databaseName, null, null,
"ta_le"));
}
@Test
@@ -383,7 +429,7 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
String databaseName = "table_details_paged_db";
catalog.createDatabase(databaseName, false);
PagedList<Table> pagedTableDetails =
- catalog.listTableDetailsPaged(databaseName, null, null);
+ catalog.listTableDetailsPaged(databaseName, null, null, null);
assertThat(pagedTableDetails.getElements()).isEmpty();
assertNull(pagedTableDetails.getNextPageToken());
@@ -394,41 +440,42 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
Identifier.create(databaseName, tableName),
DEFAULT_TABLE_SCHEMA, false);
}
- pagedTableDetails = catalog.listTableDetailsPaged(databaseName, null,
null);
+ pagedTableDetails = catalog.listTableDetailsPaged(databaseName, null,
null, null);
assertPagedTableDetails(pagedTableDetails, tableNames.length,
expectedTableNames);
assertNull(pagedTableDetails.getNextPageToken());
int maxResults = 2;
- pagedTableDetails = catalog.listTableDetailsPaged(databaseName,
maxResults, null);
+ pagedTableDetails = catalog.listTableDetailsPaged(databaseName,
maxResults, null, null);
assertPagedTableDetails(pagedTableDetails, maxResults, "abd", "def");
assertEquals("def", pagedTableDetails.getNextPageToken());
pagedTableDetails =
catalog.listTableDetailsPaged(
- databaseName, maxResults,
pagedTableDetails.getNextPageToken());
+ databaseName, maxResults,
pagedTableDetails.getNextPageToken(), null);
assertPagedTableDetails(pagedTableDetails, maxResults, "opr",
"table1");
assertEquals("table1", pagedTableDetails.getNextPageToken());
pagedTableDetails =
catalog.listTableDetailsPaged(
- databaseName, maxResults,
pagedTableDetails.getNextPageToken());
+ databaseName, maxResults,
pagedTableDetails.getNextPageToken(), null);
assertPagedTableDetails(pagedTableDetails, maxResults, "table2",
"table3");
assertEquals("table3", pagedTableDetails.getNextPageToken());
pagedTableDetails =
catalog.listTableDetailsPaged(
- databaseName, maxResults,
pagedTableDetails.getNextPageToken());
+ databaseName, maxResults,
pagedTableDetails.getNextPageToken(), null);
assertEquals(0, pagedTableDetails.getElements().size());
assertNull(pagedTableDetails.getNextPageToken());
maxResults = 8;
- pagedTableDetails = catalog.listTableDetailsPaged(databaseName,
maxResults, null);
+ pagedTableDetails = catalog.listTableDetailsPaged(databaseName,
maxResults, null, null);
assertPagedTableDetails(
pagedTableDetails, Math.min(maxResults, tableNames.length),
expectedTableNames);
assertNull(pagedTableDetails.getNextPageToken());
String pageToken = "table1";
- pagedTableDetails = catalog.listTableDetailsPaged(databaseName,
maxResults, pageToken);
+ pagedTableDetails =
+ catalog.listTableDetailsPaged(databaseName, maxResults,
pageToken, null);
assertPagedTableDetails(pagedTableDetails, 2, "table2", "table3");
assertNull(pagedTableDetails.getNextPageToken());
@@ -438,7 +485,43 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
.isThrownBy(
() ->
catalog.listTableDetailsPaged(
- "non_existing_db", finalMaxResults,
pageToken));
+ "non_existing_db", finalMaxResults,
pageToken, null));
+
+ // List tables throws DatabaseNotExistException when the database does
not exist
+ assertThatExceptionOfType(Catalog.DatabaseNotExistException.class)
+ .isThrownBy(() -> catalog.listTables("non_existing_db"));
+
+ pagedTableDetails = catalog.listTableDetailsPaged(databaseName, null,
null, "table%");
+ assertPagedTableDetails(pagedTableDetails, 3, "table1", "table2",
"table3");
+ assertNull(pagedTableDetails.getNextPageToken());
+
+ pagedTableDetails = catalog.listTableDetailsPaged(databaseName, null,
null, "table_");
+ assertPagedTableDetails(pagedTableDetails, 3, "table1", "table2",
"table3");
+ assertNull(pagedTableDetails.getNextPageToken());
+
+ pagedTableDetails = catalog.listTableDetailsPaged(databaseName, null,
null, "table_%");
+ assertPagedTableDetails(pagedTableDetails, 3, "table1", "table2",
"table3");
+ assertNull(pagedTableDetails.getNextPageToken());
+
+ pagedTableDetails = catalog.listTableDetailsPaged(databaseName, null,
null, "table%_");
+ assertPagedTableDetails(pagedTableDetails, 3, "table1", "table2",
"table3");
+ assertNull(pagedTableDetails.getNextPageToken());
+
+ pagedTableDetails = catalog.listTableDetailsPaged(databaseName, null,
null, "table\\_");
+ assertTrue(pagedTableDetails.getElements().isEmpty());
+ assertNull(pagedTableDetails.getNextPageToken());
+
+ pagedTableDetails = catalog.listTableDetailsPaged(databaseName, null,
null, "tabl_");
+ assertTrue(pagedTableDetails.getElements().isEmpty());
+ assertNull(pagedTableDetails.getNextPageToken());
+
+ Assertions.assertThrows(
+ BadRequestException.class,
+ () -> catalog.listTableDetailsPaged(databaseName, null, null,
"ta%le"));
+
+ Assertions.assertThrows(
+ BadRequestException.class,
+ () -> catalog.listTableDetailsPaged(databaseName, null, null,
"ta_le"));
}
@Test
@@ -471,7 +554,7 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
// List views returns an empty list when there are no views in the
database
String databaseName = "views_paged_db";
catalog.createDatabase(databaseName, false);
- PagedList<String> pagedViews = catalog.listViewsPaged(databaseName,
null, null);
+ PagedList<String> pagedViews = catalog.listViewsPaged(databaseName,
null, null, null);
assertThat(pagedViews.getElements()).isEmpty();
assertNull(pagedViews.getNextPageToken());
@@ -485,33 +568,35 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
catalog.createView(Identifier.create(databaseName, viewName),
view, false);
}
- pagedViews = catalog.listViewsPaged(databaseName, null, null);
+ pagedViews = catalog.listViewsPaged(databaseName, null, null, null);
assertThat(pagedViews.getElements()).containsExactly(sortedViewNames);
assertNull(pagedViews.getNextPageToken());
int maxResults = 2;
- pagedViews = catalog.listViewsPaged(databaseName, maxResults, null);
+ pagedViews = catalog.listViewsPaged(databaseName, maxResults, null,
null);
assertPagedViews(pagedViews, "abd", "def");
assertEquals("def", pagedViews.getNextPageToken());
pagedViews =
- catalog.listViewsPaged(databaseName, maxResults,
pagedViews.getNextPageToken());
+ catalog.listViewsPaged(
+ databaseName, maxResults,
pagedViews.getNextPageToken(), null);
assertPagedViews(pagedViews, "opr", "view1");
assertEquals("view1", pagedViews.getNextPageToken());
pagedViews =
- catalog.listViewsPaged(databaseName, maxResults,
pagedViews.getNextPageToken());
+ catalog.listViewsPaged(
+ databaseName, maxResults,
pagedViews.getNextPageToken(), null);
assertPagedViews(pagedViews, "view2", "view3");
assertEquals("view3", pagedViews.getNextPageToken());
maxResults = 8;
String[] expectedViewNames =
Arrays.stream(viewNames).sorted().toArray(String[]::new);
- pagedViews = catalog.listViewsPaged(databaseName, maxResults, null);
+ pagedViews = catalog.listViewsPaged(databaseName, maxResults, null,
null);
assertPagedViews(pagedViews, expectedViewNames);
assertNull(pagedViews.getNextPageToken());
String pageToken = "view1";
- pagedViews = catalog.listViewsPaged(databaseName, maxResults,
pageToken);
+ pagedViews = catalog.listViewsPaged(databaseName, maxResults,
pageToken, null);
assertPagedViews(pagedViews, "view2", "view3");
assertNull(pagedViews.getNextPageToken());
@@ -521,7 +606,39 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
.isThrownBy(
() ->
catalog.listViewsPaged(
- "non_existing_db", finalMaxResults,
pageToken));
+ "non_existing_db", finalMaxResults,
pageToken, null));
+
+ pagedViews = catalog.listViewsPaged(databaseName, null, null, "view%");
+ assertPagedViews(pagedViews, "view1", "view2", "view3");
+ assertNull(pagedViews.getNextPageToken());
+
+ pagedViews = catalog.listViewsPaged(databaseName, null, null, "view_");
+ assertPagedViews(pagedViews, "view1", "view2", "view3");
+ assertNull(pagedViews.getNextPageToken());
+
+ pagedViews = catalog.listViewsPaged(databaseName, null, null,
"view_%");
+ assertPagedViews(pagedViews, "view1", "view2", "view3");
+ assertNull(pagedViews.getNextPageToken());
+
+ pagedViews = catalog.listViewsPaged(databaseName, null, null,
"view%_");
+ assertPagedViews(pagedViews, "view1", "view2", "view3");
+ assertNull(pagedViews.getNextPageToken());
+
+ pagedViews = catalog.listViewsPaged(databaseName, null, null,
"view\\_");
+ assertTrue(pagedViews.getElements().isEmpty());
+ assertNull(pagedViews.getNextPageToken());
+
+ pagedViews = catalog.listViewsPaged(databaseName, null, null, "vie_");
+ Assertions.assertTrue(pagedViews.getElements().isEmpty());
+ assertNull(pagedViews.getNextPageToken());
+
+ Assertions.assertThrows(
+ BadRequestException.class,
+ () -> catalog.listViewsPaged(databaseName, null, null,
"vi%ew"));
+
+ Assertions.assertThrows(
+ BadRequestException.class,
+ () -> catalog.listViewsPaged(databaseName, null, null,
"vi_ew"));
}
@Test
@@ -529,7 +646,8 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
// List view details returns an empty list when there are no views in
the database
String databaseName = "view_details_paged_db";
catalog.createDatabase(databaseName, false);
- PagedList<View> pagedViewDetails =
catalog.listViewDetailsPaged(databaseName, null, null);
+ PagedList<View> pagedViewDetails =
+ catalog.listViewDetailsPaged(databaseName, null, null, null);
assertThat(pagedViewDetails.getElements()).isEmpty();
assertNull(pagedViewDetails.getNextPageToken());
@@ -539,35 +657,35 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
catalog.createView(Identifier.create(databaseName, viewName),
view, false);
}
- pagedViewDetails = catalog.listViewDetailsPaged(databaseName, null,
null);
+ pagedViewDetails = catalog.listViewDetailsPaged(databaseName, null,
null, null);
assertPagedViewDetails(pagedViewDetails, view, viewNames.length,
viewNames);
assertNull(pagedViewDetails.getNextPageToken());
int maxResults = 2;
- pagedViewDetails = catalog.listViewDetailsPaged(databaseName,
maxResults, null);
+ pagedViewDetails = catalog.listViewDetailsPaged(databaseName,
maxResults, null, null);
assertPagedViewDetails(pagedViewDetails, view, maxResults, "abd",
"def");
assertEquals("def", pagedViewDetails.getNextPageToken());
pagedViewDetails =
catalog.listViewDetailsPaged(
- databaseName, maxResults,
pagedViewDetails.getNextPageToken());
+ databaseName, maxResults,
pagedViewDetails.getNextPageToken(), null);
assertPagedViewDetails(pagedViewDetails, view, maxResults, "opr",
"view1");
assertEquals("view1", pagedViewDetails.getNextPageToken());
pagedViewDetails =
catalog.listViewDetailsPaged(
- databaseName, maxResults,
pagedViewDetails.getNextPageToken());
+ databaseName, maxResults,
pagedViewDetails.getNextPageToken(), null);
assertPagedViewDetails(pagedViewDetails, view, maxResults, "view2",
"view3");
assertEquals("view3", pagedViewDetails.getNextPageToken());
pagedViewDetails =
catalog.listViewDetailsPaged(
- databaseName, maxResults,
pagedViewDetails.getNextPageToken());
+ databaseName, maxResults,
pagedViewDetails.getNextPageToken(), null);
assertEquals(0, pagedViewDetails.getElements().size());
assertNull(pagedViewDetails.getNextPageToken());
maxResults = 8;
- pagedViewDetails = catalog.listViewDetailsPaged(databaseName,
maxResults, null);
+ pagedViewDetails = catalog.listViewDetailsPaged(databaseName,
maxResults, null, null);
String[] expectedViewNames =
Arrays.stream(viewNames).sorted().toArray(String[]::new);
assertPagedViewDetails(
pagedViewDetails,
@@ -577,7 +695,7 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
assertNull(pagedViewDetails.getNextPageToken());
String pageToken = "view1";
- pagedViewDetails = catalog.listViewDetailsPaged(databaseName,
maxResults, pageToken);
+ pagedViewDetails = catalog.listViewDetailsPaged(databaseName,
maxResults, pageToken, null);
assertPagedViewDetails(pagedViewDetails, view, 2, "view2", "view3");
assertNull(pagedViewDetails.getNextPageToken());
@@ -587,7 +705,39 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
.isThrownBy(
() ->
catalog.listViewDetailsPaged(
- "non_existing_db", finalMaxResults,
pageToken));
+ "non_existing_db", finalMaxResults,
pageToken, null));
+
+ pagedViewDetails = catalog.listViewDetailsPaged(databaseName, null,
null, "view%");
+ assertPagedViewDetails(pagedViewDetails, view, 3, "view1", "view2",
"view3");
+ assertNull(pagedViewDetails.getNextPageToken());
+
+ pagedViewDetails = catalog.listViewDetailsPaged(databaseName, null,
null, "view_");
+ assertPagedViewDetails(pagedViewDetails, view, 3, "view1", "view2",
"view3");
+ assertNull(pagedViewDetails.getNextPageToken());
+
+ pagedViewDetails = catalog.listViewDetailsPaged(databaseName, null,
null, "view%_");
+ assertPagedViewDetails(pagedViewDetails, view, 3, "view1", "view2",
"view3");
+ assertNull(pagedViewDetails.getNextPageToken());
+
+ pagedViewDetails = catalog.listViewDetailsPaged(databaseName, null,
null, "view_%");
+ assertPagedViewDetails(pagedViewDetails, view, 3, "view1", "view2",
"view3");
+ assertNull(pagedViewDetails.getNextPageToken());
+
+ pagedViewDetails = catalog.listViewDetailsPaged(databaseName, null,
null, "vie_");
+ Assertions.assertTrue(pagedViewDetails.getElements().isEmpty());
+ assertNull(pagedViewDetails.getNextPageToken());
+
+ pagedViewDetails = catalog.listViewDetailsPaged(databaseName, null,
null, "view\\_");
+ Assertions.assertTrue(pagedViewDetails.getElements().isEmpty());
+ assertNull(pagedViewDetails.getNextPageToken());
+
+ Assertions.assertThrows(
+ BadRequestException.class,
+ () -> catalog.listViewDetailsPaged(databaseName, null, null,
"vi%ew"));
+
+ Assertions.assertThrows(
+ BadRequestException.class,
+ () -> catalog.listViewDetailsPaged(databaseName, null, null,
"vi_ew"));
}
@Test
@@ -707,7 +857,7 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
assertThrows(
Catalog.TableNotExistException.class,
- () -> catalog.listPartitionsPaged(identifier, 10,
"dt=20250101"));
+ () -> catalog.listPartitionsPaged(identifier, 10,
"dt=20250101", null));
catalog.createTable(
identifier,
@@ -728,7 +878,8 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
}
commit.commit(write.prepareCommit());
}
- PagedList<Partition> pagedPartitions =
catalog.listPartitionsPaged(identifier, null, null);
+ PagedList<Partition> pagedPartitions =
+ catalog.listPartitionsPaged(identifier, null, null, null);
Map[] sortedSpecs =
partitionSpecs.stream()
.sorted(Comparator.comparing(i -> i.get("dt")))
@@ -736,47 +887,78 @@ public abstract class RESTCatalogTest extends
CatalogTestBase {
assertPagedPartitions(pagedPartitions, partitionSpecs.size(),
sortedSpecs);
int maxResults = 2;
- pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
null);
+ pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
null, null);
assertPagedPartitions(
pagedPartitions, maxResults, partitionSpecs.get(2),
partitionSpecs.get(0));
assertEquals("dt=20250101", pagedPartitions.getNextPageToken());
pagedPartitions =
catalog.listPartitionsPaged(
- identifier, maxResults,
pagedPartitions.getNextPageToken());
+ identifier, maxResults,
pagedPartitions.getNextPageToken(), null);
assertPagedPartitions(
pagedPartitions, maxResults, partitionSpecs.get(1),
partitionSpecs.get(5));
assertEquals("dt=20250103", pagedPartitions.getNextPageToken());
pagedPartitions =
catalog.listPartitionsPaged(
- identifier, maxResults,
pagedPartitions.getNextPageToken());
+ identifier, maxResults,
pagedPartitions.getNextPageToken(), null);
assertPagedPartitions(
pagedPartitions, maxResults, partitionSpecs.get(4),
partitionSpecs.get(3));
assertEquals("dt=20260101", pagedPartitions.getNextPageToken());
pagedPartitions =
catalog.listPartitionsPaged(
- identifier, maxResults,
pagedPartitions.getNextPageToken());
+ identifier, maxResults,
pagedPartitions.getNextPageToken(), null);
assertThat(pagedPartitions.getElements()).isEmpty();
assertNull(pagedPartitions.getNextPageToken());
maxResults = 8;
- pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
null);
+ pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
null, null);
assertPagedPartitions(
pagedPartitions, Math.min(maxResults, partitionSpecs.size()),
sortedSpecs);
assertNull(pagedPartitions.getNextPageToken());
- pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
"dt=20250101");
+ pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
null, "dt=2025");
+ assertTrue(pagedPartitions.getElements().isEmpty());
+ assertNull(pagedPartitions.getNextPageToken());
+
+ pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
null, "dt=2025%");
+ assertPagedPartitions(
+ pagedPartitions,
+ 4,
+ partitionSpecs.get(0),
+ partitionSpecs.get(1),
+ partitionSpecs.get(5),
+ partitionSpecs.get(4));
+ assertNull(pagedPartitions.getNextPageToken());
+
+ pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
null, "dt=2025010_");
assertPagedPartitions(
pagedPartitions,
4,
+ partitionSpecs.get(0),
partitionSpecs.get(1),
partitionSpecs.get(5),
- partitionSpecs.get(4),
- partitionSpecs.get(3));
+ partitionSpecs.get(4));
+ assertNull(pagedPartitions.getNextPageToken());
+
+ pagedPartitions =
+ catalog.listPartitionsPaged(identifier, maxResults, null,
"dt=2025010\\_");
+ assertTrue(pagedPartitions.getElements().isEmpty());
+ assertNull(pagedPartitions.getNextPageToken());
+
+ pagedPartitions = catalog.listPartitionsPaged(identifier, maxResults,
null, "dt=202501_");
+ assertTrue(pagedPartitions.getElements().isEmpty());
assertNull(pagedPartitions.getNextPageToken());
+
+ assertThrows(
+ BadRequestException.class,
+ () -> catalog.listPartitionsPaged(identifier, null, null,
"dt=%0101"));
+
+ assertThrows(
+ BadRequestException.class,
+ () -> catalog.listPartitionsPaged(identifier, null, null,
"dt=_0101"));
}
@Test
diff --git
a/paimon-hive/paimon-hive-catalog/src/main/java/org/apache/paimon/hive/HiveCatalog.java
b/paimon-hive/paimon-hive-catalog/src/main/java/org/apache/paimon/hive/HiveCatalog.java
index c802e42cdd..5321eb378f 100644
---
a/paimon-hive/paimon-hive-catalog/src/main/java/org/apache/paimon/hive/HiveCatalog.java
+++
b/paimon-hive/paimon-hive-catalog/src/main/java/org/apache/paimon/hive/HiveCatalog.java
@@ -27,6 +27,7 @@ import org.apache.paimon.catalog.CatalogContext;
import org.apache.paimon.catalog.CatalogLoader;
import org.apache.paimon.catalog.CatalogLockContext;
import org.apache.paimon.catalog.CatalogLockFactory;
+import org.apache.paimon.catalog.CatalogUtils;
import org.apache.paimon.catalog.Identifier;
import org.apache.paimon.catalog.PropertyChange;
import org.apache.paimon.catalog.TableMetadata;
@@ -854,16 +855,28 @@ public class HiveCatalog extends AbstractCatalog {
}
}
+ @Override
+ public PagedList<String> listViewsPaged(
+ String databaseName,
+ @Nullable Integer maxResults,
+ @Nullable String pageToken,
+ @Nullable String viewNamePattern)
+ throws DatabaseNotExistException {
+ CatalogUtils.validateNamePattern(this, viewNamePattern);
+ return new PagedList<>(listViews(databaseName), null);
+ }
+
@Override
public PagedList<View> listViewDetailsPaged(
- String databaseName, Integer maxResults, String pageToken)
+ String databaseName, Integer maxResults, String pageToken, String
viewNamePattern)
throws DatabaseNotExistException {
if (isSystemDatabase(databaseName)) {
return new PagedList<>(Collections.emptyList(), null);
}
getDatabase(databaseName);
- PagedList<String> pagedViewNames = listViewsPaged(databaseName,
maxResults, pageToken);
+ PagedList<String> pagedViewNames =
+ listViewsPaged(databaseName, maxResults, pageToken,
viewNamePattern);
return new PagedList<>(
pagedViewNames.getElements().stream()
.map(
diff --git a/paimon-open-api/rest-catalog-open-api.yaml
b/paimon-open-api/rest-catalog-open-api.yaml
index c6793651b4..669eb4875e 100644
--- a/paimon-open-api/rest-catalog-open-api.yaml
+++ b/paimon-open-api/rest-catalog-open-api.yaml
@@ -232,6 +232,11 @@ paths:
in: query
schema:
type: string
+ - name: tableNamePattern
+ description: A sql LIKE pattern (% and _) for table names.
+ in: query
+ schema:
+ type: string
responses:
"200":
description: OK
@@ -305,6 +310,11 @@ paths:
in: query
schema:
type: string
+ - name: tableNamePattern
+ description: A sql LIKE pattern (% and _) for table names.
+ in: query
+ schema:
+ type: string
responses:
"200":
description: OK
@@ -658,6 +668,11 @@ paths:
in: query
schema:
type: string
+ - name: partitionNamePattern
+ description: A sql LIKE pattern (% and _) for partition names.
+ in: query
+ schema:
+ type: string
responses:
"200":
description: OK
@@ -896,6 +911,11 @@ paths:
in: query
schema:
type: string
+ - name: viewNamePattern
+ description: A sql LIKE pattern (% and _) for view names.
+ in: query
+ schema:
+ type: string
responses:
"200":
description: OK
@@ -969,6 +989,11 @@ paths:
in: query
schema:
type: string
+ - name: viewNamePattern
+ description: A sql LIKE pattern (% and _) for view names.
+ in: query
+ schema:
+ type: string
responses:
"200":
description: OK
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 c27bbbba0a..cee2a50411 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
@@ -261,8 +261,9 @@ public class RESTCatalogController {
public ListTablesResponse listTables(
@PathVariable String prefix,
@PathVariable String database,
- @PathVariable Integer maxResults,
- @PathVariable String pageToken) {
+ @RequestParam(required = false) Integer maxResults,
+ @RequestParam(required = false) String pageToken,
+ @RequestParam(required = false) String tableNamePattern) {
// paged list tables in this database with provided maxResults and
pageToken
return new ListTablesResponse(ImmutableList.of("user"), null);
}
@@ -288,8 +289,9 @@ public class RESTCatalogController {
public ListTableDetailsResponse listTableDetails(
@PathVariable String prefix,
@PathVariable String database,
- @PathVariable Integer maxResults,
- @PathVariable String pageToken) {
+ @RequestParam(required = false) Integer maxResults,
+ @RequestParam(required = false) String pageToken,
+ @RequestParam(required = false) String tableNamePattern) {
// paged list table details in this database with provided maxResults
and pageToken
GetTableResponse singleTable =
new GetTableResponse(
@@ -582,8 +584,9 @@ public class RESTCatalogController {
@PathVariable String prefix,
@PathVariable String database,
@PathVariable String table,
- @PathVariable Integer maxResults,
- @PathVariable String pageToken) {
+ @RequestParam(required = false) Integer maxResults,
+ @RequestParam(required = false) String pageToken,
+ @RequestParam(required = false) String partitionNamePattern) {
// paged list partitions in this table with provided maxResults and
pageToken
Map<String, String> spec = new HashMap<>();
spec.put("f1", "1");
@@ -710,7 +713,7 @@ public class RESTCatalogController {
@PathVariable String branch) {}
@Operation(
- summary = "List view details",
+ summary = "List views",
tags = {"view"})
@ApiResponses({
@ApiResponse(
@@ -720,6 +723,34 @@ public class RESTCatalogController {
responseCode = "401",
description = "Unauthorized",
content = {@Content(schema = @Schema(implementation =
ErrorResponse.class))}),
+ @ApiResponse(
+ responseCode = "500",
+ content = {@Content(schema = @Schema(implementation =
ErrorResponse.class))})
+ })
+ @GetMapping("/v1/{prefix}/databases/{database}/views")
+ public ListViewsResponse listViews(
+ @PathVariable String prefix,
+ @PathVariable String database,
+ @RequestParam(required = false) Integer maxResults,
+ @RequestParam(required = false) String pageToken,
+ @RequestParam(required = false) String viewNamePattern) {
+ // paged list tables in this database with provided maxResults and
pageToken
+ return new ListViewsResponse(ImmutableList.of("user"), null);
+ }
+
+ @Operation(
+ summary = "List view details",
+ tags = {"view"})
+ @ApiResponses({
+ @ApiResponse(
+ responseCode = "200",
+ content = {
+ @Content(schema = @Schema(implementation =
ListViewDetailsResponse.class))
+ }),
+ @ApiResponse(
+ responseCode = "401",
+ description = "Unauthorized",
+ content = {@Content(schema = @Schema(implementation =
ErrorResponse.class))}),
@ApiResponse(
responseCode = "404",
description = "Resource not found",
@@ -732,8 +763,9 @@ public class RESTCatalogController {
public ListViewDetailsResponse listViewDetails(
@PathVariable String prefix,
@PathVariable String database,
- @PathVariable Integer maxResults,
- @PathVariable String pageToken) {
+ @RequestParam(required = false) Integer maxResults,
+ @RequestParam(required = false) String pageToken,
+ @RequestParam(required = false) String viewNamePattern) {
// paged list view details in this database with provided maxResults
and pageToken
List<DataField> fields =
Arrays.asList(