Commit a77f80b7 authored by Oleksandr Byelkin's avatar Oleksandr Byelkin

Merge branch '10.0' into 10.1

parents 9e23171c a84d87fd
......@@ -508,3 +508,14 @@ DROP TABLE t1;
SELECT 100 BETWEEN 1 AND 9223372036854775808;
100 BETWEEN 1 AND 9223372036854775808
1
#
# MDEV-17724 Wrong result for BETWEEN 0 AND 18446744073709551615
#
CREATE TABLE t1 (c1 bigint(20) unsigned NOT NULL);
INSERT INTO t1 VALUES (0),(101),(255);
SELECT * FROM t1 WHERE c1 BETWEEN 0 AND 18446744073709551615 ORDER BY c1;
c1
0
101
255
DROP TABLE t1;
......@@ -31583,8 +31583,33 @@ c1 c2 c3 c4 c5 c6 c7
0 -9223372036854775808 1 2 3 4 5
SELECT * FROM t2 WHERE c1 BETWEEN 0 AND 18446744073709551615 ORDER BY c1,c6;
c1 c2 c3 c4 c5 c6 c7
0 NULL 5 6 NULL 0 NULL
0 -9223372036854775808 1 2 3 4 5
0 0 17 18 19 20 21
0 124 22 23 24 25 26
0 124 27 28 29 30 31
0 -9223372036854775808 31 32 33 34 35
0 0 32 32 34 35 36
101 0 37 38 39 40 41
101 -102 103 104 105 106 107
102 -109 110 111 112 113 114
103 -109 110 111 112 113 114
105 NULL 102 103 104 105 106
108 -109 110 111 112 101 114
108 -109 110 111 112 102 114
108 -109 110 111 112 113 114
115 -116 117 118 119 120 121
122 -123 124 125 126 127 128
255 -2147483648 6 7 8 9 10
65535 -8388608 11 12 13 14 15
16777215 -32768 16 17 18 19 20
4294967295 -128 21 22 23 24 25
18446744073709551615 9223372036854775807 26 27 28 29 30
18446744073709551615 9223372036854775807 36 37 38 39 40
SELECT * FROM t2 WHERE c1 BETWEEN 0 AND 18446744073709551615 ORDER BY c1,c6 LIMIT 2;
c1 c2 c3 c4 c5 c6 c7
0 NULL 5 6 NULL 0 NULL
0 -9223372036854775808 1 2 3 4 5
SELECT * FROM t2 WHERE c1 IN (0,18446744073709551615) ORDER BY c1,c6;
c1 c2 c3 c4 c5 c6 c7
0 NULL 5 6 NULL 0 NULL
......@@ -31744,8 +31769,33 @@ c1 c2 c3 c4 c5 c6 c7
0 -9223372036854775808 31 32 33 34 35
SELECT * FROM t2 WHERE c1 BETWEEN 0 AND 18446744073709551615 ORDER BY c1,c6 DESC;
c1 c2 c3 c4 c5 c6 c7
0 0 32 32 34 35 36
0 -9223372036854775808 31 32 33 34 35
0 124 27 28 29 30 31
0 124 22 23 24 25 26
0 0 17 18 19 20 21
0 -9223372036854775808 1 2 3 4 5
0 NULL 5 6 NULL 0 NULL
101 -102 103 104 105 106 107
101 0 37 38 39 40 41
102 -109 110 111 112 113 114
103 -109 110 111 112 113 114
105 NULL 102 103 104 105 106
108 -109 110 111 112 113 114
108 -109 110 111 112 102 114
108 -109 110 111 112 101 114
115 -116 117 118 119 120 121
122 -123 124 125 126 127 128
255 -2147483648 6 7 8 9 10
65535 -8388608 11 12 13 14 15
16777215 -32768 16 17 18 19 20
4294967295 -128 21 22 23 24 25
18446744073709551615 9223372036854775807 36 37 38 39 40
18446744073709551615 9223372036854775807 26 27 28 29 30
SELECT * FROM t2 WHERE c1 BETWEEN 0 AND 18446744073709551615 ORDER BY c1,c6 DESC LIMIT 2;
c1 c2 c3 c4 c5 c6 c7
0 0 32 32 34 35 36
0 -9223372036854775808 31 32 33 34 35
SELECT * FROM t2 WHERE c1 IN (0,18446744073709551615) ORDER BY c1,c6 DESC;
c1 c2 c3 c4 c5 c6 c7
0 0 32 32 34 35 36
......@@ -32011,8 +32061,33 @@ c1 c2 c3 c4 c5 c6 c7
18446744073709551615 9223372036854775807 36 37 38 39 40
SELECT * FROM t2 WHERE c1 BETWEEN 0 AND 18446744073709551615 ORDER BY c1,c6;
c1 c2 c3 c4 c5 c6 c7
0 NULL 5 6 NULL 0 NULL
0 -9223372036854775808 1 2 3 4 5
0 0 17 18 19 20 21
0 124 22 23 24 25 26
0 124 27 28 29 30 31
0 -9223372036854775808 31 32 33 34 35
0 0 32 32 34 35 36
101 0 37 38 39 40 41
101 -102 103 104 105 106 107
102 -109 110 111 112 113 114
103 -109 110 111 112 113 114
105 NULL 102 103 104 105 106
108 -109 110 111 112 101 114
108 -109 110 111 112 102 114
108 -109 110 111 112 113 114
115 -116 117 118 119 120 121
122 -123 124 125 126 127 128
255 -2147483648 6 7 8 9 10
65535 -8388608 11 12 13 14 15
16777215 -32768 16 17 18 19 20
4294967295 -128 21 22 23 24 25
18446744073709551615 9223372036854775807 26 27 28 29 30
18446744073709551615 9223372036854775807 36 37 38 39 40
SELECT * FROM t2 WHERE c1 BETWEEN 0 AND 18446744073709551615 ORDER BY c1,c6 LIMIT 2;
c1 c2 c3 c4 c5 c6 c7
0 NULL 5 6 NULL 0 NULL
0 -9223372036854775808 1 2 3 4 5
SELECT * FROM t2 WHERE c1 IN (0,18446744073709551615) ORDER BY c1,c6;
c1 c2 c3 c4 c5 c6 c7
0 NULL 5 6 NULL 0 NULL
......@@ -32172,8 +32247,33 @@ c1 c2 c3 c4 c5 c6 c7
18446744073709551615 9223372036854775807 26 27 28 29 30
SELECT * FROM t2 WHERE c1 BETWEEN 0 AND 18446744073709551615 ORDER BY c1,c6 DESC;
c1 c2 c3 c4 c5 c6 c7
0 0 32 32 34 35 36
0 -9223372036854775808 31 32 33 34 35
0 124 27 28 29 30 31
0 124 22 23 24 25 26
0 0 17 18 19 20 21
0 -9223372036854775808 1 2 3 4 5
0 NULL 5 6 NULL 0 NULL
101 -102 103 104 105 106 107
101 0 37 38 39 40 41
102 -109 110 111 112 113 114
103 -109 110 111 112 113 114
105 NULL 102 103 104 105 106
108 -109 110 111 112 113 114
108 -109 110 111 112 102 114
108 -109 110 111 112 101 114
115 -116 117 118 119 120 121
122 -123 124 125 126 127 128
255 -2147483648 6 7 8 9 10
65535 -8388608 11 12 13 14 15
16777215 -32768 16 17 18 19 20
4294967295 -128 21 22 23 24 25
18446744073709551615 9223372036854775807 36 37 38 39 40
18446744073709551615 9223372036854775807 26 27 28 29 30
SELECT * FROM t2 WHERE c1 BETWEEN 0 AND 18446744073709551615 ORDER BY c1,c6 DESC LIMIT 2;
c1 c2 c3 c4 c5 c6 c7
0 0 32 32 34 35 36
0 -9223372036854775808 31 32 33 34 35
SELECT * FROM t2 WHERE c1 IN (0,18446744073709551615) ORDER BY c1,c6 DESC;
c1 c2 c3 c4 c5 c6 c7
0 0 32 32 34 35 36
......
......@@ -3768,8 +3768,25 @@ c1 c2 c3
-12 18446744073709551615 12
SELECT * FROM t2 WHERE c2 BETWEEN 0 AND 18446744073709551615 ORDER BY c2,c1;
c1 c2 c3
-4 4 4
-9 9 9
0 255 13
-9223372036854775808 18446744073709551615 12
-12 18446744073709551615 12
-11 18446744073709551615 11
-8 18446744073709551615 8
-7 18446744073709551615 7
-6 18446744073709551615 6
-5 18446744073709551615 5
-3 18446744073709551615 3
-2 18446744073709551615 2
-1 18446744073709551615 1
50 18446744073709551615 10
9223372036854775807 18446744073709551615 14
SELECT * FROM t2 WHERE c2 BETWEEN 0 AND 18446744073709551615 ORDER BY c2,c1 DESC LIMIT 2;
c1 c2 c3
-4 4 4
-9 9 9
SELECT * FROM t2 WHERE c2 IN(0,18446744073709551615) ORDER BY c2,c1 DESC;
c1 c2 c3
9223372036854775807 18446744073709551615 14
......
......@@ -414,3 +414,12 @@ DROP TABLE t1;
--echo # MDEV-9372 select 100 between 1 and 9223372036854775808 returns false
--echo #
SELECT 100 BETWEEN 1 AND 9223372036854775808;
--echo #
--echo # MDEV-17724 Wrong result for BETWEEN 0 AND 18446744073709551615
--echo #
CREATE TABLE t1 (c1 bigint(20) unsigned NOT NULL);
INSERT INTO t1 VALUES (0),(101),(255);
SELECT * FROM t1 WHERE c1 BETWEEN 0 AND 18446744073709551615 ORDER BY c1;
DROP TABLE t1;
......@@ -857,6 +857,10 @@ class Item: public Value_source,
If value is not null null_value flag will be reset to FALSE.
*/
virtual longlong val_int()=0;
Longlong_hybrid to_longlong_hybrid()
{
return Longlong_hybrid(val_int(), unsigned_flag);
}
/*
This is just a shortcut to avoid the cast. You should still use
unsigned_flag to check the sign of the item.
......
......@@ -118,7 +118,10 @@ static int cmp_row_type(Item* item1, Item* item2)
0 otherwise
*/
static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
static int agg_cmp_type(Item_result *type,
Item **items,
uint nitems,
bool int_uint_as_dec)
{
uint unsigned_count= items[0]->unsigned_flag;
type[0]= items[0]->cmp_type();
......@@ -140,7 +143,9 @@ static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
If all arguments are of INT type but have different unsigned_flag values,
switch to DECIMAL_RESULT.
*/
if (type[0] == INT_RESULT && unsigned_count != nitems && unsigned_count != 0)
if (int_uint_as_dec &&
type[0] == INT_RESULT &&
unsigned_count != nitems && unsigned_count != 0)
type[0]= DECIMAL_RESULT;
return 0;
}
......@@ -2131,7 +2136,7 @@ void Item_func_between::fix_length_and_dec()
*/
if (!args[0] || !args[1] || !args[2])
return;
if (agg_cmp_type(&m_compare_type, args, 3))
if (agg_cmp_type(&m_compare_type, args, 3, false))
return;
if (m_compare_type == STRING_RESULT &&
......@@ -2166,62 +2171,20 @@ void Item_func_between::fix_length_and_dec()
}
longlong Item_func_between::val_int()
longlong Item_func_between::val_int_cmp_string()
{
DBUG_ASSERT(fixed == 1);
switch (m_compare_type) {
case TIME_RESULT:
{
THD *thd= current_thd;
longlong value, a, b;
Item *cache, **ptr;
bool value_is_null, a_is_null, b_is_null;
ptr= &args[0];
enum_field_types f_type= field_type_for_temporal_comparison(compare_as_dates);
value= get_datetime_value(thd, &ptr, &cache, f_type, &value_is_null);
if (ptr != &args[0])
thd->change_item_tree(&args[0], *ptr);
if ((null_value= value_is_null))
return 0;
ptr= &args[1];
a= get_datetime_value(thd, &ptr, &cache, f_type, &a_is_null);
if (ptr != &args[1])
thd->change_item_tree(&args[1], *ptr);
ptr= &args[2];
b= get_datetime_value(thd, &ptr, &cache, f_type, &b_is_null);
if (ptr != &args[2])
thd->change_item_tree(&args[2], *ptr);
if (!a_is_null && !b_is_null)
return (longlong) ((value >= a && value <= b) != negated);
if (a_is_null && b_is_null)
null_value=1;
else if (a_is_null)
null_value= value <= b; // not null if false range.
else
null_value= value >= a;
break;
}
case STRING_RESULT:
{
String *value,*a,*b;
value=args[0]->val_str(&value0);
if ((null_value=args[0]->null_value))
return 0;
a=args[1]->val_str(&value1);
b=args[2]->val_str(&value2);
a= args[1]->val_str(&value1);
b= args[2]->val_str(&value2);
if (!args[1]->null_value && !args[2]->null_value)
return (longlong) ((sortcmp(value,a,cmp_collation.collation) >= 0 &&
sortcmp(value,b,cmp_collation.collation) <= 0) !=
negated);
if (args[1]->null_value && args[2]->null_value)
null_value=1;
null_value= true;
else if (args[1]->null_value)
{
// Set to not null if false range.
......@@ -2232,31 +2195,31 @@ longlong Item_func_between::val_int()
// Set to not null if false range.
null_value= sortcmp(value,a,cmp_collation.collation) >= 0;
}
break;
}
case INT_RESULT:
{
longlong value=args[0]->val_int(), a, b;
if ((null_value=args[0]->null_value))
return (longlong) (!null_value && negated);
}
longlong Item_func_between::val_int_cmp_int()
{
Longlong_hybrid value= args[0]->to_longlong_hybrid();
if ((null_value= args[0]->null_value))
return 0; /* purecov: inspected */
a=args[1]->val_int();
b=args[2]->val_int();
Longlong_hybrid a= args[1]->to_longlong_hybrid();
Longlong_hybrid b= args[2]->to_longlong_hybrid();
if (!args[1]->null_value && !args[2]->null_value)
return (longlong) ((value >= a && value <= b) != negated);
return (longlong) ((value.cmp(a) >= 0 && value.cmp(b) <= 0) != negated);
if (args[1]->null_value && args[2]->null_value)
null_value=1;
null_value= true;
else if (args[1]->null_value)
{
null_value= value <= b; // not null if false range.
}
null_value= value.cmp(b) <= 0; // not null if false range.
else
{
null_value= value >= a;
}
break;
}
case DECIMAL_RESULT:
{
null_value= value.cmp(a) >= 0;
return (longlong) (!null_value && negated);
}
longlong Item_func_between::val_int_cmp_decimal()
{
my_decimal dec_buf, *dec= args[0]->val_decimal(&dec_buf),
a_buf, *a_dec, b_buf, *b_dec;
if ((null_value=args[0]->null_value))
......@@ -2267,15 +2230,17 @@ longlong Item_func_between::val_int()
return (longlong) ((my_decimal_cmp(dec, a_dec) >= 0 &&
my_decimal_cmp(dec, b_dec) <= 0) != negated);
if (args[1]->null_value && args[2]->null_value)
null_value=1;
null_value= true;
else if (args[1]->null_value)
null_value= (my_decimal_cmp(dec, b_dec) <= 0);
else
null_value= (my_decimal_cmp(dec, a_dec) >= 0);
break;
}
case REAL_RESULT:
{
return (longlong) (!null_value && negated);
}
longlong Item_func_between::val_int_cmp_real()
{
double value= args[0]->val_real(),a,b;
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
......@@ -2284,7 +2249,7 @@ longlong Item_func_between::val_int()
if (!args[1]->null_value && !args[2]->null_value)
return (longlong) ((value >= a && value <= b) != negated);
if (args[1]->null_value && args[2]->null_value)
null_value=1;
null_value= true;
else if (args[1]->null_value)
{
null_value= value <= b; // not null if false range.
......@@ -2293,8 +2258,59 @@ longlong Item_func_between::val_int()
{
null_value= value >= a;
}
return (longlong) (!null_value && negated);
}
longlong Item_func_between::val_int()
{
DBUG_ASSERT(fixed == 1);
switch (m_compare_type) {
case TIME_RESULT:
{
THD *thd= current_thd;
longlong value, a, b;
Item *cache, **ptr;
bool value_is_null, a_is_null, b_is_null;
ptr= &args[0];
enum_field_types f_type= field_type_for_temporal_comparison(compare_as_dates);
value= get_datetime_value(thd, &ptr, &cache, f_type, &value_is_null);
if (ptr != &args[0])
thd->change_item_tree(&args[0], *ptr);
if ((null_value= value_is_null))
return 0;
ptr= &args[1];
a= get_datetime_value(thd, &ptr, &cache, f_type, &a_is_null);
if (ptr != &args[1])
thd->change_item_tree(&args[1], *ptr);
ptr= &args[2];
b= get_datetime_value(thd, &ptr, &cache, f_type, &b_is_null);
if (ptr != &args[2])
thd->change_item_tree(&args[2], *ptr);
if (!a_is_null && !b_is_null)
return (longlong) ((value >= a && value <= b) != negated);
if (a_is_null && b_is_null)
null_value=1;
else if (a_is_null)
null_value= value <= b; // not null if false range.
else
null_value= value >= a;
break;
}
case STRING_RESULT:
return val_int_cmp_string();
case INT_RESULT:
return val_int_cmp_int();
case DECIMAL_RESULT:
return val_int_cmp_decimal();
case REAL_RESULT:
return val_int_cmp_real();
case ROW_RESULT:
DBUG_ASSERT(0);
null_value= 1;
......
......@@ -846,6 +846,11 @@ class Item_func_between :public Item_func_opt_neg
cond);
return this;
}
longlong val_int_cmp_string();
longlong val_int_cmp_int();
longlong val_int_cmp_real();
longlong val_int_cmp_decimal();
};
......
......@@ -24,12 +24,25 @@ class Longlong_hybrid
protected:
longlong m_value;
bool m_unsigned;
int cmp_signed(const Longlong_hybrid& other) const
{
return m_value < other.m_value ? -1 : m_value == other.m_value ? 0 : 1;
}
int cmp_unsigned(const Longlong_hybrid& other) const
{
return (ulonglong) m_value < (ulonglong) other.m_value ? -1 :
m_value == other.m_value ? 0 : 1;
}
public:
Longlong_hybrid(longlong nr, bool unsigned_flag)
:m_value(nr), m_unsigned(unsigned_flag)
{ }
longlong value() const { return m_value; }
bool is_unsigned() const { return m_unsigned; }
bool is_unsigned_outside_of_signed_range() const
{
return m_unsigned && ((ulonglong) m_value) > (ulonglong) LONGLONG_MAX;
}
bool neg() const { return m_value < 0 && !m_unsigned; }
ulonglong abs() const
{
......@@ -39,6 +52,21 @@ class Longlong_hybrid
return ((ulonglong) LONGLONG_MAX) + 1;
return m_value < 0 ? -m_value : m_value;
}
int cmp(const Longlong_hybrid& other) const
{
if (m_unsigned == other.m_unsigned)
return m_unsigned ? cmp_unsigned(other) : cmp_signed(other);
if (is_unsigned_outside_of_signed_range())
return 1;
if (other.is_unsigned_outside_of_signed_range())
return -1;
/*
The unsigned argument is in the range 0..LONGLONG_MAX.
The signed argument is in the range LONGLONG_MIN..LONGLONG_MAX.
Safe to compare as signed.
*/
return cmp_signed(other);
}
};
#endif // SQL_TYPE_INT_INCLUDED
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment