github-actions[bot] commented on code in PR #67725:
URL: https://github.com/apache/doris/pull/67725#discussion_r4002323094


##########
fe/fe-connector/fe-connector-hive/src/main/java/org/apache/doris/connector/hive/HiveScanPlanProvider.java:
##########
@@ -279,6 +278,21 @@ public List<ConnectorScanRange> planScanForPartitionBatch(
         return ranges;
     }
 
+    private List<HmsPartitionInfo> resolveBatchPartitions(HiveTableHandle 
handle, List<String> partitionBatch) {
+        if (handle.getPrunedPartitionsByName().isEmpty()) {
+            return loadPartitionsWithProfile(handle.getDbName(), 
handle.getTableName(), partitionBatch);
+        }
+        List<HmsPartitionInfo> partitions = new 
ArrayList<>(partitionBatch.size());
+        for (String partitionName : partitionBatch) {
+            HmsPartitionInfo partition = 
handle.getPrunedPartitionsByName().get(partitionName);

Review Comment:
   [P1] Do not assume the physical handle covers the logical batch
   
   This new lookup can reject a name selected under different predicate 
semantics. For a STRING-partitioned table with `p=1` and `p=01`, `CAST(p AS 
INT)=1` is rejected by the Nereids connector converter, so typed logical 
pruning selects both; the physical converter strips the CAST, and Hive builds a 
handle/map only for bare `p='1'`. When batch mode is used, `p=01` now reaches 
the missing-partition exception below. The base batch path fetched the 
requested names directly and read both, so this is a new batch regression even 
though the analogous synchronous defect predates this PR. This is also distinct 
from the earlier two-generation thread: no HMS mutation is required. Please 
fall back to loading batch names unless the native map is proven to represent 
the same logical selection (or align the two converters), and add a 
forced-batch CAST case.



##########
fe/fe-connector/fe-connector-hive/src/main/java/org/apache/doris/connector/hive/HiveConnectorMetadata.java:
##########
@@ -2492,6 +2587,99 @@ private List<String> prunePartitionNames(List<String> 
allPartNames,
         return matched;
     }
 
+    private static String buildHmsPartitionFilter(List<String> partKeyNames, 
Map<String, String> partKeyTypes,
+            Map<String, List<String>> partitionPredicates) {
+        List<String> filters = new ArrayList<>();
+        for (String partKeyName : partKeyNames) {
+            List<String> values = partitionPredicates.get(partKeyName);
+            if (values == null || values.isEmpty()) {
+                continue;
+            }
+            if (!isHmsFilterIdentifier(partKeyName)) {
+                return null;
+            }
+            List<String> valueFilters = new ArrayList<>();
+            for (String value : values) {
+                String literal = toHmsFilterLiteral(value, 
partKeyTypes.get(partKeyName));
+                if (literal == null) {
+                    return null;
+                }
+                valueFilters.add(partKeyName + " = " + literal);
+            }
+            filters.add(valueFilters.size() == 1 ? valueFilters.get(0)
+                    : "(" + String.join(" OR ", valueFilters) + ")");
+        }
+        return filters.isEmpty() ? null : "(" + String.join(" AND ", filters) 
+ ")";
+    }
+
+    private static boolean isHmsFilterIdentifier(String value) {
+        if (value.isEmpty() || !isHmsFilterLetterOrDigit(value.charAt(0))) {

Review Comment:
   [P2] Reject Hive filter keywords as identifiers
   
   A valid quoted/API-created partition key such as lowercase `date` passes 
this check, but Hive 3.1.3's case-insensitive filter lexer tokenizes it as 
`KW_DATE`, while a key operand must be `Identifier`. Every equality/IN query on 
that schema therefore sends a predictably invalid RPC, taints/destroys the 
borrowed client, logs a warning, and falls back to unbounded partition-name 
enumeration; the uncached path repeats this on later queries. Please validate 
against the filter grammar's reserved tokens (and other lexer collisions such 
as all-digit names) and add a parser-backed `date` partition-key case.



##########
fe/fe-connector/fe-connector-hive/src/main/java/org/apache/doris/connector/hive/HiveConnectorMetadata.java:
##########
@@ -1288,6 +1279,106 @@ private List<ConnectorPartitionInfo> 
listPartitionsUncached(HiveTableHandle hive
         return result;
     }
 
+    private PartitionPruningResult prunePartitions(ConnectorSession session, 
HiveTableHandle hiveHandle,
+            ConnectorExpression expression) {
+        List<String> partKeyNames = hiveHandle.getPartitionKeyNames();
+        Map<String, List<String>> partitionPredicates = 
extractPartitionPredicates(expression, partKeyNames);
+        if (partitionPredicates.isEmpty()) {
+            return null;
+        }
+
+        String hmsFilter = buildHmsPartitionFilter(partKeyNames, 
hiveHandle.getPartitionKeyTypes(),
+                partitionPredicates);
+        if (hmsFilter != null) {
+            int predicateValueCount = 
partitionPredicates.values().stream().mapToInt(List::size).sum();
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("HMS partition filter request for {}.{} 
predicateValues={} filter={}",
+                        hiveHandle.getDbName(), hiveHandle.getTableName(), 
predicateValueCount,
+                        summarizeHmsFilterForDebug(hmsFilter));
+            }
+            try {
+                List<HmsPartitionInfo> prunedPartitions = 
hmsClient.listPartitionsByFilter(
+                        hiveHandle.getDbName(), hiveHandle.getTableName(), 
hmsFilter);
+                LOG.info("Partition pruning through HMS filter: {}.{} 
predicateValues={} pruned={}",
+                        hiveHandle.getDbName(), hiveHandle.getTableName(), 
predicateValueCount,
+                        prunedPartitions.size());
+                return new PartitionPruningResult(prunedPartitions, null);
+            } catch (HmsPartitionFilterSaturatedException e) {
+                LOG.info("HMS partition filter response saturated for {}.{} 
predicateValues={}; "
+                                + "falling back to local partition pruning",
+                        hiveHandle.getDbName(), hiveHandle.getTableName(), 
predicateValueCount);
+            } catch (HmsClientException | UnsupportedOperationException e) {
+                LOG.warn("Failed to prune Hive partitions through HMS filter 
for {}.{} predicateValues={}; "
+                                + "falling back to local partition pruning",
+                        hiveHandle.getDbName(), hiveHandle.getTableName(), 
predicateValueCount, e);
+            }
+        }
+
+        List<String> allPartNames = hmsClient.listPartitionNames(
+                hiveHandle.getDbName(), hiveHandle.getTableName(), -1);
+        List<String> matchedPartNames = prunePartitionNames(

Review Comment:
   [P1] Keep the local fallback conservative for batched pruning
   
   The result of this raw-name prefilter is now reused as the logical selected 
view, so textually different but type-equal values can be lost before 
`PartitionPruner` runs. For example, a valid quoted partition key such as `p-x` 
forces the HMS builder to fall back; an INT partition value `01` and predicate 
`` `p-x` = 1 `` both parse to integer 1, but `matchesPredicates` compares 
`"01"` with `"1"` and drops that partition. Base batch planning still loaded 
the typed logical name set directly; the new carried fallback makes batch scans 
omit it too. Please decline connector filtering/materialize the full view on 
fallback, or compare with the declared partition type, and add a 
fallback-forced batch test with `01` and `1`.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to