Commit b7d22a84 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-16872 Add CAST(expr AS FLOAT)

parent e0e80575
......@@ -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
#
......
......@@ -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;
......
......@@ -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;
......
......@@ -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
#
......@@ -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 #
......@@ -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('(');
......
......@@ -1003,25 +1003,66 @@ class Item_decimal_typecast :public Item_func
};
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); }
};
......
......@@ -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
......
......@@ -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 @@ class Type_handler
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 @@ class Type_handler_row: public Type_handler
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 @@ class Type_handler_float: public Type_handler_real_result
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 @@ class Type_handler_geometry: public Type_handler_string_result
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;
......
......@@ -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); }
;
......
......@@ -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); }
;
......
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