-
Notifications
You must be signed in to change notification settings - Fork 29k
[SPARK-24734][SQL] Fix type coercions and nullabilities of nested data types of some functions. #21704
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SPARK-24734][SQL] Fix type coercions and nullabilities of nested data types of some functions. #21704
Changes from 1 commit
d87a8c6
30d5aed
2e624df
fa73b32
da0702b
b31e401
7a838b0
01c9ff3
b2ca587
3d8891e
1fa692a
444383d
3e1f7e4
2c54e38
5f1b865
2ab025f
db254e5
b412f7b
f701242
5115961
e489e8b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -247,8 +247,22 @@ object TypeCoercion { | |
| } | ||
| } | ||
|
|
||
| private def haveSameType(exprs: Seq[Expression]): Boolean = | ||
| exprs.map(_.dataType).distinct.length == 1 | ||
| private def haveSameType(exprs: Seq[Expression]): Boolean = { | ||
| if (exprs.size <= 1) { | ||
| true | ||
| } else { | ||
| val head = exprs.head.dataType | ||
| exprs.tail.forall(_.dataType.sameType(head)) | ||
| } | ||
| } | ||
|
|
||
| private def castIfNotSameType(expr: Expression, dt: DataType): Expression = { | ||
| if (!expr.dataType.sameType(dt)) { | ||
| Cast(expr, dt) | ||
| } else { | ||
| expr | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Widens numeric types and converts strings to numbers when appropriate. | ||
|
|
@@ -513,6 +527,7 @@ object TypeCoercion { | |
| * This ensure that the types for various functions are as expected. | ||
| */ | ||
| object FunctionArgumentConversion extends TypeCoercionRule { | ||
|
|
||
| override protected def coerceTypes( | ||
| plan: LogicalPlan): LogicalPlan = plan transformAllExpressions { | ||
| // Skip nodes who's children have not been resolved yet. | ||
|
|
@@ -521,15 +536,15 @@ object TypeCoercion { | |
| case a @ CreateArray(children) if !haveSameType(children) => | ||
| val types = children.map(_.dataType) | ||
| findWiderCommonType(types) match { | ||
| case Some(finalDataType) => CreateArray(children.map(Cast(_, finalDataType))) | ||
| case Some(finalDataType) => CreateArray(children.map(castIfNotSameType(_, finalDataType))) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is it needed? I think optimizer can remove unnecessary cast.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently the optimizer doesn't remove the cast when the difference of the |
||
| case None => a | ||
| } | ||
|
|
||
| case c @ Concat(children) if children.forall(c => ArrayType.acceptsType(c.dataType)) && | ||
| !haveSameType(children) => | ||
| val types = children.map(_.dataType) | ||
| findWiderCommonType(types) match { | ||
| case Some(finalDataType) => Concat(children.map(Cast(_, finalDataType))) | ||
| case Some(finalDataType) => Concat(children.map(castIfNotSameType(_, finalDataType))) | ||
| case None => c | ||
| } | ||
|
|
||
|
|
@@ -555,7 +570,7 @@ object TypeCoercion { | |
| } else { | ||
| val types = m.keys.map(_.dataType) | ||
| findWiderCommonType(types) match { | ||
| case Some(finalDataType) => m.keys.map(Cast(_, finalDataType)) | ||
| case Some(finalDataType) => m.keys.map(castIfNotSameType(_, finalDataType)) | ||
| case None => m.keys | ||
| } | ||
| } | ||
|
|
@@ -565,7 +580,7 @@ object TypeCoercion { | |
| } else { | ||
| val types = m.values.map(_.dataType) | ||
| findWiderCommonType(types) match { | ||
| case Some(finalDataType) => m.values.map(Cast(_, finalDataType)) | ||
| case Some(finalDataType) => m.values.map(castIfNotSameType(_, finalDataType)) | ||
| case None => m.values | ||
| } | ||
| } | ||
|
|
@@ -593,7 +608,7 @@ object TypeCoercion { | |
| case c @ Coalesce(es) if !haveSameType(es) => | ||
| val types = es.map(_.dataType) | ||
| findWiderCommonType(types) match { | ||
| case Some(finalDataType) => Coalesce(es.map(Cast(_, finalDataType))) | ||
| case Some(finalDataType) => Coalesce(es.map(castIfNotSameType(_, finalDataType))) | ||
| case None => c | ||
| } | ||
|
|
||
|
|
@@ -603,14 +618,14 @@ object TypeCoercion { | |
| case g @ Greatest(children) if !haveSameType(children) => | ||
| val types = children.map(_.dataType) | ||
| findWiderTypeWithoutStringPromotion(types) match { | ||
| case Some(finalDataType) => Greatest(children.map(Cast(_, finalDataType))) | ||
| case Some(finalDataType) => Greatest(children.map(castIfNotSameType(_, finalDataType))) | ||
| case None => g | ||
| } | ||
|
|
||
| case l @ Least(children) if !haveSameType(children) => | ||
| val types = children.map(_.dataType) | ||
| findWiderTypeWithoutStringPromotion(types) match { | ||
| case Some(finalDataType) => Least(children.map(Cast(_, finalDataType))) | ||
| case Some(finalDataType) => Least(children.map(castIfNotSameType(_, finalDataType))) | ||
| case None => l | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is duplicated with
ComplexTypeMergingExpression.areInputTypesForMergingEqual, can we unify them? We canhasSameType. Any expression that needs to do this check should extendComplexTypeMergingExpressionand the TypeCoercion rule should callareInputTypesForMergingEqual.areInputTypesForMergingEqual.ComplexTypeMergingExpressionshould only define the list of data types that need to be merged, and TypeCoercion rule should callhasSameType(e.inputTypesForMerging)Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we have
CreateArrayandCreateMap, we can't make all such expressionsComplexTypeMergingExpression.I'd apply 2) approach.