Skip to content

Commit b0fa308

Browse files
committed
MDEV-21195 INSERT chooses wrong partition for RANGE partitioning by DECIMAL column
Use FLOOR rounding for DECIMAL_RESULT item_expr in partition function.
1 parent 74deeae commit b0fa308

File tree

5 files changed

+116
-6
lines changed

5 files changed

+116
-6
lines changed

mysql-test/main/partition_range.result

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,3 +1009,47 @@ select * from t1 partition (p1);
10091009
d
10101010
2000-01-01 00:00:01.000000
10111011
DROP TABLE t1, t2;
1012+
#
1013+
# MDEV-21195 INSERT chooses wrong partition for RANGE partitioning by DECIMAL column
1014+
#
1015+
create or replace table t (
1016+
d decimal(2,1)) partition by range (d)
1017+
(partition p1 values less than (10));
1018+
insert into t values (9.9);
1019+
create or replace table t (
1020+
d decimal(2,1)) partition by range (d)
1021+
(partition p1 values less than (10),
1022+
partition p2 values less than (20));
1023+
insert into t values (9.9);
1024+
select * from t partition (p1);
1025+
d
1026+
9.9
1027+
select * from t partition (p2);
1028+
d
1029+
create or replace table t (
1030+
d decimal(2,1)) partition by range (d)
1031+
(partition p1 values less than (-3));
1032+
insert into t values (-3.3);
1033+
create or replace table t (
1034+
d decimal(2,1)) partition by range (d+1)
1035+
(partition p1 values less than (10),
1036+
partition p2 values less than (20));
1037+
insert into t values (8.9);
1038+
select * from t partition (p1);
1039+
d
1040+
8.9
1041+
select * from t partition (p2);
1042+
d
1043+
set time_zone='+00:00';
1044+
create or replace table t (
1045+
d timestamp(1)) partition by range (unix_timestamp(d))
1046+
(partition p1 values less than (1577836800),
1047+
partition p2 values less than (2000000000));
1048+
insert into t values (from_unixtime(1577836799.9));
1049+
select * from t partition (p1);
1050+
d
1051+
2019-12-31 23:59:59.9
1052+
select * from t partition (p2);
1053+
d
1054+
set time_zone=default;
1055+
drop table t;

mysql-test/main/partition_range.test

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,3 +999,49 @@ select * from t1 partition (p0);
999999
select * from t1 partition (p1);
10001000

10011001
DROP TABLE t1, t2;
1002+
1003+
--echo #
1004+
--echo # MDEV-21195 INSERT chooses wrong partition for RANGE partitioning by DECIMAL column
1005+
--echo #
1006+
create or replace table t (
1007+
d decimal(2,1)) partition by range (d)
1008+
(partition p1 values less than (10));
1009+
1010+
insert into t values (9.9);
1011+
1012+
create or replace table t (
1013+
d decimal(2,1)) partition by range (d)
1014+
(partition p1 values less than (10),
1015+
partition p2 values less than (20));
1016+
1017+
insert into t values (9.9);
1018+
select * from t partition (p1);
1019+
select * from t partition (p2);
1020+
1021+
create or replace table t (
1022+
d decimal(2,1)) partition by range (d)
1023+
(partition p1 values less than (-3));
1024+
1025+
insert into t values (-3.3);
1026+
1027+
create or replace table t (
1028+
d decimal(2,1)) partition by range (d+1)
1029+
(partition p1 values less than (10),
1030+
partition p2 values less than (20));
1031+
1032+
insert into t values (8.9);
1033+
select * from t partition (p1);
1034+
select * from t partition (p2);
1035+
1036+
set time_zone='+00:00';
1037+
create or replace table t (
1038+
d timestamp(1)) partition by range (unix_timestamp(d))
1039+
(partition p1 values less than (1577836800),
1040+
partition p2 values less than (2000000000));
1041+
1042+
insert into t values (from_unixtime(1577836799.9));
1043+
select * from t partition (p1);
1044+
select * from t partition (p2);
1045+
1046+
set time_zone=default;
1047+
drop table t;

sql/my_decimal.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,12 @@ void my_decimal_trim(ulonglong *precision, uint *scale)
345345
*/
346346

347347
int my_decimal2int(uint mask, const decimal_t *d, bool unsigned_flag,
348-
longlong *l)
348+
longlong *l, decimal_round_mode round_type)
349349
{
350350
int res;
351351
my_decimal rounded;
352352
/* decimal_round can return only E_DEC_TRUNCATED */
353-
decimal_round(d, &rounded, 0, HALF_UP);
353+
decimal_round(d, &rounded, 0, round_type);
354354
res= (unsigned_flag ?
355355
decimal2ulonglong(&rounded, (ulonglong *) l) :
356356
decimal2longlong(&rounded, l));

sql/my_decimal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ my_decimal *seconds2my_decimal(bool sign, ulonglong sec, ulong microsec,
348348
(TIME)->second_part, (DECIMAL))
349349

350350
int my_decimal2int(uint mask, const decimal_t *d, bool unsigned_flag,
351-
longlong *l);
351+
longlong *l, decimal_round_mode round_type= HALF_UP);
352352

353353
inline
354354
int my_decimal2double(uint, const decimal_t *d, double *result)

sql/sql_partition.cc

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2840,14 +2840,34 @@ bool partition_key_modified(TABLE *table, const MY_BITMAP *fields)
28402840

28412841
static inline int part_val_int(Item *item_expr, longlong *result)
28422842
{
2843-
*result= item_expr->val_int();
2843+
switch (item_expr->cmp_type())
2844+
{
2845+
case DECIMAL_RESULT:
2846+
{
2847+
my_decimal buf;
2848+
my_decimal *val= item_expr->val_decimal(&buf);
2849+
if (val && my_decimal2int(E_DEC_FATAL_ERROR, val, item_expr->unsigned_flag,
2850+
result, FLOOR) != E_DEC_OK)
2851+
return true;
2852+
break;
2853+
}
2854+
case INT_RESULT:
2855+
*result= item_expr->val_int();
2856+
break;
2857+
case STRING_RESULT:
2858+
case REAL_RESULT:
2859+
case ROW_RESULT:
2860+
case TIME_RESULT:
2861+
DBUG_ASSERT(0);
2862+
break;
2863+
}
28442864
if (item_expr->null_value)
28452865
{
28462866
if (unlikely(current_thd->is_error()))
2847-
return TRUE;
2867+
return true;
28482868
*result= LONGLONG_MIN;
28492869
}
2850-
return FALSE;
2870+
return false;
28512871
}
28522872

28532873

0 commit comments

Comments
 (0)