Skip to content

Commit b7d22a8

Browse files
committed
MDEV-16872 Add CAST(expr AS FLOAT)
1 parent e0e8057 commit b7d22a8

File tree

12 files changed

+221
-16
lines changed

12 files changed

+221
-16
lines changed

mysql-test/main/cast.result

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,12 +271,12 @@ select cast(1000 as double(5,2));
271271
cast(1000 as double(5,2))
272272
999.99
273273
Warnings:
274-
Warning 1264 Out of range value for column 'cast(1000 as double(5,2))' at row 1
274+
Note 1264 Out of range value for column 'cast(1000 as double(5,2))' at row 1
275275
select cast(-1000 as double(5,2));
276276
cast(-1000 as double(5,2))
277277
-999.99
278278
Warnings:
279-
Warning 1264 Out of range value for column 'cast(-1000 as double(5,2))' at row 1
279+
Note 1264 Out of range value for column 'cast(-1000 as double(5,2))' at row 1
280280
select cast(010203101112.121314 as datetime);
281281
cast(010203101112.121314 as datetime)
282282
2001-02-03 10:11:12

mysql-test/main/dyncol.result

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -501,12 +501,12 @@ select column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2));
501501
column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2))
502502
999.99
503503
Warnings:
504-
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
504+
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
505505
select column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2));
506506
column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2))
507507
9.99
508508
Warnings:
509-
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
509+
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
510510
#
511511
# column get decimal
512512
#

mysql-test/main/gis.result

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4038,6 +4038,8 @@ SELECT CAST(POINT(1,1) AS SIGNED) FROM t1;
40384038
ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_signed'
40394039
SELECT CAST(POINT(1,1) AS UNSIGNED) FROM t1;
40404040
ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_unsigned'
4041+
SELECT CAST(POINT(1,1) AS FLOAT) FROM t1;
4042+
ERROR HY000: Illegal parameter data type geometry for operation 'float_typecast'
40414043
SELECT CAST(POINT(1,1) AS DOUBLE) FROM t1;
40424044
ERROR HY000: Illegal parameter data type geometry for operation 'double_typecast'
40434045
SELECT CAST(POINT(1,1) AS DECIMAL(10,1)) FROM t1;
@@ -4054,6 +4056,8 @@ SELECT CAST(a AS SIGNED) FROM t1;
40544056
ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_signed'
40554057
SELECT CAST(a AS UNSIGNED) FROM t1;
40564058
ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_unsigned'
4059+
SELECT CAST(a AS FLOAT) FROM t1;
4060+
ERROR HY000: Illegal parameter data type geometry for operation 'float_typecast'
40574061
SELECT CAST(a AS DOUBLE) FROM t1;
40584062
ERROR HY000: Illegal parameter data type geometry for operation 'double_typecast'
40594063
SELECT CAST(a AS DECIMAL(10,1)) FROM t1;
@@ -4070,6 +4074,8 @@ SELECT CAST(COALESCE(a) AS SIGNED) FROM t1;
40704074
ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_signed'
40714075
SELECT CAST(COALESCE(a) AS UNSIGNED) FROM t1;
40724076
ERROR HY000: Illegal parameter data type geometry for operation 'cast_as_unsigned'
4077+
SELECT CAST(COALESCE(a) AS FLOAT) FROM t1;
4078+
ERROR HY000: Illegal parameter data type geometry for operation 'float_typecast'
40734079
SELECT CAST(COALESCE(a) AS DOUBLE) FROM t1;
40744080
ERROR HY000: Illegal parameter data type geometry for operation 'double_typecast'
40754081
SELECT CAST(COALESCE(a) AS DECIMAL(10,1)) FROM t1;

mysql-test/main/gis.test

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2109,6 +2109,8 @@ SELECT CAST(POINT(1,1) AS SIGNED) FROM t1;
21092109
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
21102110
SELECT CAST(POINT(1,1) AS UNSIGNED) FROM t1;
21112111
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
2112+
SELECT CAST(POINT(1,1) AS FLOAT) FROM t1;
2113+
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
21122114
SELECT CAST(POINT(1,1) AS DOUBLE) FROM t1;
21132115
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
21142116
SELECT CAST(POINT(1,1) AS DECIMAL(10,1)) FROM t1;
@@ -2126,6 +2128,8 @@ SELECT CAST(a AS SIGNED) FROM t1;
21262128
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
21272129
SELECT CAST(a AS UNSIGNED) FROM t1;
21282130
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
2131+
SELECT CAST(a AS FLOAT) FROM t1;
2132+
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
21292133
SELECT CAST(a AS DOUBLE) FROM t1;
21302134
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
21312135
SELECT CAST(a AS DECIMAL(10,1)) FROM t1;
@@ -2143,6 +2147,8 @@ SELECT CAST(COALESCE(a) AS SIGNED) FROM t1;
21432147
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
21442148
SELECT CAST(COALESCE(a) AS UNSIGNED) FROM t1;
21452149
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
2150+
SELECT CAST(COALESCE(a) AS FLOAT) FROM t1;
2151+
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
21462152
SELECT CAST(COALESCE(a) AS DOUBLE) FROM t1;
21472153
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
21482154
SELECT CAST(COALESCE(a) AS DECIMAL(10,1)) FROM t1;

