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


##########
fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/PruneNestedColumnTest.java:
##########
@@ -1791,4 +2000,152 @@ private void assertVariantSubColumnSlotCount(String 
sql, List<String> expectedSu
 
         Assertions.assertEquals(expectedCount, actualCount);
     }
+
+    /**
+     * Verify that synthetic nullability from outer join does NOT cause META 
NULL paths
+     * on physically NOT NULL columns. When a NOT NULL struct sits on the 
nullable side
+     * of a LEFT JOIN, the slot's {@code nullable()} returns true (from outer 
join
+     * semantics), but {@code getOriginalColumn().isAllowNull()} returns false
+     * (physical column has no null map). The fix in 
AccessPathExpressionCollector
+     * should suppress the {@code [s, NULL]} META path in this case.
+     */
+    @Test
+    public void testNotNullStructOnOuterJoinNullableSide() throws Exception {
+        // driving_tbl LEFT JOIN not_null_struct_tbl:
+        //   not_null_struct_tbl.s is NOT NULL in the schema, but after LEFT 
JOIN the
+        //   slot becomes nullable (right side of LEFT JOIN → 
withNullable(true)).
+        //   element_at(s, 'f') IS NULL in WHERE:
+        //     - s.nullable() = true   (synthetic, from outer join)
+        //     - s.getOriginalColumn().isAllowNull() = false  (physical, no 
null map)
+        //   Expected: [s, f] DATA is present (field is read for IS NULL 
evaluation),
+        //             [s, NULL] META must NOT be present (no physical null 
map).
+        assertAllAccessPathsContain(
+                "select driving_tbl.id from driving_tbl"
+                        + " left join not_null_struct_tbl"
+                        + " on driving_tbl.id = not_null_struct_tbl.id"
+                        + " where element_at(not_null_struct_tbl.s, 'f') is 
null",
+                // expect-contain: field is read (DATA path)
+                ImmutableList.of(path("s", "f")),

Review Comment:
   I checked this against the real plan data before changing anything, and the 
expectation is correct as written: with `path("s", "f")` the test passes 
(`./run-fe-ut.sh --run 
org.apache.doris.nereids.rules.rewrite.PruneNestedColumnTest` → 64 tests, 0 
failures). When I first applied the suggested `metaPath("s", "f", "NULL")` the 
assertion printed the complete collected set:
   
   ```
   allAccessPaths=[TColumnAccessPath(type:DATA, 
data_access_path:TDataAccessPath(path:[s, f]), version:1)]
   ```
   
   So no field-level META path is produced for this query — the field ends up 
materialized as data because the `IS NULL` is evaluated above the LEFT JOIN 
rather than as a scan predicate. (The field-level META form does show up in 
`testNullableFieldPreservedWithSiblingProjection`, where the null check sits 
directly on the scan of a nullable struct column.)
   
   The underlying point is fair though: this SQL never produces a root `[s, 
NULL]` candidate, so the negative assertion was not really exercising the 
suppression. I added `testNotNullStructIsNullOnOuterJoinNullableSide` — `select 
not_null_struct_tbl.s is null from driving_tbl left join not_null_struct_tbl 
...` — a direct null check on the physically NOT NULL struct, which is the 
shape that reaches the `hasPhysicalNullMap` guard in `visitSlotReference`. It 
asserts that the struct slot is still present in the plan and that no `[s, 
NULL]` META path is emitted. It is kept in the SELECT list on purpose: in a 
WHERE clause the null-rejecting predicate lets the optimizer rewrite the LEFT 
JOIN into an anti join, which drops the struct from the plan and would make the 
assertion vacuous again.



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