1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

MDEV-16872 Add CAST(expr AS FLOAT)

This commit is contained in:
Alexander Barkov
2019-05-16 10:16:09 +04:00
parent e0e805759f
commit b7d22a843e
12 changed files with 221 additions and 16 deletions

View File

@ -271,12 +271,12 @@ select cast(1000 as double(5,2));
cast(1000 as double(5,2))
999.99
Warnings:
Warning 1264 Out of range value for column 'cast(1000 as double(5,2))' at row 1
Note 1264 Out of range value for column 'cast(1000 as double(5,2))' at row 1
select cast(-1000 as double(5,2));
cast(-1000 as double(5,2))
-999.99
Warnings:
Warning 1264 Out of range value for column 'cast(-1000 as double(5,2))' at row 1
Note 1264 Out of range value for column 'cast(-1000 as double(5,2))' at row 1
select cast(010203101112.121314 as datetime);
cast(010203101112.121314 as datetime)
2001-02-03 10:11:12

View File

@ -501,12 +501,12 @@ select column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2));
column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2))
999.99
Warnings:
Warning 1264 Out of range value for column 'column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2))' at row 1
Note 1264 Out of range value for column 'column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2))' at row 1
select column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2));
column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2))
9.99
Warnings:
Warning 1264 Out of range value for column 'column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2))' at row 1
Note 1264 Out of range value for column 'column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2))' at row 1
#
# column get decimal
#

View File

@ -4038,6 +4038,8 @@ SELECT CAST(POINT(1,1) AS SIGNED) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_signed'
SELECT CAST(POINT(1,1) AS UNSIGNED) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_unsigned'
SELECT CAST(POINT(1,1) AS FLOAT) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'float_typecast'
SELECT CAST(POINT(1,1) AS DOUBLE) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'double_typecast'
SELECT CAST(POINT(1,1) AS DECIMAL(10,1)) FROM t1;
@ -4054,6 +4056,8 @@ SELECT CAST(a AS SIGNED) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_signed'
SELECT CAST(a AS UNSIGNED) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_unsigned'
SELECT CAST(a AS FLOAT) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'float_typecast'
SELECT CAST(a AS DOUBLE) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'double_typecast'
SELECT CAST(a AS DECIMAL(10,1)) FROM t1;
@ -4070,6 +4074,8 @@ SELECT CAST(COALESCE(a) AS SIGNED) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_signed'
SELECT CAST(COALESCE(a) AS UNSIGNED) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_unsigned'
SELECT CAST(COALESCE(a) AS FLOAT) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'float_typecast'
SELECT CAST(COALESCE(a) AS DOUBLE) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'double_typecast'
SELECT CAST(COALESCE(a) AS DECIMAL(10,1)) FROM t1;

View File

@ -2109,6 +2109,8 @@ SELECT CAST(POINT(1,1) AS SIGNED) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT CAST(POINT(1,1) AS UNSIGNED) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT CAST(POINT(1,1) AS FLOAT) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT CAST(POINT(1,1) AS DOUBLE) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT CAST(POINT(1,1) AS DECIMAL(10,1)) FROM t1;
@ -2126,6 +2128,8 @@ SELECT CAST(a AS SIGNED) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT CAST(a AS UNSIGNED) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT CAST(a AS FLOAT) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT CAST(a AS DOUBLE) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT CAST(a AS DECIMAL(10,1)) FROM t1;
@ -2143,6 +2147,8 @@ SELECT CAST(COALESCE(a) AS SIGNED) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT CAST(COALESCE(a) AS UNSIGNED) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT CAST(COALESCE(a) AS FLOAT) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT CAST(COALESCE(a) AS DOUBLE) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT CAST(COALESCE(a) AS DECIMAL(10,1)) FROM t1;

View File