mysql-test/main/type_float.result

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,5 +875,73 @@ CONCAT(a) CONCAT(COALESCE(a)) CONCAT(LEAST(a,a)) CONCAT(MAX(a)) c
875875
0.671437 0.671437 0.671437 0.671437 0.671437
876876
DROP TABLE t1, t2;
877877
#
878+
# MDEV-16872 Add CAST(expr AS FLOAT)
879+
#
880+
SELECT CAST(0.671437 AS FLOAT), CONCAT(CAST(0.671437 AS FLOAT));
881+
CAST(0.671437 AS FLOAT) CONCAT(CAST(0.671437 AS FLOAT))
882+
0.671437 0.671437
883+
SELECT CAST(1e40 AS FLOAT), CONCAT(CAST(1e40 AS FLOAT));
884+
CAST(1e40 AS FLOAT) CONCAT(CAST(1e40 AS FLOAT))
885+
3.40282e38 3.40282e38
886+
Warnings:
887+
Note 1264 Out of range value for column 'CAST(1e40 AS FLOAT)' at row 1
888+
Note 1264 Out of range value for column 'CAST(1e40 AS FLOAT)' at row 1
889+
SELECT CAST(-1e40 AS FLOAT), CONCAT(CAST(-1e40 AS FLOAT));
890+
CAST(-1e40 AS FLOAT) CONCAT(CAST(-1e40 AS FLOAT))
891+
-3.40282e38 -3.40282e38
892+
Warnings:
893+
Note 1264 Out of range value for column 'CAST(-1e40 AS FLOAT)' at row 1
894+
Note 1264 Out of range value for column 'CAST(-1e40 AS FLOAT)' at row 1
895+
SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES';
896+
CREATE TABLE t1 (a FLOAT);
897+
INSERT INTO t1 VALUES (CAST(1e40 AS FLOAT));
898+
Warnings:
899+
Note 1264 Out of range value for column 'CAST(1e40 AS FLOAT)' at row 1
900+
SELECT * FROM t1;
901+
a
902+
3.40282e38
903+
DROP TABLE t1;
904+
SET sql_mode=DEFAULT;
905+
EXPLAIN EXTENDED SELECT CAST(0.671437 AS FLOAT);
906+
id select_type table type possible_keys key key_len ref rows filtered Extra
907+
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
908+
Warnings:
909+
Note 1003 select cast(0.671437 as float) AS `CAST(0.671437 AS FLOAT)`
910+
CREATE TABLE t1 AS SELECT CAST(0.671437 AS FLOAT) AS c1;
911+
SHOW CREATE TABLE t1;
912+
Table Create Table
913+
t1 CREATE TABLE `t1` (
914+
`c1` float DEFAULT NULL
915+
) ENGINE=MyISAM DEFAULT CHARSET=latin1
916+
SELECT * FROM t1;
917+
c1
918+
0.671437
919+
DROP TABLE t1;
920+
CREATE TABLE t1 (a FLOAT);
921+
CREATE TABLE t2 AS SELECT CONCAT(a) AS c1, CONCAT(CAST(a AS FLOAT)) AS c2 FROM t1;
922+
SHOW CREATE TABLE t2;
923+
Table Create Table
924+
t2 CREATE TABLE `t2` (
925+
`c1` varchar(12) DEFAULT NULL,
926+
`c2` varchar(12) DEFAULT NULL
927+
) ENGINE=MyISAM DEFAULT CHARSET=latin1
928+
DROP TABLE t1, t2;
929+
CREATE TABLE t1 (a FLOAT DEFAULT CAST(0.671437 AS FLOAT));
930+
SHOW CREATE TABLE t1;
931+
Table Create Table
932+
t1 CREATE TABLE `t1` (
933+
`a` float DEFAULT (cast(0.671437 as float))
934+
) ENGINE=MyISAM DEFAULT CHARSET=latin1
935+
DROP TABLE t1;
936+
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY, a FLOAT);
937+
INSERT INTO t1 VALUES (1, 0.671437),(2, 0.671437);
938+
DELETE FROM t1 WHERE a=0.671437;
939+
SELECT * FROM t1;
940+
id a
941+
1 0.671437
942+
2 0.671437
943+
DELETE FROM t1 WHERE a=CAST(0.671437 AS FLOAT);
944+
DROP TABLE t1;
945+
#
878946
# End of 10.3 tests
879947
#

