Skip to content

Commit

Permalink
planner: fix the issue that UnionAll didn't handle the range bump case (
Browse files Browse the repository at this point in the history
#52542)

close #52472
  • Loading branch information
YangKeao committed May 11, 2024
1 parent 536cf00 commit 09c8f96
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 44 deletions.
2 changes: 1 addition & 1 deletion pkg/planner/core/casetest/dag/testdata/plan_suite_out.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
},
{
"SQL": "select * from ((SELECT 1 a,6 b) UNION (SELECT 2,5) UNION (SELECT 2, 4) ORDER BY 1) t order by 1, 2",
"Best": "UnionAll{Dual->Projection->Projection->Dual->Projection->Projection->Dual->Projection->Projection}->HashAgg->Projection->Sort"
"Best": "UnionAll{Dual->Projection->Dual->Projection->Dual->Projection}->HashAgg->Projection->Sort"
},
{
"SQL": "select * from (select *, NULL as xxx from t) t order by xxx",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -786,12 +786,10 @@
" └─ExchangeSender 3544.89 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#14, collate: binary], [name: Column#15, collate: binary]",
" └─HashAgg 3544.89 mpp[tiflash] group by:Column#14, Column#15, ",
" └─Union 4431.11 mpp[tiflash] ",
" ├─Projection 3323.33 mpp[tiflash] cast(test.t.a, int(11) BINARY)->Column#14, test.t.b->Column#15",
" │ └─Selection 3323.33 mpp[tiflash] lt(test.t.a, 18), lt(test.t.a, 60)",
" │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo",
" └─Projection 1107.78 mpp[tiflash] cast(test.t.a, int(11) BINARY)->Column#14, test.t.b->Column#15",
" └─Selection 1107.78 mpp[tiflash] gt(test.t.b, 1), lt(test.t.a, 60)",
" └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo"
" ├─Selection 3323.33 mpp[tiflash] lt(test.t.a, 18), lt(test.t.a, 60)",
" │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo",
" └─Selection 1107.78 mpp[tiflash] gt(test.t.b, 1), lt(test.t.a, 60)",
" └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo"
],
"Warn": null
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -759,21 +759,19 @@
" └─ExchangeReceiver 3013.16 mpp[tiflash] ",
" └─ExchangeSender 3013.16 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#20, collate: binary], [name: Column#21, collate: binary]",
" └─Union 3013.16 mpp[tiflash] ",
" ├─Projection 2126.93 mpp[tiflash] cast(Column#12, bigint(21) BINARY)->Column#20, test.t.b->Column#21",
" │ └─Selection 2126.93 mpp[tiflash] lt(Column#12, 18)",
" │ └─Projection 2658.67 mpp[tiflash] Column#12, test.t.b",
" │ └─HashAgg 2658.67 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#12, funcs:firstrow(test.t.b)->test.t.b",
" │ └─ExchangeReceiver 3323.33 mpp[tiflash] ",
" │ └─ExchangeSender 3323.33 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]",
" │ └─Selection 3323.33 mpp[tiflash] lt(test.t.a, 60)",
" │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo",
" └─Projection 886.22 mpp[tiflash] cast(Column#20, bigint(21) BINARY)->Column#20, Column#21",
" └─Projection 886.22 mpp[tiflash] Column#19->Column#20, test.t.b->Column#21",
" └─HashAgg 886.22 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#19, funcs:firstrow(test.t.b)->test.t.b",
" └─ExchangeReceiver 1107.78 mpp[tiflash] ",
" └─ExchangeSender 1107.78 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]",
" └─Selection 1107.78 mpp[tiflash] gt(test.t.b, 1), lt(test.t.a, 60)",
" └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo"
" ├─Selection 2126.93 mpp[tiflash] lt(Column#12, 18)",
" │ └─Projection 2658.67 mpp[tiflash] Column#12, test.t.b",
" │ └─HashAgg 2658.67 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#12, funcs:firstrow(test.t.b)->test.t.b",
" │ └─ExchangeReceiver 3323.33 mpp[tiflash] ",
" │ └─ExchangeSender 3323.33 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]",
" │ └─Selection 3323.33 mpp[tiflash] lt(test.t.a, 60)",
" │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo",
" └─Projection 886.22 mpp[tiflash] Column#19->Column#20, test.t.b->Column#21",
" └─HashAgg 886.22 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#19, funcs:firstrow(test.t.b)->test.t.b",
" └─ExchangeReceiver 1107.78 mpp[tiflash] ",
" └─ExchangeSender 1107.78 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]",
" └─Selection 1107.78 mpp[tiflash] gt(test.t.b, 1), lt(test.t.a, 60)",
" └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo"
],
"Warn": null
},
Expand All @@ -787,23 +785,21 @@
" └─ExchangeReceiver 3013.16 mpp[tiflash] ",
" └─ExchangeSender 3013.16 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: Column#20, collate: binary], [name: Column#21, collate: binary]",
" └─Union 3013.16 mpp[tiflash] ",
" ├─Projection 2126.93 mpp[tiflash] cast(Column#12, bigint(21) BINARY)->Column#20, test.t.b->Column#21",
" │ └─Selection 2126.93 mpp[tiflash] lt(Column#12, 18)",
" │ └─Projection 2658.67 mpp[tiflash] Column#12, test.t.b",
" │ └─HashAgg 2658.67 mpp[tiflash] group by:test.t.b, funcs:sum(Column#32)->Column#12, funcs:firstrow(test.t.b)->test.t.b",
" │ └─ExchangeReceiver 2658.67 mpp[tiflash] ",
" │ └─ExchangeSender 2658.67 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]",
" │ └─HashAgg 2658.67 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#32",
" │ └─Selection 3323.33 mpp[tiflash] lt(test.t.a, 60)",
" │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo",
" └─Projection 886.22 mpp[tiflash] cast(Column#20, bigint(21) BINARY)->Column#20, Column#21",
" └─Projection 886.22 mpp[tiflash] Column#19->Column#20, test.t.b->Column#21",
" └─HashAgg 886.22 mpp[tiflash] group by:test.t.b, funcs:sum(Column#46)->Column#19, funcs:firstrow(test.t.b)->test.t.b",
" └─ExchangeReceiver 886.22 mpp[tiflash] ",
" └─ExchangeSender 886.22 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]",
" └─HashAgg 886.22 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#46",
" └─Selection 1107.78 mpp[tiflash] gt(test.t.b, 1), lt(test.t.a, 60)",
" └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo"
" ├─Selection 2126.93 mpp[tiflash] lt(Column#12, 18)",
" │ └─Projection 2658.67 mpp[tiflash] Column#12, test.t.b",
" │ └─HashAgg 2658.67 mpp[tiflash] group by:test.t.b, funcs:sum(Column#32)->Column#12, funcs:firstrow(test.t.b)->test.t.b",
" │ └─ExchangeReceiver 2658.67 mpp[tiflash] ",
" │ └─ExchangeSender 2658.67 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]",
" │ └─HashAgg 2658.67 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#32",
" │ └─Selection 3323.33 mpp[tiflash] lt(test.t.a, 60)",
" │ └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo",
" └─Projection 886.22 mpp[tiflash] Column#19->Column#20, test.t.b->Column#21",
" └─HashAgg 886.22 mpp[tiflash] group by:test.t.b, funcs:sum(Column#46)->Column#19, funcs:firstrow(test.t.b)->test.t.b",
" └─ExchangeReceiver 886.22 mpp[tiflash] ",
" └─ExchangeSender 886.22 mpp[tiflash] ExchangeType: HashPartition, Compression: FAST, Hash Cols: [name: test.t.b, collate: binary]",
" └─HashAgg 886.22 mpp[tiflash] group by:test.t.b, funcs:count(1)->Column#46",
" └─Selection 1107.78 mpp[tiflash] gt(test.t.b, 1), lt(test.t.a, 60)",
" └─TableFullScan 10000.00 mpp[tiflash] table:t pushed down filter:empty, keep order:false, stats:pseudo"
],
"Warn": null
},
Expand Down
27 changes: 27 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 @@ -2286,3 +2287,29 @@ 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("CREATE TABLE t3 ( c1 bigint unsigned);")
tk.MustExec("INSERT INTO t1 (c1) VALUES (8);")
tk.MustExec("INSERT INTO t2 (c1) VALUES (2454396638);")

