Commit 0c6455aa authored by Alexander Barkov's avatar Alexander Barkov

MDEV-17249 MAKETIME(-1e50,0,0) returns a wrong result

parent e43bc02e
...@@ -2661,5 +2661,50 @@ SELECT PERIOD_DIFF(2018, AES_ENCRYPT('Rae Bareli', 'Rae Bareli')); ...@@ -2661,5 +2661,50 @@ SELECT PERIOD_DIFF(2018, AES_ENCRYPT('Rae Bareli', 'Rae Bareli'));
PERIOD_DIFF(2018, AES_ENCRYPT('Rae Bareli', 'Rae Bareli')) PERIOD_DIFF(2018, AES_ENCRYPT('Rae Bareli', 'Rae Bareli'))
24257 24257
# #
# MDEV-17249 MAKETIME(-1e50,0,0) returns a wrong result
#
SELECT
MAKETIME(1e10,0,0),
MAKETIME(-1e10,0,0),
MAKETIME(1e50,0,0),
MAKETIME(-1e50,0,0),
MAKETIME(COALESCE(1e50),0,0),
MAKETIME(COALESCE(-1e50),0,0);
MAKETIME(1e10,0,0) 838:59:59
MAKETIME(-1e10,0,0) -838:59:59
MAKETIME(1e50,0,0) 838:59:59
MAKETIME(-1e50,0,0) -838:59:59
MAKETIME(COALESCE(1e50),0,0) 838:59:59
MAKETIME(COALESCE(-1e50),0,0) -838:59:59
Warnings:
Level Warning
Code 1292
Message Truncated incorrect time value: '10000000000:00:00'
Level Warning
Code 1292
Message Truncated incorrect time value: '-10000000000:00:00'
Level Warning
Code 1292
Message Truncated incorrect time value: '9223372036854775807:00:00'
Level Warning
Code 1292
Message Truncated incorrect time value: '-9223372036854775808:00:00'
Level Warning
Code 1292
Message Truncated incorrect time value: '9223372036854775807:00:00'
Level Warning
Code 1292
Message Truncated incorrect time value: '-9223372036854775808:00:00'
CREATE TABLE t1 (a FLOAT);
INSERT INTO t1 VALUES (1e30),(-1e30);
SELECT MAKETIME(a,0,0) FROM t1;
MAKETIME(a,0,0)
838:59:59
-838:59:59
Warnings:
Warning 1292 Truncated incorrect time value: '9223372036854775807:00:00'
Warning 1292 Truncated incorrect time value: '-9223372036854775808:00:00'
DROP TABLE t1;
#
# End of 5.5 tests # End of 5.5 tests
# #
...@@ -447,3 +447,39 @@ End of 5.0 tests ...@@ -447,3 +447,39 @@ End of 5.0 tests
select format(truncate('1.7976931348623157E+308',-12),1,'fr_BE') as foo; select format(truncate('1.7976931348623157E+308',-12),1,'fr_BE') as foo;
foo foo
0 0
#
# MDEV-17249 MAKETIME(-1e50,0,0) returns a wrong result
#
SELECT LEFT('a',EXP(50));
LEFT('a',EXP(50))
a
SELECT LEFT('a', COALESCE(1e30));
LEFT('a', COALESCE(1e30))
a
CREATE TABLE t1 (a FLOAT);
INSERT INTO t1 VALUES (1e30);
SELECT LEFT('a',a), LEFT('a',1e30) FROM t1;
LEFT('a',a) LEFT('a',1e30)
a a
DROP TABLE t1;
PREPARE stmt FROM 'SELECT LEFT(111,?)';
SET @a=1e30;
EXECUTE stmt USING @a;
LEFT(111,?)
111
DEALLOCATE PREPARE stmt;
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
SELECT LEFT('a',(SELECT 1e30 FROM t1 LIMIT 1));
LEFT('a',(SELECT 1e30 FROM t1 LIMIT 1))
a
DROP TABLE t1;
CREATE TABLE t1 (a DOUBLE);
INSERT INTO t1 VALUES (1e30),(0);
SELECT LEFT('a', SUM(a)) FROM t1;
LEFT('a', SUM(a))
a
SELECT LEFT('a', AVG(a)) FROM t1;
LEFT('a', AVG(a))
a
DROP TABLE t1;
...@@ -1634,6 +1634,27 @@ SELECT SEC_TO_TIME(MAKEDATE(0,RAND(~0))); ...@@ -1634,6 +1634,27 @@ SELECT SEC_TO_TIME(MAKEDATE(0,RAND(~0)));
# #
SELECT PERIOD_DIFF(2018, AES_ENCRYPT('Rae Bareli', 'Rae Bareli')); SELECT PERIOD_DIFF(2018, AES_ENCRYPT('Rae Bareli', 'Rae Bareli'));
--echo #
--echo # MDEV-17249 MAKETIME(-1e50,0,0) returns a wrong result
--echo #
--vertical_results
SELECT
MAKETIME(1e10,0,0),
MAKETIME(-1e10,0,0),
MAKETIME(1e50,0,0),
MAKETIME(-1e50,0,0),
MAKETIME(COALESCE(1e50),0,0),
MAKETIME(COALESCE(-1e50),0,0);
--horizontal_results
CREATE TABLE t1 (a FLOAT);
INSERT INTO t1 VALUES (1e30),(-1e30);
SELECT MAKETIME(a,0,0) FROM t1;
DROP TABLE t1;
--echo # --echo #
--echo # End of 5.5 tests --echo # End of 5.5 tests
--echo # --echo #
...@@ -331,3 +331,32 @@ eval select concat((truncate((-1.7976931348623157E+307),(0x1e))), ...@@ -331,3 +331,32 @@ eval select concat((truncate((-1.7976931348623157E+307),(0x1e))),
--echo # --echo #
select format(truncate('1.7976931348623157E+308',-12),1,'fr_BE') as foo; select format(truncate('1.7976931348623157E+308',-12),1,'fr_BE') as foo;
--echo #
--echo # MDEV-17249 MAKETIME(-1e50,0,0) returns a wrong result
--echo #
SELECT LEFT('a',EXP(50));
SELECT LEFT('a', COALESCE(1e30));
CREATE TABLE t1 (a FLOAT);
INSERT INTO t1 VALUES (1e30);
SELECT LEFT('a',a), LEFT('a',1e30) FROM t1;
DROP TABLE t1;
PREPARE stmt FROM 'SELECT LEFT(111,?)';
SET @a=1e30;
EXECUTE stmt USING @a;
DEALLOCATE PREPARE stmt;
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
SELECT LEFT('a',(SELECT 1e30 FROM t1 LIMIT 1));
DROP TABLE t1;
CREATE TABLE t1 (a DOUBLE);
INSERT INTO t1 VALUES (1e30),(0);
SELECT LEFT('a', SUM(a)) FROM t1;
SELECT LEFT('a', AVG(a)) FROM t1;
DROP TABLE t1;
...@@ -3948,7 +3948,8 @@ longlong Field_float::val_int(void) ...@@ -3948,7 +3948,8 @@ longlong Field_float::val_int(void)
{ {
float j; float j;
float4get(j,ptr); float4get(j,ptr);
return (longlong) rint(j); bool error;
return double_to_longlong(j, false, &error);
} }
......
...@@ -3692,7 +3692,10 @@ longlong Item_param::val_int() ...@@ -3692,7 +3692,10 @@ longlong Item_param::val_int()
{ {
switch (state) { switch (state) {
case REAL_VALUE: case REAL_VALUE:
return (longlong) rint(value.real); {
bool error;
return double_to_longlong(value.real, unsigned_flag, &error);
}
case INT_VALUE: case INT_VALUE:
return value.integer; return value.integer;
case DECIMAL_VALUE: case DECIMAL_VALUE:
...@@ -9231,7 +9234,8 @@ longlong Item_cache_real::val_int() ...@@ -9231,7 +9234,8 @@ longlong Item_cache_real::val_int()
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!has_value()) if (!has_value())
return 0; return 0;
return (longlong) rint(value); bool error;
return double_to_longlong(value, unsigned_flag, &error);
} }
......
...@@ -999,7 +999,10 @@ longlong Item_func_hybrid_result_type::val_int() ...@@ -999,7 +999,10 @@ longlong Item_func_hybrid_result_type::val_int()
case INT_RESULT: case INT_RESULT:
return int_op(); return int_op();
case REAL_RESULT: case REAL_RESULT:
return (longlong) rint(real_op()); {
bool error;
return double_to_longlong(real_op(), unsigned_flag, &error);
}
case STRING_RESULT: case STRING_RESULT:
{ {
if (is_temporal_type(field_type())) if (is_temporal_type(field_type()))
......
...@@ -411,7 +411,11 @@ class Item_real_func :public Item_func ...@@ -411,7 +411,11 @@ class Item_real_func :public Item_func
String *val_str(String*str); String *val_str(String*str);
my_decimal *val_decimal(my_decimal *decimal_value); my_decimal *val_decimal(my_decimal *decimal_value);
longlong val_int() longlong val_int()
{ DBUG_ASSERT(fixed == 1); return (longlong) rint(val_real()); } {
DBUG_ASSERT(fixed == 1);
bool error;
return double_to_longlong(val_real(), unsigned_flag, &error);
}
enum Item_result result_type () const { return REAL_RESULT; } enum Item_result result_type () const { return REAL_RESULT; }
void fix_length_and_dec() void fix_length_and_dec()
{ decimals= NOT_FIXED_DEC; max_length= float_length(decimals); } { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); }
...@@ -1465,7 +1469,9 @@ class Item_func_udf_float :public Item_udf_func ...@@ -1465,7 +1469,9 @@ class Item_func_udf_float :public Item_udf_func
longlong val_int() longlong val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
return (longlong) rint(Item_func_udf_float::val_real()); bool error;
return double_to_longlong(Item_func_udf_float::val_real(),
unsigned_flag, &error);
} }
my_decimal *val_decimal(my_decimal *dec_buf) my_decimal *val_decimal(my_decimal *dec_buf)
{ {
......
...@@ -1434,7 +1434,8 @@ longlong Item_sum_sum::val_int() ...@@ -1434,7 +1434,8 @@ longlong Item_sum_sum::val_int()
&result); &result);
return result; return result;
} }
return (longlong) rint(val_real()); bool error;
return double_to_longlong(val_real(), unsigned_flag, &error);
} }
...@@ -2648,7 +2649,8 @@ double Item_avg_field::val_real() ...@@ -2648,7 +2649,8 @@ double Item_avg_field::val_real()
longlong Item_avg_field::val_int() longlong Item_avg_field::val_int()
{ {
return (longlong) rint(val_real()); bool error;
return double_to_longlong(val_real(), unsigned_flag, &error);
} }
......
...@@ -699,7 +699,9 @@ class Item_sum_num :public Item_sum ...@@ -699,7 +699,9 @@ class Item_sum_num :public Item_sum
longlong val_int() longlong val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
return (longlong) rint(val_real()); /* Real as default */ // Real as default
bool error;
return double_to_longlong(val_real(), unsigned_flag, &error);
} }
String *val_str(String*str); String *val_str(String*str);
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
...@@ -867,7 +869,11 @@ class Item_sum_avg :public Item_sum_sum ...@@ -867,7 +869,11 @@ class Item_sum_avg :public Item_sum_sum
bool add(); bool add();
double val_real(); double val_real();
// In SPs we might force the "wrong" type with select into a declare variable // In SPs we might force the "wrong" type with select into a declare variable
longlong val_int() { return (longlong) rint(val_real()); } longlong val_int()
{
bool error;
return double_to_longlong(val_real(), unsigned_flag, &error);
}
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
String *val_str(String *str); String *val_str(String *str);
void reset_field(); void reset_field();
...@@ -904,7 +910,10 @@ class Item_variance_field :public Item_result_field ...@@ -904,7 +910,10 @@ class Item_variance_field :public Item_result_field
enum Type type() const {return FIELD_VARIANCE_ITEM; } enum Type type() const {return FIELD_VARIANCE_ITEM; }
double val_real(); double val_real();
longlong val_int() longlong val_int()
{ /* can't be fix_fields()ed */ return (longlong) rint(val_real()); } { /* can't be fix_fields()ed */
bool error;
return double_to_longlong(val_real(), unsigned_flag, &error);
}
String *val_str(String *str) String *val_str(String *str)
{ return val_string_from_real(str); } { return val_string_from_real(str); }
my_decimal *val_decimal(my_decimal *dec_buf) my_decimal *val_decimal(my_decimal *dec_buf)
...@@ -1215,7 +1224,9 @@ class Item_sum_udf_float :public Item_udf_sum ...@@ -1215,7 +1224,9 @@ class Item_sum_udf_float :public Item_udf_sum
longlong val_int() longlong val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
return (longlong) rint(Item_sum_udf_float::val_real()); bool error;
return double_to_longlong(Item_sum_udf_float::val_real(),
unsigned_flag, &error);
} }
double val_real(); double val_real();
String *val_str(String*str); String *val_str(String*str);
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "set_var.h" #include "set_var.h"
#include "sql_locale.h" // MY_LOCALE my_locale_en_US #include "sql_locale.h" // MY_LOCALE my_locale_en_US
#include "strfunc.h" // check_word #include "strfunc.h" // check_word
#include "sql_type_int.h" // Longlong_hybrid
#include "sql_time.h" // make_truncated_value_warning, #include "sql_time.h" // make_truncated_value_warning,
// get_date_from_daynr, // get_date_from_daynr,
// calc_weekday, calc_week, // calc_weekday, calc_week,
...@@ -2741,8 +2742,7 @@ bool Item_func_timediff::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) ...@@ -2741,8 +2742,7 @@ bool Item_func_timediff::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
bool overflow= 0; Longlong_hybrid hour(args[0]->val_int(), args[0]->unsigned_flag);
longlong hour= args[0]->val_int();
longlong minute= args[1]->val_int(); longlong minute= args[1]->val_int();
ulonglong second; ulonglong second;
ulong microsecond; ulong microsecond;
...@@ -2754,21 +2754,11 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) ...@@ -2754,21 +2754,11 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
bzero(ltime, sizeof(*ltime)); bzero(ltime, sizeof(*ltime));
ltime->time_type= MYSQL_TIMESTAMP_TIME; ltime->time_type= MYSQL_TIMESTAMP_TIME;
ltime->neg= hour.neg();
/* Check for integer overflows */ if (hour.abs() <= TIME_MAX_HOUR)
if (hour < 0)
{ {
if (args[0]->unsigned_flag) ltime->hour= (uint) hour.abs();
overflow= 1;
else
ltime->neg= 1;
}
if (-hour > TIME_MAX_HOUR || hour > TIME_MAX_HOUR)
overflow= 1;
if (!overflow)
{
ltime->hour= (uint) ((hour < 0 ? -hour : hour));
ltime->minute= (uint) minute; ltime->minute= (uint) minute;
ltime->second= (uint) second; ltime->second= (uint) second;
ltime->second_part= microsecond; ltime->second_part= microsecond;
...@@ -2779,7 +2769,7 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) ...@@ -2779,7 +2769,7 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date)
ltime->minute= TIME_MAX_MINUTE; ltime->minute= TIME_MAX_MINUTE;
ltime->second= TIME_MAX_SECOND; ltime->second= TIME_MAX_SECOND;
char buf[28]; char buf[28];
char *ptr= longlong10_to_str(hour, buf, args[0]->unsigned_flag ? 10 : -10); char *ptr= longlong10_to_str(hour.value(), buf, hour.is_unsigned() ? 10 : -10);
int len = (int)(ptr - buf) + sprintf(ptr, ":%02u:%02u", (uint)minute, (uint)second); int len = (int)(ptr - buf) + sprintf(ptr, ":%02u:%02u", (uint)minute, (uint)second);
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
buf, len, MYSQL_TIMESTAMP_TIME, buf, len, MYSQL_TIMESTAMP_TIME,
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "sql_list.h" /* Sql_alloc, MEM_ROOT */ #include "sql_list.h" /* Sql_alloc, MEM_ROOT */
#include "m_string.h" /* LEX_STRING */ #include "m_string.h" /* LEX_STRING */
#include "sql_type_int.h" // Longlong_hybrid
#include "sql_string.h" /* String */ #include "sql_string.h" /* String */
#include "mysql_com.h" /* MYSQL_ERRMSG_SIZE */ #include "mysql_com.h" /* MYSQL_ERRMSG_SIZE */
...@@ -542,13 +543,11 @@ class ErrConvString : public ErrConv ...@@ -542,13 +543,11 @@ class ErrConvString : public ErrConv
{ return err_conv(err_buffer, sizeof(err_buffer), str, len, cs); } { return err_conv(err_buffer, sizeof(err_buffer), str, len, cs); }
}; };
class ErrConvInteger : public ErrConv class ErrConvInteger : public ErrConv, public Longlong_hybrid
{ {
longlong m_value;
bool m_unsigned;
public: public:
ErrConvInteger(longlong num_arg, bool unsigned_flag= false) : ErrConvInteger(longlong num_arg, bool unsigned_flag= false) :
ErrConv(), m_value(num_arg), m_unsigned(unsigned_flag) {} ErrConv(), Longlong_hybrid(num_arg, unsigned_flag) {}
const char *ptr() const const char *ptr() const
{ {
return m_unsigned ? ullstr(m_value, err_buffer) : return m_unsigned ? ullstr(m_value, err_buffer) :
......
/* Copyright (c) 2006, 2010, Oracle and/or its affiliates.
Copyright (c) 2011, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#ifndef SQL_TYPE_INT_INCLUDED
#define SQL_TYPE_INT_INCLUDED
// A longlong/ulonglong hybrid. Good to store results of val_int().
class Longlong_hybrid
{
protected:
longlong m_value;
bool m_unsigned;
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 neg() const { return m_value < 0 && !m_unsigned; }
ulonglong abs() const
{
return neg() ? (ulonglong) -m_value : (ulonglong) m_value;
}
};
#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