mysql-test/main/type_float.test

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,45 @@ SELECT * FROM t2;
615615
DROP TABLE t1, t2;
616616

617617

618+
--echo #
619+
--echo # MDEV-16872 Add CAST(expr AS FLOAT)
620+
--echo #
621+
622+
SELECT CAST(0.671437 AS FLOAT), CONCAT(CAST(0.671437 AS FLOAT));
623+
SELECT CAST(1e40 AS FLOAT), CONCAT(CAST(1e40 AS FLOAT));
624+
SELECT CAST(-1e40 AS FLOAT), CONCAT(CAST(-1e40 AS FLOAT));
625+
626+
SET sql_mode='STRICT_ALL_TABLES,STRICT_TRANS_TABLES';
627+
CREATE TABLE t1 (a FLOAT);
628+
INSERT INTO t1 VALUES (CAST(1e40 AS FLOAT));
629+
SELECT * FROM t1;
630+
DROP TABLE t1;
631+
SET sql_mode=DEFAULT;
632+
633+
EXPLAIN EXTENDED SELECT CAST(0.671437 AS FLOAT);
634+
635+
CREATE TABLE t1 AS SELECT CAST(0.671437 AS FLOAT) AS c1;
636+
SHOW CREATE TABLE t1;
637+
SELECT * FROM t1;
638+
DROP TABLE t1;
639+
640+
CREATE TABLE t1 (a FLOAT);
641+
CREATE TABLE t2 AS SELECT CONCAT(a) AS c1, CONCAT(CAST(a AS FLOAT)) AS c2 FROM t1;
642+
SHOW CREATE TABLE t2;
643+
DROP TABLE t1, t2;
644+
645+
CREATE TABLE t1 (a FLOAT DEFAULT CAST(0.671437 AS FLOAT));
646+
SHOW CREATE TABLE t1;
647+
DROP TABLE t1;
648+
649+
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY, a FLOAT);
650+
INSERT INTO t1 VALUES (1, 0.671437),(2, 0.671437);
651+
DELETE FROM t1 WHERE a=0.671437;
652+
SELECT * FROM t1;
653+
DELETE FROM t1 WHERE a=CAST(0.671437 AS FLOAT);
654+
DROP TABLE t1;
655+
656+
618657
--echo #
619658
--echo # End of 10.3 tests
620659
--echo #

sql/item_func.cc

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,19 +1133,26 @@ void Item_decimal_typecast::print(String *str, enum_query_type query_type)
11331133
}
11341134

11351135