@ -875,5 +875,73 @@ CONCAT(a) CONCAT(COALESCE(a)) CONCAT(LEAST(a,a)) CONCAT(MAX(a)) c
0.671437 0.671437 0.671437 0.671437 0.671437
DROP TABLE t1, t2;
#
# MDEV-16872 Add CAST(expr AS FLOAT)
#
SELECT CAST(0.671437 AS FLOAT), CONCAT(CAST(0.671437 AS FLOAT));
CAST(0.671437 AS FLOAT) CONCAT(CAST(0.671437 AS FLOAT))
0.671437 0.671437
SELECT CAST(1e40 AS FLOAT), CONCAT(CAST(1e40 AS FLOAT));
CAST(1e40 AS FLOAT) CONCAT(CAST(1e40 AS FLOAT))
3.40282e38 3.40282e38
Warnings:
Note 1264 Out of range value for column 'CAST(1e40 AS FLOAT)' at row 1
Note 1264 Out of range value for column 'CAST(1e40 AS FLOAT)' at row 1
SELECT CAST(-1e40 AS FLOAT), CONCAT(CAST(-1e40 AS FLOAT));
CAST(-1e40 AS FLOAT) CONCAT(CAST(-1e40 AS FLOAT))
-3.40282e38 -3.40282e38
Warnings:
Note 1264 Out of range value for column 'CAST(-1e40 AS FLOAT)' at row 1
Note 1264 Out of range value for column 'CAST(-1e40 AS FLOAT)' at row 1
SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES';
CREATE TABLE t1 (a FLOAT);
INSERT INTO t1 VALUES (CAST(1e40 AS FLOAT));
Warnings:
Note 1264 Out of range value for column 'CAST(1e40 AS FLOAT)' at row 1
SELECT * FROM t1;
a
3.40282e38
DROP TABLE t1;
SET sql_mode=DEFAULT;
EXPLAIN EXTENDED SELECT CAST(0.671437 AS FLOAT);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select cast(0.671437 as float) AS `CAST(0.671437 AS FLOAT)`
CREATE TABLE t1 AS SELECT CAST(0.671437 AS FLOAT) AS c1;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` float DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t1;
c1
0.671437
DROP TABLE t1;
CREATE TABLE t1 (a FLOAT);
CREATE TABLE t2 AS SELECT CONCAT(a) AS c1, CONCAT(CAST(a AS FLOAT)) AS c2 FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c1` varchar(12) DEFAULT NULL,
`c2` varchar(12) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1, t2;
CREATE TABLE t1 (a FLOAT DEFAULT CAST(0.671437 AS FLOAT));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` float DEFAULT (cast(0.671437 as float))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY, a FLOAT);
INSERT INTO t1 VALUES (1, 0.671437),(2, 0.671437);
DELETE FROM t1 WHERE a=0.671437;
SELECT * FROM t1;
id a
1 0.671437
2 0.671437
DELETE FROM t1 WHERE a=CAST(0.671437 AS FLOAT);
DROP TABLE t1;
#
# End of 10.3 tests
#

View File

@ -615,6 +615,45 @@ SELECT * FROM t2;
DROP TABLE t1, t2;
--echo #
--echo # MDEV-16872 Add CAST(expr AS FLOAT)
--echo #
SELECT CAST(0.671437 AS FLOAT), CONCAT(CAST(0.671437 AS FLOAT));
SELECT CAST(1e40 AS FLOAT), CONCAT(CAST(1e40 AS FLOAT));
SELECT CAST(-1e40 AS FLOAT), CONCAT(CAST(-1e40 AS FLOAT));
SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES';
CREATE TABLE t1 (a FLOAT);
INSERT INTO t1 VALUES (CAST(1e40 AS FLOAT));
SELECT * FROM t1;
DROP TABLE t1;
SET sql_mode=DEFAULT;
EXPLAIN EXTENDED SELECT CAST(0.671437 AS FLOAT);
CREATE TABLE t1 AS SELECT CAST(0.671437 AS FLOAT) AS c1;
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a FLOAT);
CREATE TABLE t2 AS SELECT CONCAT(a) AS c1, CONCAT(CAST(a AS FLOAT)) AS c2 FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t1, t2;
CREATE TABLE t1 (a FLOAT DEFAULT CAST(0.671437 AS FLOAT));
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY, a FLOAT);
INSERT INTO t1 VALUES (1, 0.671437),(2, 0.671437);
DELETE FROM t1 WHERE a=0.671437;
SELECT * FROM t1;
DELETE FROM t1 WHERE a=CAST(0.671437 AS FLOAT);
DROP TABLE t1;
--echo #
--echo # End of 10.3 tests
--echo #

View File

@ -1133,19 +1133,26 @@ void Item_decimal_typecast::print(String *str, enum_query_type query_type)
}
double Item_double_typecast::val_real()
double Item_real_typecast::val_real_with_truncate(double max_value)
{
int error;
double tmp= args[0]->val_real();
if ((null_value= args[0]->null_value))
return 0.0;
if (unlikely((error= truncate_double(&tmp, max_length, decimals, 0,
DBL_MAX))))
if (unlikely((error= truncate_double(&tmp, max_length, decimals,
false/*unsigned_flag*/, max_value))))
{
/*
We don't want automatic escalation from a warning to an error
in this scenario:
INSERT INTO t1 (float_field) VALUES (CAST(1e100 AS FLOAT));
The above statement should work even in the strict mode.
So let's use a note rather than a warning.
*/
THD *thd= current_thd;
push_warning_printf(thd,
Sql_condition::WARN_LEVEL_WARN,
Sql_condition::WARN_LEVEL_NOTE,
ER_WARN_DATA_OUT_OF_RANGE,
ER_THD(thd, ER_WARN_DATA_OUT_OF_RANGE),
name.str, (ulong) 1);
@ -1159,14 +1166,15 @@ double Item_double_typecast::val_real()
}
void Item_double_typecast::print(String *str, enum_query_type query_type)
void Item_real_typecast::print(String *str, enum_query_type query_type)
{
char len_buf[20*3 + 1];
char *end;
str->append(STRING_WITH_LEN("cast("));
args[0]->print(str, query_type);
str->append(STRING_WITH_LEN(" as double"));
str->append(STRING_WITH_LEN(" as "));
str->append(type_handler()->name().ptr());
if (decimals != NOT_FIXED_DEC)
{
str->append('(');

View File

@ -1003,25 +1003,66 @@ public:
};
class Item_double_typecast :public Item_real_func
class Item_real_typecast: public Item_real_func
{
protected:
double val_real_with_truncate(double max_value);
public:
Item_double_typecast(THD *thd, Item *a, uint len, uint dec):
Item_real_func(thd, a)
Item_real_typecast(THD *thd, Item *a, uint len, uint dec)
:Item_real_func(thd, a)
{
decimals= (uint8) dec;
max_length= (uint32) len;
}
double val_real();
bool need_parentheses_in_default() { return true; }
void print(String *str, enum_query_type query_type);
void fix_length_and_dec_generic() { maybe_null= 1; }
};
class Item_float_typecast :public Item_real_typecast
{
public:
Item_float_typecast(THD *thd, Item *a)
:Item_real_typecast(thd, a, MAX_FLOAT_STR_LENGTH, NOT_FIXED_DEC)
{ }
const Type_handler *type_handler() const { return &type_handler_float; }
bool fix_length_and_dec()
{
return
args[0]->type_handler()->Item_float_typecast_fix_length_and_dec(this);
}
const char *func_name() const { return "float_typecast"; }
double val_real()
{
return (double) (float) val_real_with_truncate(FLT_MAX);
}
String *val_str(String*str)
{
Float nr(Item_float_typecast::val_real());
if (null_value)
return 0;
nr.to_string(str, decimals);
return str;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_float_typecast>(thd, this); }
};
class Item_double_typecast :public Item_real_typecast
{
public:
Item_double_typecast(THD *thd, Item *a, uint len, uint dec):
Item_real_typecast(thd, a, len, dec)
{ }
bool fix_length_and_dec()
{
return
args[0]->type_handler()->Item_double_typecast_fix_length_and_dec(this);
}
const char *func_name() const { return "double_typecast"; }
virtual void print(String *str, enum_query_type query_type);
bool need_parentheses_in_default() { return true; }
double val_real() { return val_real_with_truncate(DBL_MAX); }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_double_typecast>(thd, this); }
};

View File

@ -4642,6 +4642,14 @@ bool Type_handler::
}
bool Type_handler::
Item_float_typecast_fix_length_and_dec(Item_float_typecast *item) const
{
item->fix_length_and_dec_generic();
return false;
}
bool Type_handler::
Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const
{
@ -4731,6 +4739,13 @@ bool Type_handler_geometry::
}
bool Type_handler_geometry::
Item_float_typecast_fix_length_and_dec(Item_float_typecast *item) const
{
return Item_func_or_sum_illegal_param(item);
}
bool Type_handler_geometry::
Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const
{
@ -5760,6 +5775,15 @@ Item *Type_handler_double::
}
Item *Type_handler_float::
create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const
{
DBUG_ASSERT(!attr.length_specified());
return new (thd->mem_root) Item_float_typecast(thd, item);
}
Item *Type_handler_long_blob::
create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const

View File

@ -51,6 +51,7 @@ class Item_func_neg;
class Item_func_signed;
class Item_func_unsigned;
class Item_double_typecast;
class Item_float_typecast;
class Item_decimal_typecast;
class Item_char_typecast;
class Item_time_typecast;
@ -1391,6 +1392,8 @@ public:
virtual bool
Item_double_typecast_fix_length_and_dec(Item_double_typecast *item) const;
virtual bool
Item_float_typecast_fix_length_and_dec(Item_float_typecast *item) const;
virtual bool
Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const;
virtual bool
Item_char_typecast_fix_length_and_dec(Item_char_typecast *item) const;
@ -1695,6 +1698,11 @@ public:
DBUG_ASSERT(0);
return true;
}
bool Item_float_typecast_fix_length_and_dec(Item_float_typecast *) const
{
DBUG_ASSERT(0);
return true;
}
bool Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *) const
{
DBUG_ASSERT(0);
@ -2590,6 +2598,8 @@ public:
bool type_can_have_auto_increment_attribute() const { return true; }
uint32 max_display_length(const Item *item) const { return 25; }
uint32 calc_pack_length(uint32 length) const { return sizeof(float); }
Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const;
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{
return Item_send_float(item, protocol, buf);
@ -3366,6 +3376,7 @@ public:
bool Item_func_signed_fix_length_and_dec(Item_func_signed *) const;
bool Item_func_unsigned_fix_length_and_dec(Item_func_unsigned *) const;
bool Item_double_typecast_fix_length_and_dec(Item_double_typecast *) const;
bool Item_float_typecast_fix_length_and_dec(Item_float_typecast *) const;
bool Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *) const;
bool Item_char_typecast_fix_length_and_dec(Item_char_typecast *) const;
bool Item_time_typecast_fix_length_and_dec(Item_time_typecast *) const;

View File

@ -11728,6 +11728,7 @@ cast_type_numeric:
| UNSIGNED { $$.set(&type_handler_ulonglong); }
| UNSIGNED INT_SYM { $$.set(&type_handler_ulonglong); }
| DECIMAL_SYM float_options { $$.set(&type_handler_newdecimal, $2); }
| FLOAT_SYM { $$.set(&type_handler_float); }
| DOUBLE_SYM opt_precision { $$.set(&type_handler_double, $2); }
;

View File

@ -11674,6 +11674,7 @@ cast_type_numeric:
| UNSIGNED { $$.set(&type_handler_ulonglong); }
| UNSIGNED INT_SYM { $$.set(&type_handler_ulonglong); }
| DECIMAL_SYM float_options { $$.set(&type_handler_newdecimal, $2); }
| FLOAT_SYM { $$.set(&type_handler_float); }
| DOUBLE_SYM opt_precision { $$.set(&type_handler_double, $2); }
;