github-actions[bot] commented on code in PR #67154:
URL: https://github.com/apache/doris/pull/67154#discussion_r3877950062
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ComputeSignatureHelper.java:
##########
@@ -566,52 +577,434 @@ private static FunctionSignature
defaultTimePrecisionPromotion(FunctionSignature
}
private static FunctionSignature defaultDecimalV3PrecisionPromotion(
- FunctionSignature signature, List<Expression> arguments) {
- DecimalV3Type finalType = null;
+ FunctionSignature signature, List<Expression> arguments,
ComputeSignature computeSignature) {
+ // The wider type across all decimal slots, used for decimal slots
that are not
+ // inside a MAP (keeping the original behavior), for the placeholder
return type,
+ // and for MAP-nested leaves whose group has no concrete type
information.
+ DecimalV3Type widerType = null;
+
+ // Decimal leaves inside a MAP are independent type variables: they
must keep
+ // their own precision/scale instead of being merged into one wider
type,
+ // otherwise widening one leaf (e.g. the scale of a big integral key)
may overflow
+ // the other leaf. They are grouped by the full structural path
through nested
+ // containers (e.g. "key", "value", "value/array", "value/key") and
the resolved
+ // leaf type, so the leaves of different (or repeated) MAP arguments
on the same
+ // path aggregate while leaves on different paths stay independent.
+ Map<String, DecimalV3Type> groupWider = Maps.newHashMap();
+
+ // The template signature carrying the original Any/Follow slots that
the resolved
+ // signature was derived from. It lets us link a top-level scalar slot
with the MAP
+ // leaf it belongs to by the original Any/Follow group identity (the
index) instead
+ // of the resolved concrete type, which can collide when independent
slots resolve
+ // to the same type (e.g. the key and the value of a MAP both becoming
DECIMAL(10,3)).
+ FunctionSignature template = findDecimalV3Template(computeSignature,
signature);
+
+ // The outermost MAP leaf group of each Any/Follow index (from the
template), used
+ // to link a top-level scalar slot (e.g. map_contains_value's probe,
element_at's
+ // lookup) with the MAP leaf that carries the same index.
+ Map<Integer, String> indexToMapLeafGroup = Maps.newHashMap();
+
+ // Fallback used when the template can not be recovered: the outermost
MAP leaf
+ // group of each resolved type, used to link a top-level scalar slot
with the MAP
+ // leaf it was resolved from (after Any/Follow resolution both carry
the same type).
+ Map<DecimalV3Type, String> mapLeafGroupByType = Maps.newHashMap();
+
+ // Top-level scalar decimal leaves with a concrete resolved type,
whose promoted
+ // type must also be folded into the linked MAP leaf group.
+ List<DecimalLeaf> scalarLeaves = Lists.newArrayList();
+
+ // Top-level scalar decimal slots are independent logical type
variables
+ // (e.g. the key/value of map_agg(k, v) are Any(0) and Any(1)); group
them by
+ // the resolved type so the slots of one logical group aggregate while
the slots
+ // of different groups keep their own precision/scale.
+ Map<DecimalV3Type, DecimalV3Type> scalarGroupWider = Maps.newHashMap();
+
+ DecimalV3Type[] widerHolder = new DecimalV3Type[1];
for (int i = 0; i < arguments.size(); i++) {
- DataType targetType;
- if (i >= signature.argumentsTypes.size()) {
- Preconditions.checkState(signature.getVarArgType().isPresent(),
- "argument size larger than signature");
- targetType = signature.getVarArgType().get();
+ DataType targetType = getSignatureArgumentType(signature, i);
+ DataType templateType = template == null ? null :
getSignatureArgumentType(template, i);
+ collectDecimalLeaf(targetType, arguments.get(i).getDataType(),
arguments.get(i),
+ "", templateType, -1, indexToMapLeafGroup,
mapLeafGroupByType, groupWider,
+ scalarGroupWider, scalarLeaves, widerHolder);
+ }
+ widerType = widerHolder[0];
+ if (widerType == null) {
+ return signature;
+ }
+
+ // Fold the promoted type of every top-level scalar slot into the MAP
leaf group it
+ // is linked with (by the original Any/Follow identity when available,
otherwise by
+ // the resolved type), so the MAP leaf and the scalar slot linked with
it are
+ // promoted to one type.
+ for (DecimalLeaf scalarLeaf : scalarLeaves) {
+ String linkedGroup;
+ if (scalarLeaf.index >= 0) {
+ linkedGroup = indexToMapLeafGroup.get(scalarLeaf.index);
} else {
- targetType = signature.getArgType(i);
+ linkedGroup = mapLeafGroupByType.get(scalarLeaf.resolvedType);
}
- List<DataType> argTypes =
extractArgumentTypeBySignature(DecimalV3Type.class, targetType,
- arguments.get(i).getDataType());
- if (argTypes.isEmpty()) {
- continue;
+ if (linkedGroup != null) {
+ groupWider.merge(linkedGroup, scalarLeaf.promotedType,
+ ComputeSignatureHelper::mergeDecimalV3Type);
}
+ }
- for (DataType argType : argTypes) {
- Expression arg = arguments.get(i);
- DecimalV3Type decimalV3Type;
- if (arg.isLiteral() && arg.getDataType().isIntegralType()) {
- // create decimalV3 with minimum scale enough to hold the
integral literal
- decimalV3Type = DecimalV3Type.createDecimalV3Type(new
BigDecimal(((Literal) arg).getStringValue()));
- } else {
- decimalV3Type = DecimalV3Type.forType(argType);
+ List<DataType> newArgTypes =
Lists.newArrayListWithCapacity(signature.argumentsTypes.size());
+ for (int i = 0; i < signature.argumentsTypes.size(); i++) {
+ DataType templateType = template == null ? null :
getSignatureArgumentType(template, i);
+
newArgTypes.add(replaceDecimalV3Leaf(signature.argumentsTypes.get(i), "",
templateType, -1,
+ indexToMapLeafGroup, mapLeafGroupByType, groupWider,
scalarGroupWider, widerType));
+ }
+ signature = signature.withArgumentTypes(signature.hasVarArgs,
newArgTypes);
+ if (signature.returnType instanceof DecimalV3Type
+ && ((DecimalV3Type) signature.returnType).getPrecision() <= 0)
{
+ signature = signature.withReturnType(widerType);
+ }
+ return signature;
+ }
+
+ private static DataType getSignatureArgumentType(FunctionSignature
signature, int index) {
+ if (index >= signature.argumentsTypes.size()) {
+ Preconditions.checkState(signature.getVarArgType().isPresent(),
+ "argument size larger than signature");
+ return signature.getVarArgType().get();
+ }
+ return signature.getArgType(index);
+ }
+
+ /**
+ * Compute the promoted DecimalV3Type for one decimal slot from its
argument type.
+ */
+ private static DecimalV3Type promotedDecimalV3Type(Expression arg,
DataType argType) {
+ if (arg.isLiteral() && arg.getDataType().isIntegralType()) {
+ // create decimalV3 with minimum scale enough to hold the integral
literal
+ return DecimalV3Type.createDecimalV3Type(new BigDecimal(((Literal)
arg).getStringValue()));
+ }
+ return DecimalV3Type.forType(argType);
+ }
+
+ /**
+ * Collect every decimal leaf of one argument and fold its promoted type
into the
+ * corresponding group. {@code path} is the full structural path through
nested
+ * containers (empty for a top-level slot, {@link #MAP_KEY}/{@link
#MAP_VALUE} for
+ * the key/value of a MAP, {@link #ARRAY_ITEM} for an ARRAY item), so an
ARRAY nested
+ * in a MAP value (e.g. "value/array") or the key/value of a nested MAP
(e.g.
+ * "value/key") keep the enclosing group instead of being merged with the
outer
+ * leaves. {@code templateType} is the corresponding slot of the template
signature
+ * that still carries the original Any/Follow identity of this leaf, and
+ * {@code containerIndex} is the Any/Follow index of an enclosing MAP
container that
+ * owns this leaf as a whole (i.e. the container itself is an Any/Follow
slot), or -1
+ * when there is none. {@code widerHolder} accumulates the wider type
across all
+ * decimal leaves.
+ */
+ private static void collectDecimalLeaf(DataType sigType, DataType argType,
Expression arg,
+ String path, DataType templateType, int containerIndex,
+ Map<Integer, String> indexToMapLeafGroup, Map<DecimalV3Type,
String> mapLeafGroupByType,
+ Map<String, DecimalV3Type> groupWider, Map<DecimalV3Type,
DecimalV3Type> scalarGroupWider,
+ List<DecimalLeaf> scalarLeaves, DecimalV3Type[] widerHolder) {
+ if (sigType instanceof DecimalV3Type) {
+ DecimalV3Type sigDecimal = (DecimalV3Type) sigType;
+ DecimalV3Type promoted = null;
+ if (!(argType instanceof NullType)) {
+ promoted = promotedDecimalV3Type(arg, argType);
+ widerHolder[0] = mergeDecimalV3Type(widerHolder[0], promoted);
+ }
+ if (path.isEmpty()) {
+ // top-level scalar slot: a concrete resolved type may be
linked with a
+ // MAP leaf below by the original Any/Follow identity, and
otherwise the
+ // slots of the same resolved type form one logical group
(e.g. the two
+ // arguments of map_agg) and stay independent from the slots
of other groups
+ if (promoted != null && sigDecimal.getPrecision() > 0) {
+ scalarLeaves.add(new DecimalLeaf(sigDecimal, promoted,
anyFollowIndex(templateType)));
+ scalarGroupWider.merge(sigDecimal, promoted,
+ ComputeSignatureHelper::mergeDecimalV3Type);
}
- if (finalType == null) {
- finalType = decimalV3Type;
+ } else if (containerIndex >= 0) {
+ // the leaf is inside a MAP container that is itself an
Any/Follow slot: the
+ // container absorbs the outer structural path, so the
descendants of all the
+ // containers that share this identity aggregate (e.g. the key
of ARRAY<MAP>
+ // and the key of a plain MAP argument of the same Any(0) slot)
+ if (promoted != null) {
+ String groupKey = MAP_CONTAINER_GROUP + containerIndex +
"/" + path + ":" + sigDecimal;
+ groupWider.merge(groupKey, promoted,
ComputeSignatureHelper::mergeDecimalV3Type);
+ }
+ } else if (isMapNested(path) && promoted != null) {
+ String groupKey;
+ int index = anyFollowIndex(templateType);
+ if (index >= 0) {
+ // leaves that share the original Any/Follow identity
aggregate into one
+ // group (e.g. the value of map_contains_value and its
probe)
+ groupKey = ANY_INDEX_GROUP + index;
+ indexToMapLeafGroup.putIfAbsent(index, groupKey);
} else {
- finalType = (DecimalV3Type)
DecimalV3Type.widerDecimalV3Type(finalType, decimalV3Type, false);
+ // no identity: keep the outermost group (shortest path,
key before value)
+ // for linking by the resolved type
+ groupKey = path + ":" + sigDecimal;
+ mapLeafGroupByType.putIfAbsent(sigDecimal, groupKey);
+ }
+ groupWider.merge(groupKey, promoted,
ComputeSignatureHelper::mergeDecimalV3Type);
+ } else if (promoted != null) {
+ // non-MAP ARRAY leaf (e.g. the item of ARRAY<Any(index)>):
keep the original
+ // Any/Follow identity so it is promoted together with the
linked scalar slot
+ // of the same group (e.g. array_contains(ARRAY<Any(0)>,
Any(0)))
+ int index = anyFollowIndex(templateType);
+ if (index >= 0) {
+ String groupKey = ANY_INDEX_GROUP + index;
+ indexToMapLeafGroup.putIfAbsent(index, groupKey);
+ groupWider.merge(groupKey, promoted,
ComputeSignatureHelper::mergeDecimalV3Type);
}
+ // without an identity the leaf keeps the original single
wider-type behavior
+ }
+ return;
+ } else if (sigType instanceof MapType) {
+ MapType mapType = (MapType) sigType;
+ DataType templateKey = null;
+ DataType templateValue = null;
+ int childContainerIndex = containerIndex;
+ String childPath = path;
+ if (templateType instanceof MapType) {
+ templateKey = ((MapType) templateType).getKeyType();
+ templateValue = ((MapType) templateType).getValueType();
+ } else {
+ // the whole MAP container is an Any/Follow slot: propagate
the group
+ // identity into the descendant-relative keys and absorb the
outer path
+ int index = anyFollowIndex(templateType);
+ if (index >= 0) {
+ childContainerIndex = index;
+ childPath = "";
+ }
+ }
+ if (argType instanceof MapType) {
+ MapType argMapType = (MapType) argType;
+ collectDecimalLeaf(mapType.getKeyType(),
argMapType.getKeyType(), arg,
+ appendPath(childPath, MAP_KEY), templateKey,
childContainerIndex,
+ indexToMapLeafGroup, mapLeafGroupByType, groupWider,
+ scalarGroupWider, scalarLeaves, widerHolder);
+ collectDecimalLeaf(mapType.getValueType(),
argMapType.getValueType(), arg,
+ appendPath(childPath, MAP_VALUE), templateValue,
childContainerIndex,
+ indexToMapLeafGroup, mapLeafGroupByType, groupWider,
+ scalarGroupWider, scalarLeaves, widerHolder);
+ } else if (argType instanceof NullType) {
+ collectDecimalLeaf(mapType.getKeyType(), argType, arg,
+ appendPath(childPath, MAP_KEY), templateKey,
childContainerIndex,
+ indexToMapLeafGroup, mapLeafGroupByType, groupWider,
+ scalarGroupWider, scalarLeaves, widerHolder);
+ collectDecimalLeaf(mapType.getValueType(), argType, arg,
+ appendPath(childPath, MAP_VALUE), templateValue,
childContainerIndex,
+ indexToMapLeafGroup, mapLeafGroupByType, groupWider,
+ scalarGroupWider, scalarLeaves, widerHolder);
+ }
+ return;
+ } else if (sigType instanceof ArrayType) {
+ DataType itemArgType;
+ if (argType instanceof ArrayType) {
+ itemArgType = ((ArrayType) argType).getItemType();
+ } else if (argType instanceof NullType) {
+ itemArgType = argType;
+ } else {
+ return;
}
+ // carry the enclosing MAP path through the ARRAY so items nested
in a MAP
+ // value stay in the value group
+ DataType templateItem = templateType instanceof ArrayType
Review Comment:
[P1] Preserve Any container identity through ARRAY recursion
A distinct nested case remains after the direct-MAP fix. For a reduced tree
`Project[array_pushfront(arr, x)] -> Scan[arr
ARRAY<ARRAY<MAP<DECIMAL(10,3),DECIMAL(5,2)>>>, x
ARRAY<MAP<DECIMAL(9,2),DECIMAL(9,2)>>]`, `Any(0)` correctly resolves to the
common `ARRAY<MAP<DECIMAL(10,3),DECIMAL(9,2)>>`. Here the resolved inner ARRAY
is paired with template `Any(0)`, so `templateItem` becomes null: arg0's MAP
leaves use `array/array/key|value`, while arg1 uses `array/key|value`.
Replacement repeats the split and sends different nested MAP decimal types to
BE, which builds the result from arg0 and inserts arg1 (cross-width keys can
fail insertion; same-width scale splits can insert the wrong raw value). The
existing thread covered `Any(0)` resolving directly to MAP; this case loses
identity one level earlier. Please propagate an Any/Follow-owned container
identity through ARRAY too and add nonconstant pushfront/back coverage for
ARRAY-of-ARRAY-of-MAP plus ARRAY-of-MAP.
##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/ComputeSignatureHelper.java:
##########
@@ -566,52 +577,434 @@ private static FunctionSignature
defaultTimePrecisionPromotion(FunctionSignature
}
private static FunctionSignature defaultDecimalV3PrecisionPromotion(
- FunctionSignature signature, List<Expression> arguments) {
- DecimalV3Type finalType = null;
+ FunctionSignature signature, List<Expression> arguments,
ComputeSignature computeSignature) {
+ // The wider type across all decimal slots, used for decimal slots
that are not
+ // inside a MAP (keeping the original behavior), for the placeholder
return type,
+ // and for MAP-nested leaves whose group has no concrete type
information.
+ DecimalV3Type widerType = null;
+
+ // Decimal leaves inside a MAP are independent type variables: they
must keep
+ // their own precision/scale instead of being merged into one wider
type,
+ // otherwise widening one leaf (e.g. the scale of a big integral key)
may overflow
+ // the other leaf. They are grouped by the full structural path
through nested
+ // containers (e.g. "key", "value", "value/array", "value/key") and
the resolved
+ // leaf type, so the leaves of different (or repeated) MAP arguments
on the same
+ // path aggregate while leaves on different paths stay independent.
+ Map<String, DecimalV3Type> groupWider = Maps.newHashMap();
+
+ // The template signature carrying the original Any/Follow slots that
the resolved
+ // signature was derived from. It lets us link a top-level scalar slot
with the MAP
+ // leaf it belongs to by the original Any/Follow group identity (the
index) instead
+ // of the resolved concrete type, which can collide when independent
slots resolve
+ // to the same type (e.g. the key and the value of a MAP both becoming
DECIMAL(10,3)).
+ FunctionSignature template = findDecimalV3Template(computeSignature,
signature);
+
+ // The outermost MAP leaf group of each Any/Follow index (from the
template), used
+ // to link a top-level scalar slot (e.g. map_contains_value's probe,
element_at's
+ // lookup) with the MAP leaf that carries the same index.
+ Map<Integer, String> indexToMapLeafGroup = Maps.newHashMap();
+
+ // Fallback used when the template can not be recovered: the outermost
MAP leaf
+ // group of each resolved type, used to link a top-level scalar slot
with the MAP
+ // leaf it was resolved from (after Any/Follow resolution both carry
the same type).
+ Map<DecimalV3Type, String> mapLeafGroupByType = Maps.newHashMap();
+
+ // Top-level scalar decimal leaves with a concrete resolved type,
whose promoted
+ // type must also be folded into the linked MAP leaf group.
+ List<DecimalLeaf> scalarLeaves = Lists.newArrayList();
+
+ // Top-level scalar decimal slots are independent logical type
variables
+ // (e.g. the key/value of map_agg(k, v) are Any(0) and Any(1)); group
them by
+ // the resolved type so the slots of one logical group aggregate while
the slots
+ // of different groups keep their own precision/scale.
+ Map<DecimalV3Type, DecimalV3Type> scalarGroupWider = Maps.newHashMap();
+
+ DecimalV3Type[] widerHolder = new DecimalV3Type[1];
for (int i = 0; i < arguments.size(); i++) {
- DataType targetType;
- if (i >= signature.argumentsTypes.size()) {
- Preconditions.checkState(signature.getVarArgType().isPresent(),
- "argument size larger than signature");
- targetType = signature.getVarArgType().get();
+ DataType targetType = getSignatureArgumentType(signature, i);
+ DataType templateType = template == null ? null :
getSignatureArgumentType(template, i);
+ collectDecimalLeaf(targetType, arguments.get(i).getDataType(),
arguments.get(i),
+ "", templateType, -1, indexToMapLeafGroup,
mapLeafGroupByType, groupWider,
+ scalarGroupWider, scalarLeaves, widerHolder);
+ }
+ widerType = widerHolder[0];
+ if (widerType == null) {
+ return signature;
+ }
+
+ // Fold the promoted type of every top-level scalar slot into the MAP
leaf group it
+ // is linked with (by the original Any/Follow identity when available,
otherwise by
+ // the resolved type), so the MAP leaf and the scalar slot linked with
it are
+ // promoted to one type.
+ for (DecimalLeaf scalarLeaf : scalarLeaves) {
+ String linkedGroup;
+ if (scalarLeaf.index >= 0) {
+ linkedGroup = indexToMapLeafGroup.get(scalarLeaf.index);
} else {
- targetType = signature.getArgType(i);
+ linkedGroup = mapLeafGroupByType.get(scalarLeaf.resolvedType);
}
- List<DataType> argTypes =
extractArgumentTypeBySignature(DecimalV3Type.class, targetType,
- arguments.get(i).getDataType());
- if (argTypes.isEmpty()) {
- continue;
+ if (linkedGroup != null) {
+ groupWider.merge(linkedGroup, scalarLeaf.promotedType,
+ ComputeSignatureHelper::mergeDecimalV3Type);
}
+ }
- for (DataType argType : argTypes) {
- Expression arg = arguments.get(i);
- DecimalV3Type decimalV3Type;
- if (arg.isLiteral() && arg.getDataType().isIntegralType()) {
- // create decimalV3 with minimum scale enough to hold the
integral literal
- decimalV3Type = DecimalV3Type.createDecimalV3Type(new
BigDecimal(((Literal) arg).getStringValue()));
- } else {
- decimalV3Type = DecimalV3Type.forType(argType);
+ List<DataType> newArgTypes =
Lists.newArrayListWithCapacity(signature.argumentsTypes.size());
+ for (int i = 0; i < signature.argumentsTypes.size(); i++) {
+ DataType templateType = template == null ? null :
getSignatureArgumentType(template, i);
+
newArgTypes.add(replaceDecimalV3Leaf(signature.argumentsTypes.get(i), "",
templateType, -1,
+ indexToMapLeafGroup, mapLeafGroupByType, groupWider,
scalarGroupWider, widerType));
+ }
+ signature = signature.withArgumentTypes(signature.hasVarArgs,
newArgTypes);
+ if (signature.returnType instanceof DecimalV3Type
+ && ((DecimalV3Type) signature.returnType).getPrecision() <= 0)
{
+ signature = signature.withReturnType(widerType);
+ }
+ return signature;
+ }
+
+ private static DataType getSignatureArgumentType(FunctionSignature
signature, int index) {
+ if (index >= signature.argumentsTypes.size()) {
+ Preconditions.checkState(signature.getVarArgType().isPresent(),
+ "argument size larger than signature");
+ return signature.getVarArgType().get();
+ }
+ return signature.getArgType(index);
+ }
+
+ /**
+ * Compute the promoted DecimalV3Type for one decimal slot from its
argument type.
+ */
+ private static DecimalV3Type promotedDecimalV3Type(Expression arg,
DataType argType) {
+ if (arg.isLiteral() && arg.getDataType().isIntegralType()) {
+ // create decimalV3 with minimum scale enough to hold the integral
literal
+ return DecimalV3Type.createDecimalV3Type(new BigDecimal(((Literal)
arg).getStringValue()));
+ }
+ return DecimalV3Type.forType(argType);
+ }
+
+ /**
+ * Collect every decimal leaf of one argument and fold its promoted type
into the
+ * corresponding group. {@code path} is the full structural path through
nested
+ * containers (empty for a top-level slot, {@link #MAP_KEY}/{@link
#MAP_VALUE} for
+ * the key/value of a MAP, {@link #ARRAY_ITEM} for an ARRAY item), so an
ARRAY nested
+ * in a MAP value (e.g. "value/array") or the key/value of a nested MAP
(e.g.
+ * "value/key") keep the enclosing group instead of being merged with the
outer
+ * leaves. {@code templateType} is the corresponding slot of the template
signature
+ * that still carries the original Any/Follow identity of this leaf, and
+ * {@code containerIndex} is the Any/Follow index of an enclosing MAP
container that
+ * owns this leaf as a whole (i.e. the container itself is an Any/Follow
slot), or -1
+ * when there is none. {@code widerHolder} accumulates the wider type
across all
+ * decimal leaves.
+ */
+ private static void collectDecimalLeaf(DataType sigType, DataType argType,
Expression arg,
+ String path, DataType templateType, int containerIndex,
+ Map<Integer, String> indexToMapLeafGroup, Map<DecimalV3Type,
String> mapLeafGroupByType,
+ Map<String, DecimalV3Type> groupWider, Map<DecimalV3Type,
DecimalV3Type> scalarGroupWider,
+ List<DecimalLeaf> scalarLeaves, DecimalV3Type[] widerHolder) {
+ if (sigType instanceof DecimalV3Type) {
+ DecimalV3Type sigDecimal = (DecimalV3Type) sigType;
+ DecimalV3Type promoted = null;
+ if (!(argType instanceof NullType)) {
+ promoted = promotedDecimalV3Type(arg, argType);
+ widerHolder[0] = mergeDecimalV3Type(widerHolder[0], promoted);
+ }
+ if (path.isEmpty()) {
+ // top-level scalar slot: a concrete resolved type may be
linked with a
+ // MAP leaf below by the original Any/Follow identity, and
otherwise the
+ // slots of the same resolved type form one logical group
(e.g. the two
+ // arguments of map_agg) and stay independent from the slots
of other groups
+ if (promoted != null && sigDecimal.getPrecision() > 0) {
+ scalarLeaves.add(new DecimalLeaf(sigDecimal, promoted,
anyFollowIndex(templateType)));
+ scalarGroupWider.merge(sigDecimal, promoted,
+ ComputeSignatureHelper::mergeDecimalV3Type);
}
- if (finalType == null) {
- finalType = decimalV3Type;
+ } else if (containerIndex >= 0) {
+ // the leaf is inside a MAP container that is itself an
Any/Follow slot: the
+ // container absorbs the outer structural path, so the
descendants of all the
+ // containers that share this identity aggregate (e.g. the key
of ARRAY<MAP>
+ // and the key of a plain MAP argument of the same Any(0) slot)
+ if (promoted != null) {
+ String groupKey = MAP_CONTAINER_GROUP + containerIndex +
"/" + path + ":" + sigDecimal;
+ groupWider.merge(groupKey, promoted,
ComputeSignatureHelper::mergeDecimalV3Type);
+ }
+ } else if (isMapNested(path) && promoted != null) {
Review Comment:
[P1] Register linked MAP groups even when the MAP leaf is NULL
For `Project[map_contains_value(map(k, NULL), p)] -> Scan[k DECIMAL(18,18),
p DECIMAL(9,2)]`, all-NULL Any handling first resolves the MAP value and probe
to the same `DECIMAL(9,2)`. This condition then skips both the value
contribution and `idx:0` registration because the actual MAP leaf is NULL. The
unrelated key and probe make global `widerType` `DECIMAL(25,18)`, so
replacement emits a Decimal128 MAP value but a Decimal32 probe. BE converts the
values to an array and rejects the unequal primitive types before it can
observe that the stored value is NULL; `map_contains_key(map(NULL, v), p)` is
symmetric. The earlier NULL thread covered a NULL scalar following a concrete
MAP leaf, whereas this is the inverse unregistered-MAP-leaf path. Please
register group identity independently of promoted evidence, merge only non-NULL
evidence, and add key/value regressions with a NULL MAP leaf plus a concrete
probe.
--
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]