-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
planner, type: fix AggFieldType error when encouter unsigned and sign type #21062
Changes from 2 commits
efc9e9f
ab1fafe
4e5c29e
ee78e69
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,15 +66,38 @@ func NewFieldTypeWithCollation(tp byte, collation string, length int) *FieldType | |
// Aggregation is performed by MergeFieldType function. | ||
func AggFieldType(tps []*FieldType) *FieldType { | ||
var currType FieldType | ||
isMixedSign := false | ||
for i, t := range tps { | ||
if i == 0 && currType.Tp == mysql.TypeUnspecified { | ||
currType = *t | ||
continue | ||
} | ||
mtp := MergeFieldType(currType.Tp, t.Tp) | ||
isMixedSign = isMixedSign || (mysql.HasUnsignedFlag(currType.Flag) != mysql.HasUnsignedFlag(t.Flag)) | ||
currType.Tp = mtp | ||
currType.Flag = mergeTypeFlag(currType.Flag, t.Flag) | ||
} | ||
// integral promotion when tps contains signed and unsigned | ||
if isMixedSign && IsTypeInteger(currType.Tp) { | ||
bumpRange := false // indicate one of tps bump currType range | ||
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. Does MySQL also bumpRange ? 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. yes, I refer from here https://github.com/mysql/mysql-server/blob/8.0/sql/item.cc#L557 |
||
for _, t := range tps { | ||
bumpRange = bumpRange || (mysql.HasUnsignedFlag(t.Flag) && (t.Tp == currType.Tp || t.Tp == mysql.TypeBit)) | ||
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. Why check 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. because the TypeBit can't be mergeType and assume it max range bit(64). so it must bump. Whether it will be consistent with mysql in the future. if not, No need to consider |
||
} | ||
if bumpRange { | ||
switch currType.Tp { | ||
case mysql.TypeTiny: | ||
currType.Tp = mysql.TypeShort | ||
case mysql.TypeShort: | ||
currType.Tp = mysql.TypeInt24 | ||
case mysql.TypeInt24: | ||
currType.Tp = mysql.TypeLong | ||
case mysql.TypeLong: | ||
currType.Tp = mysql.TypeLonglong | ||
case mysql.TypeLonglong: | ||
currType.Tp = mysql.TypeNewDecimal | ||
} | ||
} | ||
} | ||
|
||
return &currType | ||
} | ||
|
@@ -311,10 +334,10 @@ func MergeFieldType(a byte, b byte) byte { | |
} | ||
|
||
// mergeTypeFlag merges two MySQL type flag to a new one | ||
// currently only NotNullFlag is checked | ||
// todo more flag need to be checked, for example: UnsignedFlag | ||
// currently only NotNullFlag and UnsignedFlag is checked | ||
// todo more flag need to be checked | ||
func mergeTypeFlag(a, b uint) uint { | ||
return a & (b&mysql.NotNullFlag | ^mysql.NotNullFlag) | ||
return a & (b&mysql.NotNullFlag | ^mysql.NotNullFlag) & (b&mysql.UnsignedFlag | ^mysql.UnsignedFlag) | ||
} | ||
|
||
func getFieldTypeIndex(tp byte) int { | ||
|
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.
I do not understand why we need to change these 2 funcs
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.
because i make test fail when i modify AggFieldType. The test is https://github.com/pingcap/tidb/blob/master/planner/cascades/transformation_rules_test.go#L389. "SQL": "select count(b), sum(b), avg(b), b, max(b), min(b), bit_and(b), bit_or(b), bit_xor(b) from t group by a having sum(b) >= 0 and count(b) >= 0 order by b",
The reason for fail is that the bit_or will add a cast wrap (cast(b as bigint unsigned binary), the arg is unsigned.
the TransformAggToProj will add ifnull wrap ifnull(cast(b as bigint unsigned binary), expression.NewZero()).
ifnull use AggFieldType infer type to tigger integral promotion.
https://github.com/pingcap/tidb/blob/master/planner/core/rule_aggregation_elimination.go#L124
I think this is a easy way to process. what do you think?