This is an automated email from the ASF dual-hosted git repository.

dengzhhu653 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new d0050d9e85a HIVE-30153: Avoid unnecessary SERDES join in 
PartitionProjectionEvaluator when no serde field is projected (#6864)
d0050d9e85a is described below

commit d0050d9e85a628767e97f02ebceaae6ddea775e2
Author: Yuming Wang <[email protected]>
AuthorDate: Tue Oct 13 07:43:06 2026 +0800

    HIVE-30153: Avoid unnecessary SERDES join in PartitionProjectionEvaluator 
when no serde field is projected (#6864)
---
 .../metastore/PartitionProjectionEvaluator.java    |  4 +-
 .../TestPartitionProjectionEvaluator.java          | 54 ++++++++++++++++++++++
 2 files changed, 55 insertions(+), 3 deletions(-)

diff --git 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/PartitionProjectionEvaluator.java
 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/PartitionProjectionEvaluator.java
index 6841380b24a..b249204ab58 100644
--- 
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/PartitionProjectionEvaluator.java
+++ 
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/PartitionProjectionEvaluator.java
@@ -522,15 +522,13 @@ private int buildQueryForSingleValuedFields(List<Long> 
partitionIds, StringBuild
     queryTextBuilder.append(SPACE);
     queryTextBuilder.append("from " + PARTITIONS);
     // if SD fields are selected add join clause with SDS
-    boolean foundSD = false;
     if (find(SD_PATTERN)) {
       queryTextBuilder.append(SPACE);
       queryTextBuilder.append(
           "left outer join " + SDS + " on " + PARTITIONS + ".\"SD_ID\" = " + 
SDS + ".\"SD_ID\"");
-      foundSD = true;
     }
     // if serde fields are selected add join clause on serdes
-    if (foundSD || find(SERDE_PATTERN)) {
+    if (find(SERDE_PATTERN)) {
       queryTextBuilder.append(SPACE);
       queryTextBuilder.append(
           "  left outer join " + SERDES + " on " + SDS + ".\"SERDE_ID\" = " + 
SERDES
diff --git 
a/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestPartitionProjectionEvaluator.java
 
b/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestPartitionProjectionEvaluator.java
index c40a67b9678..44cea15890a 100644
--- 
a/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestPartitionProjectionEvaluator.java
+++ 
b/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestPartitionProjectionEvaluator.java
@@ -26,11 +26,14 @@
 import org.junit.Assert;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 
 import javax.jdo.PersistenceManager;
+import javax.jdo.Query;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -239,6 +242,57 @@ public void testFind() throws MetaException {
     Assert.assertTrue(projectionEvaluator.find(CD_PATTERN));
   }
 
+  /**
+   * Captures the SQL text that the evaluator hands to the PersistenceManager 
while answering
+   * {@link 
PartitionProjectionEvaluator#getPartitionsUsingProjectionList(List)}, without 
reaching
+   * into any private method. The PersistenceManager/Query are mocked just 
like in the rest of this
+   * test class; the mocked query simply returns no rows so the evaluator 
exits its result loop
+   * immediately after the SQL has been built and submitted.
+   */
+  private String captureGeneratedQuery(PersistenceManager mockPm,
+      List<String> projectionFields) throws Exception {
+    Query mockQuery = Mockito.mock(Query.class);
+    Mockito.when(mockPm.newQuery(Mockito.anyString(), 
Mockito.any())).thenReturn(mockQuery);
+    Mockito.when(mockQuery.execute()).thenReturn(Collections.emptyList());
+
+    PartitionProjectionEvaluator projectionEvaluator =
+        new PartitionProjectionEvaluator(mockPm, fieldNameToColumnName, 
projectionFields, false,
+            false, null, null);
+    Deadline.registerIfNot(100_000);
+    Deadline.startTimer("getPartitionsUsingProjectionList");
+    try {
+      
projectionEvaluator.getPartitionsUsingProjectionList(Collections.singletonList(1L));
+    } finally {
+      Deadline.stopTimer();
+    }
+
+    ArgumentCaptor<String> sqlCaptor = ArgumentCaptor.forClass(String.class);
+    Mockito.verify(mockPm).newQuery(Mockito.eq("javax.jdo.query.SQL"), 
sqlCaptor.capture());
+    return sqlCaptor.getValue();
+  }
+
+  @Test
+  public void testSerdesNotJoinedWhenOnlySdFieldsRequested() throws Exception {
+    String generatedSql = 
captureGeneratedQuery(Mockito.mock(PersistenceManager.class),
+        Arrays.asList("createTime", "sd.location"));
+
+    Assert.assertTrue("sd field is requested, SDS should be joined",
+        generatedSql.contains("join " + "\"SDS\""));
+    Assert.assertFalse("no serde field is requested, SERDES should not be 
joined",
+        generatedSql.contains("\"SERDES\""));
+  }
+
+  @Test
+  public void testSerdesJoinedWhenSerdeFieldRequested() throws Exception {
+    String generatedSql = 
captureGeneratedQuery(Mockito.mock(PersistenceManager.class),
+        Arrays.asList("createTime", "sd.serdeInfo.serializationLib"));
+
+    Assert.assertTrue("sd field is implied by a serde field, SDS should be 
joined",
+        generatedSql.contains("join " + "\"SDS\""));
+    Assert.assertTrue("serde field is requested, SERDES should be joined",
+        generatedSql.contains("join " + "\"SERDES\""));
+  }
+
   @Test(expected = MetaException.class)
   public void testFindNegative() throws MetaException {
     PersistenceManager mockPm = Mockito.mock(PersistenceManager.class);

Reply via email to