1136-
double Item_double_typecast::val_real()
1136+
double Item_real_typecast::val_real_with_truncate(double max_value)
11371137
{
11381138
int error;
11391139
double tmp= args[0]->val_real();
11401140
if ((null_value= args[0]->null_value))
11411141
return 0.0;
11421142

1143-
if (unlikely((error= truncate_double(&tmp, max_length, decimals, 0,
1144-
DBL_MAX))))
1143+
if (unlikely((error= truncate_double(&tmp, max_length, decimals,
1144+
false/*unsigned_flag*/, max_value))))
11451145
{
1146+
/*
1147+
We don't want automatic escalation from a warning to an error
1148+
in this scenario:
1149+
INSERT INTO t1 (float_field) VALUES (CAST(1e100 AS FLOAT));
1150+
The above statement should work even in the strict mode.
1151+
So let's use a note rather than a warning.
1152+
*/
11461153
THD *thd= current_thd;
11471154
push_warning_printf(thd,
1148-
Sql_condition::WARN_LEVEL_WARN,
1155+
Sql_condition::WARN_LEVEL_NOTE,
11491156
ER_WARN_DATA_OUT_OF_RANGE,
11501157
ER_THD(thd, ER_WARN_DATA_OUT_OF_RANGE),
11511158
name.str, (ulong) 1);
@@ -1159,14 +1166,15 @@ double Item_double_typecast::val_real()
11591166
}
11601167

11611168

1162-
void Item_double_typecast::print(String *str, enum_query_type query_type)
1169+
void Item_real_typecast::print(String *str, enum_query_type query_type)
11631170
{
11641171
char len_buf[20*3 + 1];
11651172
char *end;
11661173

11671174
str->append(STRING_WITH_LEN("cast("));
11681175
args[0]->print(str, query_type);
1169-
str->append(STRING_WITH_LEN(" as double"));
1176+
str->append(STRING_WITH_LEN(" as "));
1177+
str->append(type_handler()->name().ptr());
11701178
if (decimals != NOT_FIXED_DEC)
11711179
{
11721180
str->append('(');

sql/item_func.h

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,25 +1003,66 @@ class Item_decimal_typecast :public Item_func
10031003
};
10041004

10051005

1006-
class Item_double_typecast :public Item_real_func
1006+
class Item_real_typecast: public Item_real_func
10071007
{
1008+
protected:
1009+
double val_real_with_truncate(double max_value);
10081010
public:
1009-
Item_double_typecast(THD *thd, Item *a, uint len, uint dec):
1010-
Item_real_func(thd, a)
1011+
Item_real_typecast(THD *thd, Item *a, uint len, uint dec)
1012+
:Item_real_func(thd, a)
10111013
{
10121014
decimals= (uint8) dec;
10131015
max_length= (uint32) len;
10141016
}
1015-
double val_real();
1017+
bool need_parentheses_in_default() { return true; }
1018+
void print(String *str, enum_query_type query_type);
10161019
void fix_length_and_dec_generic() { maybe_null= 1; }
1020+
};
1021+
1022+
1023+
class Item_float_typecast :public Item_real_typecast
1024+
{
1025+
public:
1026+
Item_float_typecast(THD *thd, Item *a)
1027+
:Item_real_typecast(thd, a, MAX_FLOAT_STR_LENGTH, NOT_FIXED_DEC)
1028+
{ }
1029+
const Type_handler *type_handler() const { return &type_handler_float; }
1030+
bool fix_length_and_dec()
1031+
{
1032+
return
1033+
args[0]->type_handler()->Item_float_typecast_fix_length_and_dec(this);
1034+
}
1035+
const char *func_name() const { return "float_typecast"; }
1036+
double val_real()
1037+
{
1038+
return (double) (float) val_real_with_truncate(FLT_MAX);
1039+
}
1040+
String *val_str(String*str)
1041+
{
1042+
Float nr(Item_float_typecast::val_real());
1043+
if (null_value)
1044+
return 0;
1045+
nr.to_string(str, decimals);
1046+
return str;
1047+
}
1048+
Item *get_copy(THD *thd)
1049+
{ return get_item_copy<Item_float_typecast>(thd, this); }
1050+
};
1051+
1052+
1053+
class Item_double_typecast :public Item_real_typecast
1054+
{
1055+
public:
1056+
Item_double_typecast(THD *thd, Item *a, uint len, uint dec):
1057+
Item_real_typecast(thd, a, len, dec)
1058+
{ }
10171059
bool fix_length_and_dec()
10181060
{
10191061
return
10201062
args[0]->type_handler()->Item_double_typecast_fix_length_and_dec(this);
10211063
}
10221064
const char *func_name() const { return "double_typecast"; }
1023-
virtual void print(String *str, enum_query_type query_type);
1024-
bool need_parentheses_in_default() { return true; }
1065+
double val_real() { return val_real_with_truncate(DBL_MAX); }
10251066
Item *get_copy(THD *thd)
10261067
{ return get_item_copy<Item_double_typecast>(thd, this); }
10271068
};

sql/sql_type.cc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4642,6 +4642,14 @@ bool Type_handler::
46424642
}
46434643

46444644

4645+
bool Type_handler::
4646+
Item_float_typecast_fix_length_and_dec(Item_float_typecast *item) const
4647+
{
4648+
item->fix_length_and_dec_generic();
4649+
return false;
4650+
}
4651+
4652+
46454653
bool Type_handler::
46464654
Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const
46474655
{
@@ -4731,6 +4739,13 @@ bool Type_handler_geometry::
47314739
}
47324740

47334741

4742+
bool Type_handler_geometry::
4743+
Item_float_typecast_fix_length_and_dec(Item_float_typecast *item) const
4744+
{
4745+
return Item_func_or_sum_illegal_param(item);
4746+
}
4747+
4748+
47344749
bool Type_handler_geometry::
47354750
Item_decimal_typecast_fix_length_and_dec(Item_decimal_typecast *item) const
47364751
{
@@ -5760,6 +5775,15 @@ Item *Type_handler_double::
57605775
}
57615776

57625777

5778+
Item *Type_handler_float::
5779+
create_typecast_item(THD *thd, Item *item,
5780+
const Type_cast_attributes &attr) const
5781+
{
5782+
DBUG_ASSERT(!attr.length_specified());
5783+
return new (thd->mem_root) Item_float_typecast(thd, item);
5784+
}
5785+
5786+
57635787
Item *Type_handler_long_blob::
57645788
create_typecast_item(THD *thd, Item *item,
57655789
const Type_cast_attributes &attr) const

0 commit comments

Comments
 (0)