github-actions[bot] commented on code in PR #65591:
URL: https://github.com/apache/doris/pull/65591#discussion_r3612931048
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/AccessPathExpressionCollector.java:
##########
@@ -334,6 +338,23 @@ public Void visitElementAt(ElementAt elementAt,
CollectorContext context) {
Expression fieldName = arguments.get(1);
DataType fieldType = fieldName.getDataType();
if (fieldName.isLiteral() && (fieldType.isIntegerLikeType() ||
fieldType.isStringLikeType())) {
+ // element_at(s, 'field') IS NULL has two-layer null semantics:
+ // s IS NULL OR s.field IS NULL
+ // Always emit META [s, NULL] for the struct-level null map.
+ // Only emit META [s, field, NULL] when the selected field
itself is nullable.
+ if (context.type == ColumnAccessPathType.META
+ &&
isUnderIsNull(context.accessPathBuilder.getPathList())) {
+ StructField field = resolveStructField(
+ (StructType) first.getDataType(), fieldName);
+ // Path 1: struct-level null check — bypass field prefix
+ continueCollectAccessPath(first, copyContext(context));
Review Comment:
[P1] Do not map expression nullability to a non-null Struct
This unconditional ancestor walk can emit a physical NULL path for a node
that has no null map. With `s STRUCT<f:INT NOT NULL> NOT NULL`, a
predicate-only `element_at(s, 'f') IS NULL` emits only typed META `[s,NULL]`:
`ElementAt` is always nullable, then the non-nullable-field branch returns
early. The same happens through `element_at(if(id = 1, NULL, s), 'f')`, where
synthetic `IF` nullability is forwarded to the physical `s` slot. The BE makes
the root Struct `NULL_MAP_ONLY`, but this slot creates a plain `ColumnStruct`,
so `StructFileColumnIterator::next_batch` fails its `is_column_nullable(*dst)`
check. This is distinct from the existing nullable-parent/non-nullable-leaf
thread: the current fix redirects that case to a real parent null map, whereas
these paths target a root with no map. Please track physical nullability
through the ancestor/wrapper path and retain DATA (or disable metadata pruning)
when no real null map can answer the expression; add direct and IF-wrapped all-
NOT-NULL regressions.
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/AccessPathExpressionCollector.java:
##########
@@ -334,6 +338,23 @@ public Void visitElementAt(ElementAt elementAt,
CollectorContext context) {
Expression fieldName = arguments.get(1);
DataType fieldType = fieldName.getDataType();
if (fieldName.isLiteral() && (fieldType.isIntegerLikeType() ||
fieldType.isStringLikeType())) {
+ // element_at(s, 'field') IS NULL has two-layer null semantics:
+ // s IS NULL OR s.field IS NULL
+ // Always emit META [s, NULL] for the struct-level null map.
+ // Only emit META [s, field, NULL] when the selected field
itself is nullable.
+ if (context.type == ColumnAccessPathType.META
+ &&
isUnderIsNull(context.accessPathBuilder.getPathList())) {
+ StructField field = resolveStructField(
+ (StructType) first.getDataType(), fieldName);
+ // Path 1: struct-level null check — bypass field prefix
+ continueCollectAccessPath(first, copyContext(context));
+ if (field != null && !field.isNullable()) {
+ // Non-nullable leaf: struct-level NULL is sufficient
+ return null;
Review Comment:
[P1] Keep the field referenced by the unchanged predicate
The early return drops a field that the filter expression still references.
For the reduced plan
```text
Project(element_at(s, 'g'))
Filter(element_at(s, 'f') IS NULL)
Scan(s STRUCT<f:INT NOT NULL,g:INT> NULL)
```
the projection records DATA `[s,g]`, line 350 records META `[s,NULL]`, and
this branch returns without any `f` path. Because the Struct now has a parent
NULL path plus a partial child, `DataTypeAccessTree.pruneDataType` produces
`STRUCT<g>`. `SlotTypeReplacer` then rebuilds the unchanged filter on that
pruned slot with signature reuse disabled, so `ElementAt.structFieldType`
cannot find `f` (and the materialized Struct could not evaluate it either). A
parent null map is a valid semantic shortcut only if the predicate is also
rewritten to test the parent; otherwise preserve `f` in the pruned type/data
paths. Please add nullable-root sibling-projection regressions for both `IS
NULL` and `IS NOT NULL`.
--
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]