[Fix](Variant) support view for accessing variant subcolumns and temp… (#32225)
This commit is contained in:
@ -492,17 +492,24 @@ public class BinaryPredicate extends Predicate implements Writable {
|
||||
}
|
||||
}
|
||||
|
||||
if ((t1.isDecimalV3Type() && !t2.isStringType() && !t2.isFloatingPointType())
|
||||
|| (t2.isDecimalV3Type() && !t1.isStringType() && !t1.isFloatingPointType())) {
|
||||
if ((t1.isDecimalV3Type() && !t2.isStringType() && !t2.isFloatingPointType() && !t2.isVariantType())
|
||||
|| (t2.isDecimalV3Type() && !t1.isStringType() && !t1.isFloatingPointType() && !t1.isVariantType())) {
|
||||
return Type.getAssignmentCompatibleType(getChild(0).getType(), getChild(1).getType(), false,
|
||||
SessionVariable.getEnableDecimal256());
|
||||
}
|
||||
|
||||
// Variant can be implicit cast to numeric type and string type at present
|
||||
if (t1.isVariantType() && (t2.isNumericType() || t2.isStringType())) {
|
||||
if (t2.isDecimalV2Type() || t2.isDecimalV3Type()) {
|
||||
// TODO support decimal
|
||||
return Type.DOUBLE;
|
||||
}
|
||||
return Type.fromPrimitiveType(t2);
|
||||
}
|
||||
if (t2.isVariantType() && (t1.isNumericType() || t1.isStringType())) {
|
||||
if (t1.isDecimalV2Type() || t1.isDecimalV3Type()) {
|
||||
return Type.DOUBLE;
|
||||
}
|
||||
return Type.fromPrimitiveType(t1);
|
||||
}
|
||||
|
||||
|
||||
@ -114,6 +114,12 @@ public class ExpressionAnalyzer extends SubExprAnalyzer<ExpressionRewriteContext
|
||||
private final boolean bindSlotInOuterScope;
|
||||
private boolean currentInLambda;
|
||||
|
||||
// Keep track of which element_at function's level
|
||||
// e.g. element_at(element_at(v, 'repo'), 'name') level 1
|
||||
// element_at(v, 'repo') level 2
|
||||
// Only works with function ElementAt which satisfy condition PushDownToProjectionFunction.validToPushDown
|
||||
private int currentElementAtLevel = 0;
|
||||
|
||||
public ExpressionAnalyzer(Plan currentPlan, Scope scope, CascadesContext cascadesContext,
|
||||
boolean enableExactMatch, boolean bindSlotInOuterScope) {
|
||||
super(scope, cascadesContext);
|
||||
@ -285,6 +291,9 @@ public class ExpressionAnalyzer extends SubExprAnalyzer<ExpressionRewriteContext
|
||||
* ******************************************************************************************** */
|
||||
@Override
|
||||
public Expression visitUnboundFunction(UnboundFunction unboundFunction, ExpressionRewriteContext context) {
|
||||
if (unboundFunction.getName().equalsIgnoreCase("element_at")) {
|
||||
++currentElementAtLevel;
|
||||
}
|
||||
if (unboundFunction.isHighOrder()) {
|
||||
unboundFunction = bindHighOrderFunction(unboundFunction, context);
|
||||
} else {
|
||||
@ -331,6 +340,17 @@ public class ExpressionAnalyzer extends SubExprAnalyzer<ExpressionRewriteContext
|
||||
// so wrap COUNT with Nvl to ensure it's result is 0 instead of null to get the correct result
|
||||
boundFunction = new Nvl(boundFunction, new BigIntLiteral(0));
|
||||
}
|
||||
|
||||
if (currentElementAtLevel == 1
|
||||
&& PushDownToProjectionFunction.validToPushDown(boundFunction)) {
|
||||
// Only rewrite the top level of PushDownToProjectionFunction, otherwise invalid slot will be generated
|
||||
// currentElementAtLevel == 1 means at the top of element_at function, other levels will be ignored.
|
||||
currentElementAtLevel = 0;
|
||||
return visitElementAt((ElementAt) boundFunction, context);
|
||||
}
|
||||
if (boundFunction instanceof ElementAt) {
|
||||
--currentElementAtLevel;
|
||||
}
|
||||
return boundFunction;
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,6 +80,12 @@ public class FunctionBinder extends AbstractExpressionRewriteRule {
|
||||
|
||||
public static final FunctionBinder INSTANCE = new FunctionBinder();
|
||||
|
||||
// Keep track of which element_at function's level
|
||||
// e.g. element_at(element_at(v, 'repo'), 'name') level 1
|
||||
// element_at(v, 'repo') level 2
|
||||
// Only works with function ElementAt which satisfy condition PushDownToProjectionFunction.validToPushDown
|
||||
private int currentElementAtLevel = 0;
|
||||
|
||||
@Override
|
||||
public Expression visit(Expression expr, ExpressionRewriteContext context) {
|
||||
expr = super.visit(expr, context);
|
||||
@ -141,6 +147,9 @@ public class FunctionBinder extends AbstractExpressionRewriteRule {
|
||||
|
||||
@Override
|
||||
public Expression visitUnboundFunction(UnboundFunction unboundFunction, ExpressionRewriteContext context) {
|
||||
if (unboundFunction.getName().equalsIgnoreCase("element_at")) {
|
||||
++currentElementAtLevel;
|
||||
}
|
||||
if (unboundFunction.isHighOrder()) {
|
||||
unboundFunction = bindHighOrderFunction(unboundFunction, context);
|
||||
} else {
|
||||
@ -188,6 +197,16 @@ public class FunctionBinder extends AbstractExpressionRewriteRule {
|
||||
// so wrap COUNT with Nvl to ensure it's result is 0 instead of null to get the correct result
|
||||
boundFunction = new Nvl(boundFunction, new BigIntLiteral(0));
|
||||
}
|
||||
if (currentElementAtLevel == 1
|
||||
&& PushDownToProjectionFunction.validToPushDown(boundFunction)) {
|
||||
// Only rewrite the top level of PushDownToProjectionFunction, otherwise invalid slot will be generated
|
||||
// currentElementAtLevel == 1 means at the top of element_at function, other levels will be ignored.
|
||||
currentElementAtLevel = 0;
|
||||
return visitElementAt((ElementAt) boundFunction, context);
|
||||
}
|
||||
if (boundFunction instanceof ElementAt) {
|
||||
--currentElementAtLevel;
|
||||
}
|
||||
return boundFunction;
|
||||
}
|
||||
}
|
||||
@ -201,6 +220,7 @@ public class FunctionBinder extends AbstractExpressionRewriteRule {
|
||||
@Override
|
||||
public Expression visitElementAt(ElementAt elementAt, ExpressionRewriteContext context) {
|
||||
Expression boundFunction = visitBoundFunction(elementAt, context);
|
||||
|
||||
if (PushDownToProjectionFunction.validToPushDown(boundFunction)) {
|
||||
if (ConnectContext.get() != null
|
||||
&& ConnectContext.get().getSessionVariable() != null
|
||||
|
||||
@ -1294,9 +1294,17 @@ public class TypeCoercionUtils {
|
||||
|
||||
// variant type
|
||||
if ((leftType.isVariantType() && (rightType.isStringLikeType() || rightType.isNumericType()))) {
|
||||
if (rightType.isDecimalLikeType()) {
|
||||
// TODO support decimal
|
||||
return Optional.of(DoubleType.INSTANCE);
|
||||
}
|
||||
return Optional.of(rightType);
|
||||
}
|
||||
if ((rightType.isVariantType() && (leftType.isStringLikeType() || leftType.isNumericType()))) {
|
||||
if (leftType.isDecimalLikeType()) {
|
||||
// TODO support decimal
|
||||
return Optional.of(DoubleType.INSTANCE);
|
||||
}
|
||||
return Optional.of(leftType);
|
||||
}
|
||||
return Optional.of(DoubleType.INSTANCE);
|
||||
|
||||
Reference in New Issue
Block a user