Skip to content

Commit ce72017

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

File tree

3 files changed

+100
-22
lines changed

3 files changed

+100
-22
lines changed

pkg/planner/core/point_get_plan.go

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ import (
6161
"github.com/pingcap/tidb/pkg/util/intest"
6262
"github.com/pingcap/tidb/pkg/util/logutil"
6363
"github.com/pingcap/tidb/pkg/util/plancodec"
64+
"github.com/pingcap/tidb/pkg/util/ranger"
6465
"github.com/pingcap/tidb/pkg/util/redact"
6566
"github.com/pingcap/tidb/pkg/util/size"
6667
"github.com/pingcap/tidb/pkg/util/stringutil"
@@ -340,6 +341,7 @@ func (p *PointGetPlan) LoadTableStats(ctx sessionctx.Context) {
340341
loadTableStats(ctx, p.TblInfo, tableID)
341342
}
342343

344+
<<<<<<< HEAD
343345
// needsPartitionPruning checks if IndexValues can be used by GetPartitionIdxByRow() or if they have already been
344346
// converted to SortKey and would need GetPartitionIdxByRow() to be refactored to work, since it will unconditionally
345347
// convert it again.
@@ -394,6 +396,8 @@ func needsPartitionPruning(sctx sessionctx.Context, tblInfo *model.TableInfo, pt
394396
return partIdx, true, nil
395397
}
396398

399+
=======
400+
>>>>>>> ce538d6759f (planner: fix `PointGetPlan.PrunePartitions` function works with non-binary collate (#62002))
397401
// PrunePartitions will check which partition to use
398402
// returns true if no matching partition
399403
func (p *PointGetPlan) PrunePartitions(sctx sessionctx.Context) (bool, error) {
@@ -438,32 +442,29 @@ func (p *PointGetPlan) PrunePartitions(sctx sessionctx.Context) (bool, error) {
438442
}
439443
row := make([]types.Datum, len(p.TblInfo.Columns))
440444
if p.HandleConstant == nil && len(p.IndexValues) > 0 {
441-
partColsNames := pt.Meta().Partition.Columns
442-
if len(partColsNames) > 0 {
443-
partIdx, done, err := needsPartitionPruning(sctx, p.TblInfo, pt, p.dbName, p.IndexInfo, p.IdxCols, p.IndexValues, p.AccessConditions, p.PartitionNames)
444-
if table.ErrNoPartitionForGivenValue.Equal(err) {
445-
err = nil
446-
partIdx = nil
447-
}
448-
if err != nil {
449-
return false, err
450-
}
451-
if done {
452-
if len(partIdx) == 1 {
453-
p.PartitionIdx = &partIdx[0]
454-
return false, nil
445+
indexValues := p.IndexValues
446+
evalCtx := sctx.GetExprCtx().GetEvalCtx()
447+
// If the plan is created via the fast path, `IdxCols` will be nil here,
448+
// and the fast path does not convert the values to `sortKey`.
449+
for _, col := range p.IdxCols {
450+
// TODO: We could check whether `col` belongs to the partition columns to avoid unnecessary ranger building.
451+
// https://github.com/pingcap/tidb/pull/62002#discussion_r2171420731
452+
if !collate.IsBinCollation(col.GetType(evalCtx).GetCollate()) {
453+
// If a non-binary collation is used, the values in `p.IndexValues` are sort keys and cannot be used for partition pruning.
454+
r, err := ranger.DetachCondAndBuildRangeForPartition(sctx.GetRangerCtx(), p.AccessConditions, p.IdxCols, p.IdxColLens, sctx.GetSessionVars().RangeMaxSize)
455+
if err != nil {
456+
return false, err
455457
}
456-
if len(partIdx) == 0 {
457-
idx := -1
458-
p.PartitionIdx = &idx
459-
return true, nil
458+
if len(r.Ranges) != 1 || !r.Ranges[0].IsPoint(sctx.GetRangerCtx()) {
459+
return false, errors.Errorf("internal error, build ranger for PointGet failed")
460460
}
461-
return false, errors.Errorf("too many partitions matching for PointGetPlan")
461+
indexValues = r.Ranges[0].LowVal
462+
break
462463
}
463464
}
464465
for i := range p.IndexInfo.Columns {
465466
// TODO: Skip copying non-partitioning columns?
466-
p.IndexValues[i].Copy(&row[p.IndexInfo.Columns[i].Offset])
467+
indexValues[i].Copy(&row[p.IndexInfo.Columns[i].Offset])
467468
}
468469
} else {
469470
var dVal types.Datum
@@ -1818,7 +1819,8 @@ func getNameValuePairs(ctx expression.BuildContext, tbl *model.TableInfo, tblNam
18181819
if !ok {
18191820
return nil, false
18201821
}
1821-
if binOp.Op == opcode.LogicAnd {
1822+
switch binOp.Op {
1823+
case opcode.LogicAnd:
18221824
nvPairs, isTableDual = getNameValuePairs(ctx, tbl, tblName, nvPairs, binOp.L)
18231825
if nvPairs == nil || isTableDual {
18241826
return nil, isTableDual
@@ -1828,7 +1830,7 @@ func getNameValuePairs(ctx expression.BuildContext, tbl *model.TableInfo, tblNam
18281830
return nil, isTableDual
18291831
}
18301832
return nvPairs, isTableDual
1831-
} else if binOp.Op == opcode.EQ {
1833+
case opcode.EQ:
18321834
var (
18331835
d types.Datum
18341836
colName *ast.ColumnNameExpr

tests/integrationtest/r/planner/core/casetest/partition/partition_pruner.result

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,3 +920,40 @@ IndexLookUp_8 1.60 root partition:p1,p2
920920
├─IndexRangeScan_5(Build) 2.00 cop[tikv] table:t, index:PRIMARY(b) range:[1,1], [2,2], keep order:false, stats:pseudo
921921
└─Selection_7(Probe) 1.60 cop[tikv] like(issue42135.t.a, "%a%", 92)
922922
└─TableRowIDScan_6 2.00 cop[tikv] table:t keep order:false, stats:pseudo
923+
<<<<<<< HEAD
924+
=======
925+
drop table if exists t;
926+
CREATE TABLE `t` (
927+
`col_4` varchar(223) DEFAULT 'QKd^)QlWh#cT&3',
928+
UNIQUE KEY `idx_3` (`col_4`)
929+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
930+
PARTITION BY RANGE COLUMNS(`col_4`)
931+
(PARTITION `p0` VALUES LESS THAN ('+*8Ab='),
932+
PARTITION `p1` VALUES LESS THAN ('959#Km%JOy2EFI'),
933+
PARTITION `p2` VALUES LESS THAN ('FbL~@RpX01&CYY-%%+'),
934+
PARTITION `p3` VALUES LESS THAN ('GFB'),
935+
PARTITION `p4` VALUES LESS THAN (MAXVALUE));
936+
insert into t values ('u^D92@_4'), (null);
937+
explain format='brief' select * from t where col_4 in ( 'u^D92@_4' ,null );
938+
id estRows task access object operator info
939+
Point_Get 1.00 root table:t, partition:p4, index:idx_3(col_4)
940+
select * from t where col_4 in ( 'u^D92@_4' ,null );
941+
col_4
942+
u^D92@_4
943+
drop table if exists t;
944+
CREATE TABLE `t` (
945+
`col_95` char(181) COLLATE gbk_bin NOT NULL DEFAULT 'SaMKHTyg+nlID-X3Y',
946+
PRIMARY KEY (`col_95`) /*T![clustered_index] CLUSTERED */
947+
) ENGINE=InnoDB DEFAULT CHARSET=gbk COLLATE=gbk_bin
948+
PARTITION BY RANGE COLUMNS(`col_95`)
949+
(PARTITION `p0` VALUES LESS THAN ('6)nvX^uj0UGxqX'),
950+
PARTITION `p1` VALUES LESS THAN ('BHSluf6'),
951+
PARTITION `p2` VALUES LESS THAN (MAXVALUE));
952+
insert into t values ('58y-j)84-&Y*'), ('WNe(rS5uwmvIvFnHw'), ('j9FsMawX5uBro%$p'), ('C(#EQm@J');
953+
explain format='brief' select t.col_95 as r0 from t where t.col_95 between 'Dyw=*7nigCMh' and 'Im0*7sZ' or t.col_95 in ( '58y-j)84-&Y*' ,'WNe(rS5uwmvIvFnHw' ,'j9FsMawX5uBro%$p' ,'C(#EQm@J' ) group by t.col_95 having t.col_95 between '%^2' and '38ABfC-' or t.col_95 between 'eKCAE$d2x_hxscj' and 'zcw35^ATEEp1md=L';
954+
id estRows task access object operator info
955+
Point_Get 1.00 root table:t, partition:p2, clustered index:PRIMARY(col_95)
956+
select t.col_95 as r0 from t where t.col_95 between 'Dyw=*7nigCMh' and 'Im0*7sZ' or t.col_95 in ( '58y-j)84-&Y*' ,'WNe(rS5uwmvIvFnHw' ,'j9FsMawX5uBro%$p' ,'C(#EQm@J' ) group by t.col_95 having t.col_95 between '%^2' and '38ABfC-' or t.col_95 between 'eKCAE$d2x_hxscj' and 'zcw35^ATEEp1md=L';
957+
r0
958+
j9FsMawX5uBro%$p
959+
>>>>>>> ce538d6759f (planner: fix `PointGetPlan.PrunePartitions` function works with non-binary collate (#62002))

tests/integrationtest/t/planner/core/casetest/partition/partition_pruner.test

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,3 +310,42 @@ explain select * from t where b in (1,2);
310310
--sorted_result
311311
select * from t where b in (1,2) and a like '%a%';
312312
explain select * from t where b in (1,2) and a like '%a%';
313+
<<<<<<< HEAD
314+
=======
315+
316+
# Test issue 61726
317+
drop table if exists t;
318+
CREATE TABLE `t` (
319+
`col_4` varchar(223) DEFAULT 'QKd^)QlWh#cT&3',
320+
UNIQUE KEY `idx_3` (`col_4`)
321+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
322+
PARTITION BY RANGE COLUMNS(`col_4`)
323+
(PARTITION `p0` VALUES LESS THAN ('+*8Ab='),
324+
PARTITION `p1` VALUES LESS THAN ('959#Km%JOy2EFI'),
325+
PARTITION `p2` VALUES LESS THAN ('FbL~@RpX01&CYY-%%+'),
326+
PARTITION `p3` VALUES LESS THAN ('GFB'),
327+
PARTITION `p4` VALUES LESS THAN (MAXVALUE));
328+
329+
insert into t values ('u^D92@_4'), (null);
330+
331+
# no error
332+
explain format='brief' select * from t where col_4 in ( 'u^D92@_4' ,null );
333+
select * from t where col_4 in ( 'u^D92@_4' ,null );
334+
335+
# Test issue 61965
336+
drop table if exists t;
337+
CREATE TABLE `t` (
338+
`col_95` char(181) COLLATE gbk_bin NOT NULL DEFAULT 'SaMKHTyg+nlID-X3Y',
339+
PRIMARY KEY (`col_95`) /*T![clustered_index] CLUSTERED */
340+
) ENGINE=InnoDB DEFAULT CHARSET=gbk COLLATE=gbk_bin
341+
PARTITION BY RANGE COLUMNS(`col_95`)
342+
(PARTITION `p0` VALUES LESS THAN ('6)nvX^uj0UGxqX'),
343+
PARTITION `p1` VALUES LESS THAN ('BHSluf6'),
344+
PARTITION `p2` VALUES LESS THAN (MAXVALUE));
345+
346+
insert into t values ('58y-j)84-&Y*'), ('WNe(rS5uwmvIvFnHw'), ('j9FsMawX5uBro%$p'), ('C(#EQm@J');
347+
348+
explain format='brief' select t.col_95 as r0 from t where t.col_95 between 'Dyw=*7nigCMh' and 'Im0*7sZ' or t.col_95 in ( '58y-j)84-&Y*' ,'WNe(rS5uwmvIvFnHw' ,'j9FsMawX5uBro%$p' ,'C(#EQm@J' ) group by t.col_95 having t.col_95 between '%^2' and '38ABfC-' or t.col_95 between 'eKCAE$d2x_hxscj' and 'zcw35^ATEEp1md=L';
349+
select t.col_95 as r0 from t where t.col_95 between 'Dyw=*7nigCMh' and 'Im0*7sZ' or t.col_95 in ( '58y-j)84-&Y*' ,'WNe(rS5uwmvIvFnHw' ,'j9FsMawX5uBro%$p' ,'C(#EQm@J' ) group by t.col_95 having t.col_95 between '%^2' and '38ABfC-' or t.col_95 between 'eKCAE$d2x_hxscj' and 'zcw35^ATEEp1md=L';
350+
351+
>>>>>>> ce538d6759f (planner: fix `PointGetPlan.PrunePartitions` function works with non-binary collate (#62002))

0 commit comments

Comments
 (0)