englefly commented on code in PR #69340:
URL: https://github.com/apache/doris/pull/69340#discussion_r4332426708


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/AccessPathExpressionCollector.java:
##########
@@ -576,11 +576,32 @@ public Void visitArrayMap(ArrayMap arrayMap, 
CollectorContext context) {
 
         Expression argument = arrayMap.getArgument(0);
         if ((argument instanceof Lambda)) {
-            return collectArrayPathInLambda((Lambda) argument, context);
+            Lambda lambda = (Lambda) argument;
+            return collectArrayMapPathInLambda(lambda, context);
         }
         return visit(arrayMap, context);
     }
 
+    private Void collectArrayMapPathInLambda(Lambda lambda, CollectorContext 
context) {
+        if (context.getType() == ColumnAccessPathType.META) {
+            // A metadata requirement on the ARRAY_MAP result (OFFSET for 
cardinality(), NULL for
+            // IS NULL) describes the output ARRAY container, not the lambda 
elements. The output
+            // container is shaped by the input arrays: array_map copies the 
first input's offsets
+            // and its null map is the union of all inputs' null maps. Pushing 
that context into
+            // the lambda body would attach the metadata to the element layer 
instead, producing
+            // e.g. `arr.*.OFFSET`, which the BE rejects for a struct element 
(OFFSET metadata is
+            // only supported at array/map/string level). Route the container 
metadata to the
+            // input arrays, and collect the element paths the lambda actually 
reads with a fresh
+            // data context so that the elements stay available to the lambda 
body.
+            for (ArrayItemReference lambdaArgument : 
lambda.getLambdaArguments()) {
+                continueCollectAccessPath(lambdaArgument.getArrayExpression(), 
copyContext(context));

Review Comment:
   Fixed in 5d0d5dc6f36. The finding was correct and reproducible on a local 
FE/BE cluster.
   
   - Added `isRootContainerMetadata`: only an unprefixed `[OFFSET]` / `[NULL]` 
request describes the ARRAY_MAP result's own container and is routed to the 
input arrays.
   - A prefixed request such as the `[*, OFFSET]` of 
`cardinality(element_at(array_map(...), 1))` keeps the previous 
`collectArrayPathInLambda` traversal, which drops the unrepresentable metadata 
and preserves the lambda payload.
   - Added unit case `testArrayMapResultElementMetadataKeepsLambdaPayloadOnly` 
and regression cases `array_map_result_element_cardinality` / 
`array_map_result_element_is_null` (plus two explain guards) with a selected 
ARRAY_MAP result whose element type differs from the input.
   
   Verification for `a ARRAY<STRUCT<v:INT>>` and 
`cardinality(element_at(array_map(x -> array(x.v), a), 1))`:
   
   ```
   before: all access paths: [a.*.v, a.*.OFFSET]  ->  [E-3110] Invalid META 
access path ... OFFSET metadata is not supported at this level
   after:  all access paths: [a.*.v]              ->  1, NULL, NULL   (same as 
nested column pruning disabled)
   ```
   
   Root-container cases are unchanged (`[a.*, a.OFFSET]`, `[s.arr.*, 
s.arr.OFFSET]`, `[m.KEYS, m.VALUES.*, m.VALUES.OFFSET]`, `[a.*, a.NULL]`). 
`PruneNestedColumnTest` passes 79/79 and the whole 
`nereids_rules_p0/column_pruning` directory (16 suites) passes.
   



-- 
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