Skip to content

Commit

Permalink
fix the issue that UnionAll didn't handle the range bump case
Browse files Browse the repository at this point in the history
Signed-off-by: Yang Keao <[email protected]>
  • Loading branch information
YangKeao committed Apr 12, 2024
1 parent 0362dc8 commit 1143223
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 4 deletions.
16 changes: 16 additions & 0 deletions pkg/planner/core/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/pingcap/tidb/pkg/infoschema"
"github.com/pingcap/tidb/pkg/parser/auth"
"github.com/pingcap/tidb/pkg/parser/model"
"github.com/pingcap/tidb/pkg/parser/mysql"
"github.com/pingcap/tidb/pkg/planner/core"
"github.com/pingcap/tidb/pkg/sessionctx/variable"
"github.com/pingcap/tidb/pkg/table"
Expand Down Expand Up @@ -2269,3 +2270,18 @@ func TestIssue48257(t *testing.T) {
"└─TableFullScan 1.00 cop[tikv] table:t1 keep order:false",
))
}

func TestIssue52472(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)

tk.MustExec("use test")
tk.MustExec("CREATE TABLE t1 ( c1 int);")
tk.MustExec("CREATE TABLE t2 ( c1 int unsigned);")
tk.MustExec("INSERT INTO t1 (c1) VALUES (8);")
tk.MustExec("INSERT INTO t2 (c1) VALUES (2454396638);")
rs, err := tk.Exec("SELECT c1 FROM t1 UNION ALL SELECT c1 FROM t2")
require.NoError(t, err)
require.Len(t, rs.Fields(), 1)
require.Equal(t, mysql.TypeLonglong, rs.Fields()[0].Column.FieldType.GetType())
}
2 changes: 1 addition & 1 deletion pkg/planner/core/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -1901,7 +1901,7 @@ func unionJoinFieldType(a, b *types.FieldType) *types.FieldType {
} else if b.GetType() == mysql.TypeNull {
return a
}
resultTp := types.NewFieldType(types.MergeFieldType(a.GetType(), b.GetType()))
resultTp := types.AggFieldType([]*types.FieldType{a, b})
// This logic will be intelligible when it is associated with the buildProjection4Union logic.
if resultTp.GetType() == mysql.TypeNewDecimal {
// The decimal result type will be unsigned only when all the decimals to be united are unsigned.
Expand Down
10 changes: 7 additions & 3 deletions pkg/types/field_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func AggFieldType(tps []*FieldType) *FieldType {
currType = *t
continue
}
mtp := MergeFieldType(currType.GetType(), t.GetType())
mtp := mergeFieldType(currType.GetType(), t.GetType())
isMixedSign = isMixedSign || (mysql.HasUnsignedFlag(currType.GetFlag()) != mysql.HasUnsignedFlag(t.GetFlag()))
currType.SetType(mtp)
currType.SetFlag(mergeTypeFlag(currType.GetFlag(), t.GetFlag()))
Expand Down Expand Up @@ -367,12 +367,16 @@ func DefaultCharsetForType(tp byte) (defaultCharset string, defaultCollation str
return charset.CharsetBin, charset.CollationBin
}

// MergeFieldType merges two MySQL type to a new type.
// mergeFieldType merges two MySQL type to a new type.
// This is used in hybrid field type expression.
// For example "select case c when 1 then 2 when 2 then 'tidb' from t;"
// The result field type of the case expression is the merged type of the two when clause.
// See https://github.com/mysql/mysql-server/blob/8.0/sql/field.cc#L1042
func MergeFieldType(a byte, b byte) byte {
//
// This function doesn't handle the range bump: for example, when the unsigned long is merged with signed long,
// the result should be longlong. However, this function returns long for this case. Please use `AggFieldType`
// function if you need to handle the range bump.
func mergeFieldType(a byte, b byte) byte {
ia := getFieldTypeIndex(a)
ib := getFieldTypeIndex(b)
return fieldTypeMergeRules[ia][ib]
Expand Down

0 comments on commit 1143223

Please sign in to comment.