Skip to content
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: fix between ... and ... get wrong result for partition table #49853

Merged
merged 3 commits into from
Dec 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 47 additions & 12 deletions pkg/planner/core/rule_partition_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,17 +180,31 @@ func (s *partitionProcessor) getUsedHashPartitions(ctx sessionctx.Context,
posHigh--
}

var rangeScalar float64
var rangeScalar uint64
var offset int64
if mysql.HasUnsignedFlag(col.RetType.GetFlag()) {
rangeScalar = float64(uint64(posHigh)) - float64(uint64(posLow)) // use float64 to avoid integer overflow
// Avoid integer overflow
if uint64(posHigh) < uint64(posLow) {
rangeScalar = 0
} else {
rangeScalar = uint64(posHigh) - uint64(posLow)
offset = int64(uint64(posLow) % uint64(numPartitions))
}
} else {
rangeScalar = float64(posHigh) - float64(posLow) // use float64 to avoid integer overflow
// Avoid integer overflow
if posHigh < posLow {
rangeScalar = 0
} else {
rangeScalar = uint64(posHigh - posLow)
offset = mathutil.Abs(posLow % int64(numPartitions))
}
}

// if range is less than the number of partitions, there will be unused partitions we can prune out.
if rangeScalar < float64(numPartitions) && !highIsNull && !lowIsNull {
for i := posLow; i <= posHigh; i++ {
idx := mathutil.Abs(i % int64(pi.Num))
if rangeScalar < uint64(numPartitions) && !highIsNull && !lowIsNull {
var i int64
for i = 0; i <= int64(rangeScalar); i++ {
idx := (offset + i) % int64(numPartitions)
if len(partitionNames) > 0 && !s.findByName(partitionNames, pi.Definitions[idx].Name.L) {
continue
}
Expand Down Expand Up @@ -280,26 +294,47 @@ func (s *partitionProcessor) getUsedKeyPartitions(ctx sessionctx.Context,
posHigh--
}

var rangeScalar float64
var rangeScalar uint64
if mysql.HasUnsignedFlag(col.RetType.GetFlag()) {
rangeScalar = float64(uint64(posHigh)) - float64(uint64(posLow)) // use float64 to avoid integer overflow
// Avoid integer overflow
if uint64(posHigh) < uint64(posLow) {
rangeScalar = 0
} else {
rangeScalar = uint64(posHigh) - uint64(posLow)
}
} else {
rangeScalar = float64(posHigh) - float64(posLow) // use float64 to avoid integer overflow
// Avoid integer overflow
if posHigh < posLow {
rangeScalar = 0
} else {
rangeScalar = uint64(posHigh - posLow)
}
}

// if range is less than the number of partitions, there will be unused partitions we can prune out.
if rangeScalar < float64(pi.Num) && !highIsNull && !lowIsNull {
for i := posLow; i <= posHigh; i++ {
d := types.NewIntDatum(i)
if rangeScalar < pi.Num && !highIsNull && !lowIsNull {
m := make(map[int]struct{})
for i := 0; i <= int(rangeScalar); i++ {
var d types.Datum
if mysql.HasUnsignedFlag(col.RetType.GetFlag()) {
d = types.NewUintDatum(uint64(posLow) + uint64(i))
} else {
d = types.NewIntDatum(posLow + int64(i))
}
idx, err := pe.LocateKeyPartition(pi.Num, []types.Datum{d})
if err != nil {
// If we failed to get the point position, we can just skip and ignore it.
continue
}
if _, ok := m[idx]; ok {
// Keys maybe in a same partition, we should skip.
continue
}
if len(partitionNames) > 0 && !s.findByName(partitionNames, pi.Definitions[idx].Name.L) {
continue
}
used = append(used, idx)
m[idx] = struct{}{}
}
continue
}
Expand Down
64 changes: 64 additions & 0 deletions tests/integrationtest/r/executor/partition/issues.result
Original file line number Diff line number Diff line change
Expand Up @@ -459,3 +459,67 @@ IndexJoin_20 0.80 root inner join, inner:TableReader_19, outer key:executor__pa
└─TableRangeScan_17 0.80 cop[tikv] table:c range: decided by [eq(executor__partition__issues.c.txt_account_id, executor__partition__issues.t.txn_account_id) eq(executor__partition__issues.c.serial_id, executor__partition__issues.t.serial_id) eq(executor__partition__issues.c.occur_trade_date, 2022-11-17 00:00:00.000000)], keep order:false
set @@tidb_opt_advanced_join_hint=default;
set tidb_partition_prune_mode=default;
drop table if exists t;
CREATE TABLE `t` (
`col_51` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`col_51`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
PARTITION BY HASH (`col_51`) PARTITIONS 5;
insert into t values (9223372036854775807), (9223372036854775808), (9223372036854775809);
analyze table t;
desc SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN 9223372036854775807 AND 9223372036854775808;
id estRows task access object operator info
TableReader_6 2.00 root partition:p2,p3 data:TableRangeScan_5
└─TableRangeScan_5 2.00 cop[tikv] table:t range:[9223372036854775807,9223372036854775808], keep order:false
SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN 9223372036854775807 AND 9223372036854775808;
col_51
9223372036854775807
9223372036854775808
drop table if exists t;
CREATE TABLE `t` (
`col_51` bigint(20) NOT NULL,
PRIMARY KEY (`col_51`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
PARTITION BY HASH (`col_51`) PARTITIONS 5;
insert into t values (9223372036854775807), (-9223372036854775808);
analyze table t;
desc SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN -9223372036854775808 AND 9223372036854775807;
id estRows task access object operator info
TableReader_6 2.00 root partition:all data:TableFullScan_5
└─TableFullScan_5 2.00 cop[tikv] table:t keep order:false
SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN -9223372036854775808 AND 9223372036854775807;
col_51
-9223372036854775808
9223372036854775807
drop table if exists t;
CREATE TABLE `t` (
`col_51` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`col_51`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
PARTITION BY KEY (`col_51`) PARTITIONS 5;
insert into t values (9223372036854775807), (9223372036854775808), (9223372036854775809);
analyze table t;
desc SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN 9223372036854775807 AND 9223372036854775808;
id estRows task access object operator info
TableReader_6 2.00 root partition:p2 data:TableRangeScan_5
└─TableRangeScan_5 2.00 cop[tikv] table:t range:[9223372036854775807,9223372036854775808], keep order:false
SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN 9223372036854775807 AND 9223372036854775808;
col_51
9223372036854775807
9223372036854775808
drop table if exists t;
CREATE TABLE `t` (
`col_51` bigint(20) NOT NULL,
PRIMARY KEY (`col_51`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
PARTITION BY KEY (`col_51`) PARTITIONS 5;
insert into t values (9223372036854775807), (-9223372036854775808);
analyze table t;
desc SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN -9223372036854775808 AND 9223372036854775807;
id estRows task access object operator info
TableReader_6 2.00 root partition:all data:TableFullScan_5
└─TableFullScan_5 2.00 cop[tikv] table:t keep order:false
SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN -9223372036854775808 AND 9223372036854775807;
col_51
-9223372036854775808
9223372036854775807
52 changes: 52 additions & 0 deletions tests/integrationtest/t/executor/partition/issues.test
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,55 @@ from
and c.occur_trade_date = '2022-11-17' and c.serial_id = t.serial_id;
set @@tidb_opt_advanced_join_hint=default;
set tidb_partition_prune_mode=default;


# TestIssue49842
## For Hash partition
drop table if exists t;
CREATE TABLE `t` (
`col_51` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`col_51`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
PARTITION BY HASH (`col_51`) PARTITIONS 5;
insert into t values (9223372036854775807), (9223372036854775808), (9223372036854775809);
analyze table t;
desc SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN 9223372036854775807 AND 9223372036854775808;
--sorted_result
SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN 9223372036854775807 AND 9223372036854775808;

drop table if exists t;
CREATE TABLE `t` (
`col_51` bigint(20) NOT NULL,
PRIMARY KEY (`col_51`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
PARTITION BY HASH (`col_51`) PARTITIONS 5;
insert into t values (9223372036854775807), (-9223372036854775808);
analyze table t;
desc SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN -9223372036854775808 AND 9223372036854775807;
--sorted_result
SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN -9223372036854775808 AND 9223372036854775807;

## For Key partition
drop table if exists t;
CREATE TABLE `t` (
`col_51` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`col_51`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
PARTITION BY KEY (`col_51`) PARTITIONS 5;
insert into t values (9223372036854775807), (9223372036854775808), (9223372036854775809);
analyze table t;
desc SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN 9223372036854775807 AND 9223372036854775808;
--sorted_result
SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN 9223372036854775807 AND 9223372036854775808;

drop table if exists t;
CREATE TABLE `t` (
`col_51` bigint(20) NOT NULL,
PRIMARY KEY (`col_51`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
PARTITION BY KEY (`col_51`) PARTITIONS 5;
insert into t values (9223372036854775807), (-9223372036854775808);
analyze table t;
desc SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN -9223372036854775808 AND 9223372036854775807;
--sorted_result
SELECT * FROM `t` WHERE `t`.`col_51` BETWEEN -9223372036854775808 AND 9223372036854775807;