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 c8463334a4 [core] Introduce Catalog.listPartitionsByNames (#7340)
c8463334a4 is described below

commit c8463334a4a6149ae064db63477b2201446a1bfe
Author: Jingsong Lee <[email protected]>
AuthorDate: Wed Mar 4 22:20:16 2026 +0800

    [core] Introduce Catalog.listPartitionsByNames (#7340)
---
 docs/static/rest-catalog-open-api.yaml             | 52 +++++++++++++++++++
 .../main/java/org/apache/paimon/rest/RESTApi.java  | 34 ++++++++++++
 .../java/org/apache/paimon/rest/ResourcePaths.java | 12 +++++
 .../requests/ListPartitionsByNamesRequest.java     | 37 +++++++++++++
 .../org/apache/paimon/catalog/AbstractCatalog.java |  7 +++
 .../java/org/apache/paimon/catalog/Catalog.java    | 13 +++++
 .../org/apache/paimon/catalog/CatalogUtils.java    | 26 +++++++---
 .../org/apache/paimon/catalog/DelegateCatalog.java |  7 +++
 .../java/org/apache/paimon/rest/RESTCatalog.java   | 15 ++++++
 .../org/apache/paimon/catalog/CatalogTestBase.java | 60 ++++++++++++++++++++++
 .../org/apache/paimon/rest/RESTCatalogServer.java  | 34 ++++++++++++
 .../org/apache/paimon/rest/RESTCatalogTest.java    | 34 ++++++++++++
 12 files changed, 325 insertions(+), 6 deletions(-)

diff --git a/docs/static/rest-catalog-open-api.yaml 
b/docs/static/rest-catalog-open-api.yaml
index 5c654e4a2f..0fc27922df 100644
--- a/docs/static/rest-catalog-open-api.yaml
+++ b/docs/static/rest-catalog-open-api.yaml
@@ -983,6 +983,48 @@ paths:
           $ref: '#/components/responses/TableNotExistErrorResponse'
         "500":
           $ref: '#/components/responses/ServerErrorResponse'
+  /v1/{prefix}/databases/{database}/tables/{table}/partitions/list-by-names:
+    post:
+      tags:
+        - partition
+      summary: List partitions by names
+      operationId: listPartitionsByNames
+      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/ListPartitionsByNamesRequest'
+      responses:
+        "200":
+          description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ListPartitionsResponse'
+        "400":
+          $ref: '#/components/responses/BadRequestErrorResponse'
+        "401":
+          $ref: '#/components/responses/UnauthorizedErrorResponse'
+        "404":
+          $ref: '#/components/responses/TableNotExistErrorResponse'
+        "500":
+          $ref: '#/components/responses/ServerErrorResponse'
   /v1/{prefix}/databases/{database}/tables/{table}/branches:
     get:
       tags:
@@ -2170,6 +2212,16 @@ components:
           type: array
           items:
             type: object
+    ListPartitionsByNamesRequest:
+      type: object
+      properties:
+        specs:
+          type: array
+          description: List of partition specs to query
+          items:
+            type: object
+            additionalProperties:
+              type: string
     CreateDatabaseResponse:
       type: object
       properties:
diff --git a/paimon-api/src/main/java/org/apache/paimon/rest/RESTApi.java 
b/paimon-api/src/main/java/org/apache/paimon/rest/RESTApi.java
index bfa0b5cb50..8e90eb7542 100644
--- a/paimon-api/src/main/java/org/apache/paimon/rest/RESTApi.java
+++ b/paimon-api/src/main/java/org/apache/paimon/rest/RESTApi.java
@@ -45,6 +45,7 @@ import org.apache.paimon.rest.requests.CreateTableRequest;
 import org.apache.paimon.rest.requests.CreateTagRequest;
 import org.apache.paimon.rest.requests.CreateViewRequest;
 import org.apache.paimon.rest.requests.ForwardBranchRequest;
+import org.apache.paimon.rest.requests.ListPartitionsByNamesRequest;
 import org.apache.paimon.rest.requests.MarkDonePartitionsRequest;
 import org.apache.paimon.rest.requests.RegisterTableRequest;
 import org.apache.paimon.rest.requests.RenameTableRequest;
@@ -106,6 +107,7 @@ import static 
org.apache.paimon.rest.RESTFunctionValidator.checkFunctionName;
 import static org.apache.paimon.rest.RESTFunctionValidator.isValidFunctionName;
 import static org.apache.paimon.rest.RESTUtil.extractPrefixMap;
 import static 
org.apache.paimon.rest.auth.AuthProviderFactory.createAuthProvider;
+import static org.apache.paimon.utils.Preconditions.checkArgument;
 
 /**
  * REST API for REST Catalog.
@@ -822,6 +824,38 @@ public class RESTApi {
         return new PagedList<>(partitions, response.getNextPageToken());
     }
 
+    /**
+     * List partitions by partition names for table.
+     *
+     * @param identifier database name and table name.
+     * @param partitionSpecs partition specs to be queried
+     * @return a list of partitions matching the given partition specs
+     * @throws IllegalArgumentException if the number of partition specs 
exceeds 1000
+     * @throws NoSuchResourceException Exception thrown on HTTP 404 means the 
table not exists
+     * @throws ForbiddenException Exception thrown on HTTP 403 means don't 
have the permission for
+     *     this table
+     */
+    public List<Partition> listPartitionsByNames(
+            Identifier identifier, List<Map<String, String>> partitionSpecs) {
+        checkArgument(
+                partitionSpecs.size() <= 1000,
+                "The number of partition specs must not exceed 1000, but got 
%s",
+                partitionSpecs.size());
+        ListPartitionsByNamesRequest request = new 
ListPartitionsByNamesRequest(partitionSpecs);
+        ListPartitionsResponse response =
+                client.post(
+                        resourcePaths.listPartitionsByNames(
+                                identifier.getDatabaseName(), 
identifier.getObjectName()),
+                        request,
+                        ListPartitionsResponse.class,
+                        restAuthFunction);
+        List<Partition> partitions = response.getPartitions();
+        if (partitions == null) {
+            return emptyList();
+        }
+        return partitions;
+    }
+
     /**
      * Create branch for table.
      *
diff --git a/paimon-api/src/main/java/org/apache/paimon/rest/ResourcePaths.java 
b/paimon-api/src/main/java/org/apache/paimon/rest/ResourcePaths.java
index fdd183a3fc..aaa8b2e297 100644
--- a/paimon-api/src/main/java/org/apache/paimon/rest/ResourcePaths.java
+++ b/paimon-api/src/main/java/org/apache/paimon/rest/ResourcePaths.java
@@ -202,6 +202,18 @@ public class ResourcePaths {
                 "mark");
     }
 
+    public String listPartitionsByNames(String databaseName, String 
objectName) {
+        return SLASH.join(
+                V1,
+                prefix,
+                DATABASES,
+                encodeString(databaseName),
+                TABLES,
+                encodeString(objectName),
+                PARTITIONS,
+                "list-by-names");
+    }
+
     public String branches(String databaseName, String objectName) {
         return SLASH.join(
                 V1,
diff --git 
a/paimon-api/src/main/java/org/apache/paimon/rest/requests/ListPartitionsByNamesRequest.java
 
b/paimon-api/src/main/java/org/apache/paimon/rest/requests/ListPartitionsByNamesRequest.java
new file mode 100644
index 0000000000..7cec810769
--- /dev/null
+++ 
b/paimon-api/src/main/java/org/apache/paimon/rest/requests/ListPartitionsByNamesRequest.java
@@ -0,0 +1,37 @@
+/*
+ * 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.shade.jackson2.com.fasterxml.jackson.annotation.JsonCreator;
+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;
+import java.util.Map;
+
+/** Request for listing partitions by names. */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ListPartitionsByNamesRequest extends BasePartitionsRequest {
+
+    @JsonCreator
+    public ListPartitionsByNamesRequest(
+            @JsonProperty(FIELD_PARTITION_SPECS) List<Map<String, String>> 
partitionSpecs) {
+        super(partitionSpecs);
+    }
+}
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 fb6fe21ac3..709010d2ce 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
@@ -193,6 +193,13 @@ public abstract class AbstractCatalog implements Catalog {
         return new PagedList<>(listPartitions(identifier), null);
     }
 
+    @Override
+    public List<Partition> listPartitionsByNames(
+            Identifier identifier, List<Map<String, String>> partitions)
+            throws TableNotExistException {
+        return CatalogUtils.listPartitionsFromFileSystem(getTable(identifier), 
partitions);
+    }
+
     protected abstract void createDatabaseImpl(String name, Map<String, 
String> properties);
 
     @Override
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 72d35c7a76..79aace221f 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
@@ -403,6 +403,19 @@ public interface Catalog extends AutoCloseable {
             @Nullable String partitionNamePattern)
             throws TableNotExistException;
 
+    /**
+     * Get Partition list by partition names of the table.
+     *
+     * @param identifier path of the table to list partitions
+     * @param partitions partition names to be queried
+     * @return a list of the partitions matching the given partition names
+     * @throws IllegalArgumentException if the number of partition specs 
exceeds 1000
+     * @throws TableNotExistException if the table does not exist
+     */
+    List<Partition> listPartitionsByNames(
+            Identifier identifier, List<Map<String, String>> partitions)
+            throws TableNotExistException;
+
     // ======================= view 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 d766e114c0..3059af4d5e 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
@@ -54,10 +54,12 @@ import javax.annotation.Nullable;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Set;
 import java.util.function.Function;
 
 import static org.apache.paimon.CoreOptions.AUTO_CREATE;
@@ -192,6 +194,11 @@ public class CatalogUtils {
     }
 
     public static List<Partition> listPartitionsFromFileSystem(Table table) {
+        return listPartitionsFromFileSystem(table, null);
+    }
+
+    public static List<Partition> listPartitionsFromFileSystem(
+            Table table, @Nullable List<Map<String, String>> partitionSpecs) {
         Options options = Options.fromMap(table.options());
         InternalRowPartitionComputer computer =
                 new InternalRowPartitionComputer(
@@ -204,17 +211,24 @@ public class CatalogUtils {
 
         // partitions should be seen even all files are level-0 when enable 
dv, see
         // https://github.com/apache/paimon/pull/6531 for details
-        List<PartitionEntry> partitionEntries;
         if (scan instanceof InnerTableScan) {
-            partitionEntries =
-                    ((InnerTableScan) scan).withLevelFilter(level -> 
true).listPartitionEntries();
-        } else {
-            partitionEntries = scan.listPartitionEntries();
+            ((InnerTableScan) scan).withLevelFilter(level -> true);
+            if (partitionSpecs != null) {
+                ((InnerTableScan) scan).withPartitionsFilter(partitionSpecs);
+            }
         }
 
+        List<PartitionEntry> partitionEntries = scan.listPartitionEntries();
+
         List<Partition> partitions = new ArrayList<>(partitionEntries.size());
+        Set<Map<String, String>> filterSet =
+                partitionSpecs == null ? null : new HashSet<>(partitionSpecs);
         for (PartitionEntry entry : partitionEntries) {
-            partitions.add(entry.toPartition(computer));
+            Partition partition = entry.toPartition(computer);
+            if (filterSet != null && !filterSet.contains(partition.spec())) {
+                continue;
+            }
+            partitions.add(partition);
         }
         return partitions;
     }
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 12505698db..3f1ea209a9 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
@@ -423,6 +423,13 @@ public abstract class DelegateCatalog implements Catalog {
         return wrapped.listPartitionsPaged(identifier, maxResults, pageToken, 
partitionNamePattern);
     }
 
+    @Override
+    public List<Partition> listPartitionsByNames(
+            Identifier identifier, List<Map<String, String>> partitions)
+            throws TableNotExistException {
+        return wrapped.listPartitionsByNames(identifier, partitions);
+    }
+
     @Override
     public TableQueryAuthResult authTableQuery(Identifier identifier, 
@Nullable List<String> select)
             throws TableNotExistException {
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 30e53de66b..6c6344bfc7 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
@@ -646,6 +646,21 @@ public class RESTCatalog implements Catalog {
         }
     }
 
+    @Override
+    public List<Partition> listPartitionsByNames(
+            Identifier identifier, List<Map<String, String>> partitions)
+            throws TableNotExistException {
+        try {
+            return api.listPartitionsByNames(identifier, partitions);
+        } catch (NoSuchResourceException e) {
+            throw new TableNotExistException(identifier);
+        } catch (ForbiddenException e) {
+            throw new TableNoPermissionException(identifier, e);
+        } catch (NotImplementedException e) {
+            return listPartitionsFromFileSystem(getTable(identifier), 
partitions);
+        }
+    }
+
     @Override
     public void createBranch(Identifier identifier, String branch, @Nullable 
String fromTag)
             throws TableNotExistException, BranchAlreadyExistException, 
TagNotExistException {
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 18a649b67c..b3a9d93e45 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
@@ -77,6 +77,7 @@ import java.util.Map;
 import java.util.Random;
 import java.util.stream.Collectors;
 
+import static java.util.Collections.singletonMap;
 import static org.apache.paimon.CoreOptions.METASTORE_PARTITIONED_TABLE;
 import static org.apache.paimon.CoreOptions.METASTORE_TAG_TO_PARTITION;
 import static org.apache.paimon.CoreOptions.TYPE;
@@ -1545,6 +1546,65 @@ public abstract class CatalogTestBase {
                 () -> catalog.listPartitionsPaged(identifier, null, null, 
"dt=0101"));
     }
 
+    @Test
+    public void testListPartitionsByNames() throws Exception {
+        if (!supportPartitions()) {
+            return;
+        }
+
+        String databaseName = "partitions_by_names_db";
+        List<Map<String, String>> partitionSpecs =
+                Arrays.asList(
+                        singletonMap("dt", "20250101"),
+                        singletonMap("dt", "20250102"),
+                        singletonMap("dt", "20240102"),
+                        singletonMap("dt", "20260101"));
+
+        catalog.dropDatabase(databaseName, true, true);
+        catalog.createDatabase(databaseName, true);
+        Identifier identifier = Identifier.create(databaseName, "table");
+
+        catalog.createTable(
+                identifier,
+                Schema.newBuilder()
+                        .option(METASTORE_PARTITIONED_TABLE.key(), "true")
+                        .option(METASTORE_TAG_TO_PARTITION.key(), "dt")
+                        .column("col", DataTypes.INT())
+                        .column("dt", DataTypes.STRING())
+                        .partitionKeys("dt")
+                        .build(),
+                true);
+
+        BatchWriteBuilder writeBuilder = 
catalog.getTable(identifier).newBatchWriteBuilder();
+        try (BatchTableWrite write = writeBuilder.newWrite();
+                BatchTableCommit commit = writeBuilder.newCommit()) {
+            for (Map<String, String> partitionSpec : partitionSpecs) {
+                write.write(GenericRow.of(0, 
BinaryString.fromString(partitionSpec.get("dt"))));
+            }
+            commit.commit(write.prepareCommit());
+        }
+
+        // Test listing partitions by names
+        List<Map<String, String>> specsToQuery =
+                Arrays.asList(singletonMap("dt", "20250101"), 
singletonMap("dt", "20250102"));
+        List<Partition> partitions = catalog.listPartitionsByNames(identifier, 
specsToQuery);
+
+        
assertThat(partitions.stream().map(Partition::spec).collect(Collectors.toList()))
+                .containsExactlyInAnyOrderElementsOf(specsToQuery);
+
+        // Test with non-existent partition spec
+        List<Map<String, String>> nonExistentSpecs =
+                Arrays.asList(singletonMap("dt", "20990101"), 
singletonMap("dt", "20990102"));
+        List<Partition> emptyPartitions =
+                catalog.listPartitionsByNames(identifier, nonExistentSpecs);
+        assertEquals(0, emptyPartitions.size());
+
+        // Test with empty partition specs
+        List<Partition> emptyResult =
+                catalog.listPartitionsByNames(identifier, 
Collections.emptyList());
+        assertEquals(0, emptyResult.size());
+    }
+
     protected boolean supportsAlterDatabase() {
         return false;
     }
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 98e1beddda..5d8c5ab3cb 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
@@ -57,6 +57,7 @@ import org.apache.paimon.rest.requests.CreateFunctionRequest;
 import org.apache.paimon.rest.requests.CreateTableRequest;
 import org.apache.paimon.rest.requests.CreateTagRequest;
 import org.apache.paimon.rest.requests.CreateViewRequest;
+import org.apache.paimon.rest.requests.ListPartitionsByNamesRequest;
 import org.apache.paimon.rest.requests.MarkDonePartitionsRequest;
 import org.apache.paimon.rest.requests.RenameTableRequest;
 import org.apache.paimon.rest.requests.RollbackTableRequest;
@@ -133,6 +134,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -413,6 +415,12 @@ public class RESTCatalogServer {
                                         && "partitions".equals(resources[3])
                                         && "mark".equals(resources[4]);
 
+                        boolean isListPartitionsByNames =
+                                resources.length == 5
+                                        && 
ResourcePaths.TABLES.equals(resources[1])
+                                        && "partitions".equals(resources[3])
+                                        && 
"list-by-names".equals(resources[4]);
+
                         boolean isBranches =
                                 resources.length >= 4
                                         && 
ResourcePaths.TABLES.equals(resources[1])
@@ -460,6 +468,13 @@ public class RESTCatalogServer {
                         } else if (isPartitions) {
                             return partitionsApiHandle(
                                     restAuthParameter.method(), parameters, 
identifier);
+                        } else if (isListPartitionsByNames) {
+                            ListPartitionsByNamesRequest 
listPartitionsByNamesRequest =
+                                    RESTApi.fromJson(data, 
ListPartitionsByNamesRequest.class);
+                            return listPartitionsByNames(
+                                    parameters,
+                                    identifier,
+                                    
listPartitionsByNamesRequest.getPartitionSpecs());
                         } else if (isBranches) {
                             return branchApiHandle(
                                     resources,
@@ -1697,6 +1712,25 @@ public class RESTCatalogServer {
         }
     }
 
+    private MockResponse listPartitionsByNames(
+            Map<String, String> parameters,
+            Identifier tableIdentifier,
+            List<Map<String, String>> partitionSpecs) {
+        List<Partition> partitions = new ArrayList<>();
+        Set<Map<String, String>> partitionSpecSet = new 
HashSet<>(partitionSpecs);
+        for (Map.Entry<String, List<Partition>> entry : 
tablePartitionsStore.entrySet()) {
+            String objectName = 
Identifier.fromString(entry.getKey()).getObjectName();
+            if (objectName.equals(tableIdentifier.getObjectName())) {
+                for (Partition partition : entry.getValue()) {
+                    if (partitionSpecSet.contains(partition.spec())) {
+                        partitions.add(partition);
+                    }
+                }
+            }
+        }
+        return generateFinalListPartitionsResponse(parameters, partitions);
+    }
+
     private MockResponse branchApiHandle(
             String[] resources, String method, String data, Identifier 
identifier)
             throws Exception {
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 8c5fdf5459..0c17d9029c 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
@@ -1641,6 +1641,40 @@ public abstract class RESTCatalogTest extends 
CatalogTestBase {
         assertPagedPartitions(pagedPartitions, 1, partitionSpecs.get(1));
     }
 
+    @Test
+    public void testListPartitionsByNamesExceedsLimit() throws Exception {
+        if (!supportPartitions()) {
+            return;
+        }
+
+        String databaseName = "partitions_by_names_limit_db";
+        catalog.dropDatabase(databaseName, true, true);
+        catalog.createDatabase(databaseName, true);
+        Identifier identifier = Identifier.create(databaseName, "table");
+
+        catalog.createTable(
+                identifier,
+                Schema.newBuilder()
+                        .option(METASTORE_PARTITIONED_TABLE.key(), "true")
+                        .option(METASTORE_TAG_TO_PARTITION.key(), "dt")
+                        .column("col", DataTypes.INT())
+                        .column("dt", DataTypes.STRING())
+                        .partitionKeys("dt")
+                        .build(),
+                true);
+
+        // Create a list with more than 1000 partition specs
+        List<Map<String, String>> tooManySpecs = new ArrayList<>();
+        for (int i = 0; i < 1001; i++) {
+            tooManySpecs.add(singletonMap("dt", String.format("202501%04d", 
i)));
+        }
+
+        // Should throw IllegalArgumentException
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> catalog.listPartitionsByNames(identifier, tooManySpecs));
+    }
+
     @Test
     void testPartitionExpire() throws Exception {
         // create table

Reply via email to