Skip to content

Commit 645e4bb

Browse files
Defined2014ti-chi-bot
authored andcommitted
This is an automated cherry-pick of pingcap#57344
Signed-off-by: ti-chi-bot <[email protected]>
1 parent 1a581e1 commit 645e4bb

File tree

3 files changed

+71
-12
lines changed

3 files changed

+71
-12
lines changed

pkg/planner/core/partition_pruning_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,60 @@ func TestPartitionRangeColumnsForExpr(t *testing.T) {
576576
}
577577
}
578578

579+
func TestPartitionRangeColumnsForExprWithSpecialCollation(t *testing.T) {
580+
tc := prepareTestCtx(t, "create table t (a varchar(255) COLLATE utf8mb4_0900_ai_ci, b varchar(255) COLLATE utf8mb4_unicode_ci)", "a,b")
581+
lessThan := make([][]*expression.Expression, 0, 6)
582+
partDefs := [][]string{
583+
{"'i'", "'i'"},
584+
{"MAXVALUE", "MAXVALUE"},
585+
}
586+
for i := range partDefs {
587+
l := make([]*expression.Expression, 0, 2)
588+
for j := range []int{0, 1} {
589+
v := partDefs[i][j]
590+
var e *expression.Expression
591+
if v == "MAXVALUE" {
592+
e = nil // MAXVALUE
593+
} else {
594+
expr, err := expression.ParseSimpleExpr(tc.sctx, v, expression.WithInputSchemaAndNames(tc.schema, tc.names, nil))
595+
require.NoError(t, err)
596+
e = &expr
597+
}
598+
l = append(l, e)
599+
}
600+
lessThan = append(lessThan, l)
601+
}
602+
pruner := &rangeColumnsPruner{lessThan, tc.columns[:2]}
603+
cases := []struct {
604+
input string
605+
result partitionRangeOR
606+
}{
607+
{"a = 'q'", partitionRangeOR{{1, 2}}},
608+
{"a = 'Q'", partitionRangeOR{{1, 2}}},
609+
{"a = 'a'", partitionRangeOR{{0, 1}}},
610+
{"a = 'A'", partitionRangeOR{{0, 1}}},
611+
{"a > 'a'", partitionRangeOR{{0, 2}}},
612+
{"a > 'q'", partitionRangeOR{{1, 2}}},
613+
{"a = 'i' and b = 'q'", partitionRangeOR{{1, 2}}},
614+
{"a = 'i' and b = 'Q'", partitionRangeOR{{1, 2}}},
615+
{"a = 'i' and b = 'a'", partitionRangeOR{{0, 1}}},
616+
{"a = 'i' and b = 'A'", partitionRangeOR{{0, 1}}},
617+
{"a = 'i' and b > 'a'", partitionRangeOR{{0, 2}}},
618+
{"a = 'i' and b > 'q'", partitionRangeOR{{1, 2}}},
619+
{"a = 'i' or a = 'h'", partitionRangeOR{{0, 2}}},
620+
{"a = 'h' and a = 'j'", partitionRangeOR{}},
621+
}
622+
623+
for _, ca := range cases {
624+
expr, err := expression.ParseSimpleExpr(tc.sctx, ca.input, expression.WithInputSchemaAndNames(tc.schema, tc.names, nil))
625+
require.NoError(t, err)
626+
result := fullRange(len(lessThan))
627+
e := expression.SplitCNFItems(expr)
628+
result = partitionRangeForCNFExpr(tc.sctx, e, pruner, result)
629+
require.Truef(t, equalPartitionRangeOR(ca.result, result), "unexpected: %v %v != %v", ca.input, ca.result, result)
630+
}
631+
}
632+
579633
func benchmarkRangeColumnsPruner(b *testing.B, parts int) {
580634
tc := prepareBenchCtx("create table t (a bigint unsigned, b int, c int)", "a")
581635
if tc == nil {

pkg/planner/core/rule_partition_processor.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,7 +1281,11 @@ func multiColumnRangeColumnsPruner(sctx PlanContext, exprs []expression.Expressi
12811281
lens = append(lens, columnsPruner.partCols[i].RetType.GetFlen())
12821282
}
12831283

1284+
<<<<<<< HEAD
12841285
res, err := ranger.DetachCondAndBuildRangeForIndex(sctx, exprs, columnsPruner.partCols, lens, sctx.GetSessionVars().RangeMaxSize)
1286+
=======
1287+
res, err := ranger.DetachCondAndBuildRangeForPartition(sctx.GetRangerCtx(), exprs, columnsPruner.partCols, lens, sctx.GetSessionVars().RangeMaxSize)
1288+
>>>>>>> 3c70a289b27 (planner: fix RANGE COLUMNS partition prune gives wrong result with special collation (#57344))
12851289
if err != nil {
12861290
return fullRange(len(columnsPruner.lessThan))
12871291
}
@@ -1296,16 +1300,12 @@ func multiColumnRangeColumnsPruner(sctx PlanContext, exprs []expression.Expressi
12961300

12971301
rangeOr := make([]partitionRange, 0, len(res.Ranges))
12981302

1299-
comparer := make([]collate.Collator, 0, len(columnsPruner.partCols))
1300-
for i := range columnsPruner.partCols {
1301-
comparer = append(comparer, collate.GetCollator(columnsPruner.partCols[i].RetType.GetCollate()))
1302-
}
13031303
gotError := false
13041304
// Create a sort.Search where the compare loops over ColumnValues
13051305
// Loop over the different ranges and extend/include all the partitions found
13061306
for idx := range res.Ranges {
1307-
minComparer := minCmp(sctx, res.Ranges[idx].LowVal, columnsPruner, comparer, res.Ranges[idx].LowExclude, &gotError)
1308-
maxComparer := maxCmp(sctx, res.Ranges[idx].HighVal, columnsPruner, comparer, res.Ranges[idx].HighExclude, &gotError)
1307+
minComparer := minCmp(sctx, res.Ranges[idx].LowVal, columnsPruner, res.Ranges[idx].Collators, res.Ranges[idx].LowExclude, &gotError)
1308+
maxComparer := maxCmp(sctx, res.Ranges[idx].HighVal, columnsPruner, res.Ranges[idx].Collators, res.Ranges[idx].HighExclude, &gotError)
13091309
if gotError {
13101310
// the compare function returned error, use all partitions.
13111311
return fullRange(len(columnsPruner.lessThan))
@@ -1914,10 +1914,9 @@ func makeRangeColumnPruner(columns []*expression.Column, pi *model.PartitionInfo
19141914
if len(pi.Definitions) != len(from.LessThan) {
19151915
return nil, errors.Trace(fmt.Errorf("internal error len(pi.Definitions) != len(from.LessThan) %d != %d", len(pi.Definitions), len(from.LessThan)))
19161916
}
1917-
schema := expression.NewSchema(columns...)
19181917
partCols := make([]*expression.Column, len(offsets))
19191918
for i, offset := range offsets {
1920-
partCols[i] = schema.Columns[offset]
1919+
partCols[i] = columns[offset]
19211920
}
19221921
lessThan := make([][]*expression.Expression, 0, len(from.LessThan))
19231922
for i := range from.LessThan {

pkg/util/ranger/detacher.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ func extractBestCNFItemRanges(sctx planctx.PlanContext, conds []expression.Expre
261261
// We build ranges for `(a,b) in ((1,1),(1,2))` and get `[1 1, 1 1] [1 2, 1 2]`, which are point ranges and we can
262262
// append `c = 1` to the point ranges. However, if we choose to merge consecutive ranges here, we get `[1 1, 1 2]`,
263263
// which are not point ranges, and we cannot append `c = 1` anymore.
264-
res, err := detachCondAndBuildRangeWithoutMerging(sctx, tmpConds, cols, lengths, rangeMaxSize, convertToSortKey)
264+
res, err := detachCondAndBuildRange(sctx, tmpConds, cols, lengths, rangeMaxSize, convertToSortKey, false)
265265
if err != nil {
266266
return nil, nil, err
267267
}
@@ -418,7 +418,7 @@ func (d *rangeDetacher) detachCNFCondAndBuildRangeForIndex(conditions []expressi
418418
if eqOrInCount > 0 {
419419
newCols := d.cols[eqOrInCount:]
420420
newLengths := d.lengths[eqOrInCount:]
421-
tailRes, err := DetachCondAndBuildRangeForIndex(d.sctx, newConditions, newCols, newLengths, d.rangeMaxSize)
421+
tailRes, err := detachCondAndBuildRange(d.sctx, newConditions, newCols, newLengths, d.rangeMaxSize, d.convertToSortKey, d.mergeConsecutive)
422422
if err != nil {
423423
return nil, err
424424
}
@@ -892,16 +892,22 @@ func DetachCondAndBuildRangeForIndex(sctx planctx.PlanContext, conditions []expr
892892
return d.detachCondAndBuildRangeForCols()
893893
}
894894

895+
<<<<<<< HEAD
895896
// detachCondAndBuildRangeWithoutMerging detaches the index filters from table filters and uses them to build ranges.
896897
// When building ranges, it doesn't merge consecutive ranges.
897898
func detachCondAndBuildRangeWithoutMerging(sctx planctx.PlanContext, conditions []expression.Expression, cols []*expression.Column,
898899
lengths []int, rangeMaxSize int64, convertToSortKey bool) (*DetachRangeResult, error) {
900+
=======
901+
// detachCondAndBuildRange detaches the index filters from table filters and uses them to build ranges.
902+
func detachCondAndBuildRange(sctx *rangerctx.RangerContext, conditions []expression.Expression, cols []*expression.Column,
903+
lengths []int, rangeMaxSize int64, convertToSortKey bool, mergeConsecutive bool) (*DetachRangeResult, error) {
904+
>>>>>>> 3c70a289b27 (planner: fix RANGE COLUMNS partition prune gives wrong result with special collation (#57344))
899905
d := &rangeDetacher{
900906
sctx: sctx,
901907
allConds: conditions,
902908
cols: cols,
903909
lengths: lengths,
904-
mergeConsecutive: false,
910+
mergeConsecutive: mergeConsecutive,
905911
convertToSortKey: convertToSortKey,
906912
rangeMaxSize: rangeMaxSize,
907913
}
@@ -914,7 +920,7 @@ func detachCondAndBuildRangeWithoutMerging(sctx planctx.PlanContext, conditions
914920
// The returned values are encapsulated into a struct DetachRangeResult, see its comments for explanation.
915921
func DetachCondAndBuildRangeForPartition(sctx planctx.PlanContext, conditions []expression.Expression, cols []*expression.Column,
916922
lengths []int, rangeMaxSize int64) (*DetachRangeResult, error) {
917-
return detachCondAndBuildRangeWithoutMerging(sctx, conditions, cols, lengths, rangeMaxSize, false)
923+
return detachCondAndBuildRange(sctx, conditions, cols, lengths, rangeMaxSize, false, false)
918924
}
919925

920926
type rangeDetacher struct {

0 commit comments

Comments
 (0)