// union int and unsigned int will be promoted to long long
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())
require.NoError(t, rs.Close())

// union int (even literal) and unsigned bigint will be promoted to decimal
rs, err = tk.Exec("SELECT 0 UNION ALL SELECT c1 FROM t3")
require.NoError(t, err)
require.Len(t, rs.Fields(), 1)
require.Equal(t, mysql.TypeNewDecimal, rs.Fields()[0].Column.FieldType.GetType())
require.NoError(t, rs.Close())
}
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 @@ -1904,7 +1904,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
2 changes: 1 addition & 1 deletion tests/integrationtest/r/explain_easy.result
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ StreamAgg 1.00 root funcs:count(1)->Column#22
│ └─Projection 1.00 root Column#33, Column#34, Column#35, Column#14, Column#15, Column#16
│ └─HashAgg 1.00 root group by:explain_easy.test01.region_id, explain_easy.test01.show_date, explain_easy.test01.stat_date, funcs:firstrow(explain_easy.test01.stat_date)->Column#33, funcs:firstrow(explain_easy.test01.show_date)->Column#34, funcs:firstrow(explain_easy.test01.region_id)->Column#35, funcs:firstrow(explain_easy.test01.stat_date)->Column#14, funcs:firstrow(explain_easy.test01.show_date)->Column#15, funcs:firstrow(explain_easy.test01.region_id)->Column#16, funcs:count(1)->Column#39
│ └─TableReader 0.01 root data:Selection
│ └─Selection 0.01 cop[tikv] eq(explain_easy.test01.period, 1), ge(explain_easy.test01.stat_date, 20191202), gt(cast(explain_easy.test01.registration_num, bigint(20) BINARY), 0), le(explain_easy.test01.stat_date, 20191202)
│ └─Selection 0.01 cop[tikv] eq(explain_easy.test01.period, 1), ge(explain_easy.test01.stat_date, 20191202), gt(cast(explain_easy.test01.registration_num, decimal(20,0) BINARY), 0), le(explain_easy.test01.stat_date, 20191202)
│ └─TableFullScan 10000.00 cop[tikv] table:test01 keep order:false, stats:pseudo
└─TableReader(Probe) 2.00 root data:TableRangeScan
└─TableRangeScan 2.00 cop[tikv] table:b range: decided by [Column#16], keep order:false, stats:pseudo
Expand Down

0 comments on commit 09c8f96

Please sign in to comment.