mrhhsg commented on code in PR #67713:
URL: https://github.com/apache/doris/pull/67713#discussion_r4069779044
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/ExpressionAnalyzer.java:
##########
@@ -511,6 +516,36 @@ protected boolean shouldPrioritizeRelationQualifier() {
return lambdaAnalyzer.analyze(lambdaFunction, context);
}
+ /**
+ * Build the scope of a lambda body. The lambda arguments shadow the
same-named slots that are visible
+ * to the enclosing expression, and the enclosing scope becomes the outer
scope. Slot binding only looks
+ * one level up, so when this analyzer itself analyzes a lambda body
(nested high-order functions), the
+ * scope of this analyzer only holds the enclosing lambda arguments: merge
them into the new scope and keep
+ * the plan scope as the outer scope, so that the columns captured by the
nested lambda body stay bindable.
+ */
+ private Scope newLambdaScope(List<Slot> lambdaArgumentSlots) {
Review Comment:
Done in d8de8168105. The branch is rebased onto current master (no merge
commit) and the production change is dropped entirely: #68260's
enclosing-analyzer delegation already binds query columns at any lambda nesting
depth, so `newLambdaScope`/`isLambdaBodyAnalyzer` are gone. The PR is now
test-only coverage (title/description updated accordingly).
##########
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/analysis/BindFunctionTest.java:
##########
@@ -74,4 +89,63 @@ void testJoinBindFunction() {
).when(join -> join.getHashJoinConjuncts().size() == 1)
);
}
+
+ @Test
+ void testNestedLambdaCapturesOuterColumn() {
+ List<String> sqls = ImmutableList.of(
+ "SELECT array_map(a -> array_sum(array_map(b -> if(flag, b,
0), arr2)), arr1) FROM t_arr",
+ "SELECT array_map(a -> array_sum(array_sortby(b -> if(flag, b,
0), arr2)), arr1) FROM t_arr",
+ "SELECT array_map(a -> array_map(b -> array_map(c -> if(flag,
b + c, id), arr2), arr2), arr1)"
+ + " FROM t_arr"
+ );
+ for (String sql : sqls) {
+ Lambda innermostLambda =
innermostLambda(PlanChecker.from(connectContext).analyze(sql).getPlan());
+ // getInputSlots() never contains the lambda argument slots
+ Set<String> capturedColumns =
innermostLambda.getLambdaFunction().getInputSlots().stream()
+ .map(Slot::getName)
+ .collect(Collectors.toSet());
+ Assertions.assertTrue(capturedColumns.contains("flag"), sql);
+ }
+ }
+
+ @Test
+ void testNestedLambdaSeesAllEnclosingLambdaArguments() {
+ String sql = "SELECT array_map(a -> array_map(b -> array_map(c ->
concat(a, b, c), arr1), arr1), arr1)"
+ + " FROM t_arr";
+ Lambda innermostLambda =
innermostLambda(PlanChecker.from(connectContext).analyze(sql).getPlan());
+ Set<ArrayItemSlot> lambdaArguments =
innermostLambda.getLambdaFunction()
+ .collect(ArrayItemSlot.class::isInstance);
+ Assertions.assertEquals(ImmutableList.of("a", "b", "c"),
+
lambdaArguments.stream().map(Slot::getName).sorted().collect(Collectors.toList()));
+ }
+
+ @Test
+ void testNestedLambdaArgumentShadowsEnclosingArgument() {
+ String sql = "SELECT array_map(x -> array_map(x -> x + 1, arr2), arr1)
FROM t_arr";
+ Lambda innermostLambda =
innermostLambda(PlanChecker.from(connectContext).analyze(sql).getPlan());
+ Set<ArrayItemSlot> bodySlots =
innermostLambda.getLambdaFunction().collect(ArrayItemSlot.class::isInstance);
+ Assertions.assertEquals(1, bodySlots.size());
+
Assertions.assertEquals(innermostLambda.getLambdaArgument(0).getExprId(),
+ bodySlots.iterator().next().getExprId());
+
Assertions.assertTrue(innermostLambda.getLambdaFunction().getInputSlots().isEmpty());
+ }
+
+ @Test
+ void testNestedLambdaUnknownSlot() {
+ String sql = "SELECT array_map(a -> array_map(b -> unknown_col + b,
arr2), arr1) FROM t_arr";
+ AnalysisException exception =
Assertions.assertThrows(AnalysisException.class,
+ () -> PlanChecker.from(connectContext).analyze(sql));
+ Assertions.assertTrue(exception.getMessage().contains("Unknown lambda
slot 'unknown_col"),
Review Comment:
Done in d8de8168105. Both negative expectations now match the reachable
diagnostic emitted by the query analyzer: `Unknown column 'unknown_col'` (full
message on master: `Unknown column 'unknown_col' in 'table list' in PROJECT
clause`). Verified by running `BindFunctionTest` (6/6 pass) and the
`test_nested_array_map` regression suite against a current-master cluster.
--
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]