Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
8aa044e6
Commit
8aa044e6
authored
Dec 29, 2016
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-11478 Result data type aggregation for pluggable data types
parent
f6138883
Changes
14
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
1138 additions
and
266 deletions
+1138
-266
mysql-test/r/func_str.result
mysql-test/r/func_str.result
+1
-7
mysql-test/r/gis.result
mysql-test/r/gis.result
+612
-0
mysql-test/t/func_str.test
mysql-test/t/func_str.test
+2
-0
mysql-test/t/gis.test
mysql-test/t/gis.test
+79
-0
sql/field.cc
sql/field.cc
+83
-139
sql/field.h
sql/field.h
+0
-1
sql/item.cc
sql/item.cc
+27
-26
sql/item_cmpfunc.cc
sql/item_cmpfunc.cc
+3
-83
sql/item_cmpfunc.h
sql/item_cmpfunc.h
+4
-4
sql/item_func.cc
sql/item_func.cc
+5
-3
sql/item_func.h
sql/item_func.h
+0
-2
sql/share/errmsg-utf8.txt
sql/share/errmsg-utf8.txt
+2
-0
sql/sql_type.cc
sql/sql_type.cc
+182
-1
sql/sql_type.h
sql/sql_type.h
+138
-0
No files found.
mysql-test/r/func_str.result
View file @
8aa044e6
...
...
@@ -2938,13 +2938,7 @@ sha1('P'),
)
)
) AS r;
r
0
Warnings:
Warning 1292 Truncated incorrect INTEGER value: '511993d3c99719e38a6779073019dacd7178ddb9'
Warning 1292 Truncated incorrect DECIMAL value: '[.DC2.]'
Warning 1292 Truncated incorrect INTEGER value: '511993d3c99719e38a6779073019dacd7178ddb9'
Warning 1292 Truncated incorrect DOUBLE value: '0.000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111'
ERROR HY000: Illegal parameter data types geometry and decimal for operation 'coalesce'
connection conn1;
SET @@global.max_allowed_packet:= @tmp_max;
disconnect newconn;
...
...
mysql-test/r/gis.result
View file @
8aa044e6
This diff is collapsed.
Click to expand it.
mysql-test/t/func_str.test
View file @
8aa044e6
...
...
@@ -1554,6 +1554,8 @@ format(rpad('111111111.1',
# But in mysqltest --disable_prepare_warnings affects SELECT queries only
# and can't suppress prepare time warnings for DO.
#
--
error
ER_CANT_AGGREGATE_2TYPES
SELECT
round
(
concat
(
(
...
...
mysql-test/t/gis.test
View file @
8aa044e6
...
...
@@ -1716,6 +1716,85 @@ INSERT INTO t1 (a,b) VALUES (Point(1,1),Point(1,1));
SELECT
c
FROM
t1
;
DROP
TABLE
t1
;
--
echo
#
--
echo
#
--
echo
#
DELIMITER
$$
;
CREATE
PROCEDURE
p2
(
query
TEXT
)
BEGIN
DECLARE
errcount
INT
DEFAULT
0
;
DECLARE
CONTINUE
HANDLER
FOR
SQLEXCEPTION
BEGIN
SET
errcount
=
errcount
+
1
;
#SHOW WARNINGS;
GET
DIAGNOSTICS
CONDITION
1
@
p
=
MESSAGE_TEXT
;
SELECT
@
p
AS
`ERROR: `
;
END
;
SELECT
query
AS
``
;
EXECUTE
IMMEDIATE
query
;
IF
errcount
=
0
THEN
SHOW
CREATE
TABLE
t2
;
DROP
TABLE
t2
;
END
IF
;
END
;
$$
CREATE
PROCEDURE
p1
(
query
TEXT
)
BEGIN
SELECT
query
AS
`-------------------------------------`
;
EXECUTE
IMMEDIATE
query
;
CALL
p2
(
'CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1'
);
CALL
p2
(
'CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1'
);
CALL
p2
(
'CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1'
);
CALL
p2
(
'CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1'
);
CALL
p2
(
'CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1'
);
DROP
TABLE
t1
;
END
;
$$
DELIMITER
;
$$
--
disable_query_log
CALL
p1
(
'CREATE TABLE t1 (a CHAR(10), b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a VARCHAR(10), b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a TINYTEXT, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a TEXT, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a MEDIUMTEXT, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a LONGTEXT, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a TINYINT, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a SMALLINT, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a MEDIUMINT, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a INT, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a BIGINT, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a FLOAT, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a DOUBLE, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a DECIMAL(10,2), b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a BIT(8), b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a TIME, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a DATE, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a DATETIME, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a TIMESTAMP, b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a YEAR, b Point)'
);
--
echo
# This creates BLOB with hybrid functions, but fails on error with UNION (MDEV-11458)
CALL
p1
(
'CREATE TABLE t1 (a ENUM(0x61), b Point)'
);
CALL
p1
(
'CREATE TABLE t1 (a SET(0x61), b Point)'
);
--
enable_query_log
--
echo
# This does not preserve geometry type (MDEV-9405)
CREATE
TABLE
t1
AS
SELECT
COALESCE
(
NULL
,
Point
(
1
,
1
));
SHOW
CREATE
TABLE
t1
;
DROP
TABLE
t1
;
CREATE
TABLE
t1
AS
SELECT
NULL
UNION
SELECT
Point
(
1
,
1
);
SHOW
CREATE
TABLE
t1
;
DROP
TABLE
t1
;
DROP
PROCEDURE
p1
;
DROP
PROCEDURE
p2
;
--
echo
#
--
echo
# End of 10.2 tests
--
echo
#
sql/field.cc
View file @
8aa044e6
This diff is collapsed.
Click to expand it.
sql/field.h
View file @
8aa044e6
...
...
@@ -853,7 +853,6 @@ class Field: public Value_source
virtual
Item_result
cmp_type
()
const
{
return
result_type
();
}
static
bool
type_can_have_key_part
(
enum_field_types
);
static
enum_field_types
field_type_merge
(
enum_field_types
,
enum_field_types
);
static
Item_result
result_merge_type
(
enum_field_types
);
virtual
bool
eq
(
Field
*
field
)
{
return
(
ptr
==
field
->
ptr
&&
null_ptr
==
field
->
null_ptr
&&
...
...
sql/item.cc
View file @
8aa044e6
...
...
@@ -9900,23 +9900,8 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item)
{
DBUG_ASSERT
(
item
->
fixed
);
maybe_null
=
item
->
maybe_null
;
collation
.
set
(
item
->
collation
);
get_full_info
(
item
);
/**
Field::result_merge_type(real_field_type()) should be equal to
result_type(), with one exception when "this" is a Item_field for
a BIT field:
- Field_bit::result_type() returns INT_RESULT, so does its Item_field.
- Field::result_merge_type(MYSQL_TYPE_BIT) returns STRING_RESULT.
Perhaps we need a new method in Type_handler to cover these type
merging rules for UNION.
*/
DBUG_ASSERT
(
real_field_type
()
==
MYSQL_TYPE_BIT
||
Item_type_holder
::
result_type
()
==
Field
::
result_merge_type
(
Item_type_holder
::
real_field_type
()));
/* fix variable decimals which always is NOT_FIXED_DEC */
if
(
Field
::
result_merge_type
(
real_field_type
())
==
INT_RESULT
)
decimals
=
0
;
DBUG_ASSERT
(
!
decimals
||
Item_type_holder
::
result_type
()
!=
INT_RESULT
);
prev_decimal_int_part
=
item
->
decimal_int_part
();
#ifdef HAVE_SPATIAL
if
(
item
->
field_type
()
==
MYSQL_TYPE_GEOMETRY
)
...
...
@@ -10030,21 +10015,37 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
DBUG_PRINT
(
"info:"
,
(
"in type %d len %d, dec %d"
,
get_real_type
(
item
),
item
->
max_length
,
item
->
decimals
));
set_handler_by_real_type
(
Field
::
field_type_merge
(
real_field_type
(),
get_real_type
(
item
)));
{
uint
item_decimals
=
item
->
decimals
;
/* fix variable decimals which always is NOT_FIXED_DEC */
if
(
Field
::
result_merge_type
(
real_field_type
())
==
INT_RESULT
)
item_decimals
=
0
;
decimals
=
MY_MAX
(
decimals
,
item_decimals
);
const
Type_handler
*
item_type_handler
=
Type_handler
::
get_handler_by_real_type
(
get_real_type
(
item
));
if
(
aggregate_for_result
(
item_type_handler
))
{
my_error
(
ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
,
MYF
(
0
),
Item_type_holder
::
type_handler
()
->
name
().
ptr
(),
item_type_handler
->
name
().
ptr
(),
"UNION"
);
DBUG_RETURN
(
true
);
}
/*
At this point non-zero decimals in combination with integer data types
is possible in some cases:
SELECT * FROM (SELECT NULL) a UNION SELECT 1;
In the constructor Item_type_holder::Item_type_holder() the data type
handler was set to type_handler_null with decimals==NOT_FIXED_DEC.
After the above call for aggregate_for_result() for the literal 1
which is on the right side of the UNION, the data type handler
changes to type_handler_longlong, while decimals is still NOT_FIXED_DEC.
*/
if
(
Item_type_holder
::
result_type
()
==
INT_RESULT
)
decimals
=
0
;
else
decimals
=
MY_MAX
(
decimals
,
item
->
decimals
);
if
(
Item_type_holder
::
field_type
()
==
FIELD_TYPE_GEOMETRY
)
geometry_type
=
Field_geom
::
geometry_type_merge
(
geometry_type
,
item
->
get_geometry_type
());
if
(
Field
::
result_merge_type
(
real_field_type
()
)
==
DECIMAL_RESULT
)
if
(
Item_type_holder
::
result_type
(
)
==
DECIMAL_RESULT
)
{
decimals
=
MY_MIN
(
MY_MAX
(
decimals
,
item
->
decimals
),
DECIMAL_MAX_SCALE
);
int
item_int_part
=
item
->
decimal_int_part
();
...
...
@@ -10056,7 +10057,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
unsigned_flag
);
}
switch
(
Field
::
result_merge_type
(
real_field_type
()
))
switch
(
Item_type_holder
::
result_type
(
))
{
case
STRING_RESULT
:
{
...
...
sql/item_cmpfunc.cc
View file @
8aa044e6
...
...
@@ -155,87 +155,6 @@ bool Type_handler_hybrid_field_type::aggregate_for_comparison(Item **items,
}
/**
@brief Aggregates field types from the array of items.
@param[in] items array of items to aggregate the type from
@paran[in] nitems number of items in the array
@param[in] treat_bit_as_number - if BIT should be aggregated to a non-BIT
counterpart as a LONGLONG number or as a VARBINARY string.
Currently behaviour depends on the function:
- LEAST/GREATEST treat BIT as VARBINARY when
aggregating with a non-BIT counterpart.
Note, UNION also works this way.
- CASE, COALESCE, IF, IFNULL treat BIT as LONGLONG when
aggregating with a non-BIT counterpart;
This inconsistency may be changed in the future. See MDEV-8867.
Note, independently from "treat_bit_as_number":
- a single BIT argument gives BIT as a result
- two BIT couterparts give BIT as a result
@details This function aggregates field types from the array of items.
Found type is supposed to be used later as the result field type
of a multi-argument function.
Aggregation itself is performed by the Field::field_type_merge()
function.
@note The term "aggregation" is used here in the sense of inferring the
result type of a function from its argument types.
@return aggregated field type.
*/
enum_field_types
agg_field_type
(
Item
**
items
,
uint
nitems
,
bool
treat_bit_as_number
)
{
uint
i
;
if
(
!
nitems
||
items
[
0
]
->
result_type
()
==
ROW_RESULT
)
{
DBUG_ASSERT
(
0
);
return
MYSQL_TYPE_NULL
;
}
enum_field_types
res
=
items
[
0
]
->
field_type
();
uint
unsigned_count
=
items
[
0
]
->
unsigned_flag
;
for
(
i
=
1
;
i
<
nitems
;
i
++
)
{
enum_field_types
cur
=
items
[
i
]
->
field_type
();
if
(
treat_bit_as_number
&&
((
res
==
MYSQL_TYPE_BIT
)
^
(
cur
==
MYSQL_TYPE_BIT
)))
{
if
(
res
==
MYSQL_TYPE_BIT
)
res
=
MYSQL_TYPE_LONGLONG
;
// BIT + non-BIT
else
cur
=
MYSQL_TYPE_LONGLONG
;
// non-BIT + BIT
}
res
=
Field
::
field_type_merge
(
res
,
cur
);
unsigned_count
+=
items
[
i
]
->
unsigned_flag
;
}
switch
(
res
)
{
case
MYSQL_TYPE_TINY
:
case
MYSQL_TYPE_SHORT
:
case
MYSQL_TYPE_LONG
:
case
MYSQL_TYPE_LONGLONG
:
case
MYSQL_TYPE_INT24
:
case
MYSQL_TYPE_YEAR
:
case
MYSQL_TYPE_BIT
:
if
(
unsigned_count
!=
0
&&
unsigned_count
!=
nitems
)
{
/*
If all arguments are of INT-alike type but have different
unsigned_flag, then convert to DECIMAL.
*/
return
MYSQL_TYPE_NEWDECIMAL
;
}
default:
break
;
}
return
res
;
}
/*
Collects different types for comparison of first item with each other items
...
...
@@ -3105,8 +3024,9 @@ void Item_func_case::fix_length_and_dec()
if
(
else_expr_num
!=
-
1
)
agg
[
nagg
++
]
=
args
[
else_expr_num
];
set_handler_by_field_type
(
agg_field_type
(
agg
,
nagg
,
true
));
if
(
aggregate_for_result
(
func_name
(),
agg
,
nagg
,
true
))
return
;
if
(
fix_attributes
(
agg
,
nagg
))
return
;
...
...
sql/item_cmpfunc.h
View file @
8aa044e6
...
...
@@ -977,8 +977,8 @@ class Item_func_coalesce :public Item_func_hybrid_field_type
bool
date_op
(
MYSQL_TIME
*
ltime
,
uint
fuzzydate
);
void
fix_length_and_dec
()
{
set_handler_by_field_type
(
agg_field_type
(
args
,
arg_count
,
true
));
fix_attributes
(
args
,
arg_count
);
if
(
!
aggregate_for_result
(
func_name
(),
args
,
arg_count
,
true
))
fix_attributes
(
args
,
arg_count
);
}
const
char
*
func_name
()
const
{
return
"coalesce"
;
}
table_map
not_null_tables
()
const
{
return
0
;
}
...
...
@@ -997,8 +997,8 @@ class Item_func_case_abbreviation2 :public Item_func_hybrid_field_type
protected:
void
fix_length_and_dec2
(
Item
**
items
)
{
set_handler_by_field_type
(
agg_field_type
(
items
,
2
,
true
));
fix_attributes
(
items
,
2
);
if
(
!
aggregate_for_result
(
func_name
(),
items
,
2
,
true
))
fix_attributes
(
items
,
2
);
}
uint
decimal_precision2
(
Item
**
args
)
const
;
public:
...
...
sql/item_func.cc
View file @
8aa044e6
...
...
@@ -2695,6 +2695,8 @@ void Item_func_min_max::fix_length_and_dec()
break
;
case
STRING_RESULT
:
if
(
aggregate_for_result
(
func_name
(),
args
,
arg_count
,
false
))
return
;
/*
All arguments are of string-alike types:
CHAR, VARCHAR, TEXT, BINARY, VARBINARY, BLOB, SET, ENUM
...
...
@@ -2702,7 +2704,6 @@ void Item_func_min_max::fix_length_and_dec()
*/
agg_arg_charsets_for_string_result_with_comparison
(
collation
,
args
,
arg_count
);
set_handler_by_field_type
(
agg_field_type
(
args
,
arg_count
,
false
));
break
;
case
INT_RESULT
:
...
...
@@ -2731,7 +2732,8 @@ void Item_func_min_max::fix_length_and_dec()
Treat BIT as LONGLONG when aggregating to non-BIT types.
Possible final type: TINY, SHORT, LONG, LONGLONG, INT24, YEAR, BIT.
*/
set_handler_by_field_type
(
agg_field_type
(
args
,
arg_count
,
true
));
if
(
aggregate_for_result
(
func_name
(),
args
,
arg_count
,
true
))
return
;
}
break
;
...
...
@@ -2754,7 +2756,7 @@ void Item_func_min_max::fix_length_and_dec()
/*
Set type to DOUBLE, as Item_func::create_tmp_field() does not
distinguish between DOUBLE and FLOAT and always creates Field_double.
Perhaps we should eventually change this to use agg
_field_type() here,
Perhaps we should eventually change this to use agg
regate_for_result()
and fix Item_func::create_tmp_field() to create Field_float when possible.
*/
set_handler_by_field_type
(
MYSQL_TYPE_DOUBLE
);
...
...
sql/item_func.h
View file @
8aa044e6
...
...
@@ -2587,8 +2587,6 @@ class Item_func_last_value :public Item_func
Item
*
get_system_var
(
THD
*
thd
,
enum_var_type
var_type
,
LEX_STRING
name
,
LEX_STRING
component
);
extern
bool
check_reserved_words
(
LEX_STRING
*
name
);
extern
enum_field_types
agg_field_type
(
Item
**
items
,
uint
nitems
,
bool
treat_bit_as_number
);
Item
*
find_date_time_item
(
Item
**
args
,
uint
nargs
,
uint
col
);
double
my_double_round
(
double
value
,
longlong
dec
,
bool
dec_unsigned
,
bool
truncate
);
...
...
sql/share/errmsg-utf8.txt
View file @
8aa044e6
...
...
@@ -7438,3 +7438,5 @@ ER_JSON_PATH_ARRAY
eng "JSON path should end with an array identifier in argument %d to function '%s'"
ER_JSON_ONE_OR_ALL
eng "Argument 2 to function '%s' must be "one" or "all"."
ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
eng "Illegal parameter data types %s and %s for operation '%s'"
sql/sql_type.cc
View file @
8aa044e6
...
...
@@ -25,7 +25,6 @@ static Type_handler_short type_handler_short;
static
Type_handler_long
type_handler_long
;
static
Type_handler_int24
type_handler_int24
;
static
Type_handler_year
type_handler_year
;
static
Type_handler_bit
type_handler_bit
;
static
Type_handler_float
type_handler_float
;
static
Type_handler_double
type_handler_double
;
static
Type_handler_time
type_handler_time
;
...
...
@@ -54,6 +53,39 @@ Type_handler_varchar type_handler_varchar;
Type_handler_longlong
type_handler_longlong
;
Type_handler_newdecimal
type_handler_newdecimal
;
Type_handler_datetime
type_handler_datetime
;
Type_handler_bit
type_handler_bit
;
Type_aggregator
type_aggregator_for_result
;
class
Static_data_initializer
{
public:
static
Static_data_initializer
m_singleton
;
Static_data_initializer
()
{
#ifdef HAVE_SPATIAL
type_aggregator_for_result
.
add
(
&
type_handler_geometry
,
&
type_handler_null
,
&
type_handler_geometry
);
type_aggregator_for_result
.
add
(
&
type_handler_geometry
,
&
type_handler_geometry
,
&
type_handler_geometry
);
type_aggregator_for_result
.
add
(
&
type_handler_geometry
,
&
type_handler_blob
,
&
type_handler_long_blob
);
type_aggregator_for_result
.
add
(
&
type_handler_geometry
,
&
type_handler_varchar
,
&
type_handler_long_blob
);
type_aggregator_for_result
.
add
(
&
type_handler_geometry
,
&
type_handler_string
,
&
type_handler_long_blob
);
#endif
}
};
Static_data_initializer
Static_data_initializer
::
m_singleton
;
void
Type_std_attributes
::
set
(
const
Field
*
field
)
...
...
@@ -149,6 +181,46 @@ Type_handler_hybrid_field_type::Type_handler_hybrid_field_type()
}
/***************************************************************************/
const
Name
Type_handler_row
::
m_name_row
(
C_STRING_WITH_LEN
(
"row"
));
const
Name
Type_handler_null
::
m_name_null
(
C_STRING_WITH_LEN
(
"null"
));
const
Name
Type_handler_string
::
m_name_char
(
C_STRING_WITH_LEN
(
"char"
)),
Type_handler_varchar
::
m_name_varchar
(
C_STRING_WITH_LEN
(
"varchar"
)),
Type_handler_tiny_blob
::
m_name_tinyblob
(
C_STRING_WITH_LEN
(
"tinyblob"
)),
Type_handler_medium_blob
::
m_name_mediumblob
(
C_STRING_WITH_LEN
(
"mediumblob"
)),
Type_handler_long_blob
::
m_name_longblob
(
C_STRING_WITH_LEN
(
"longblob"
)),
Type_handler_blob
::
m_name_blob
(
C_STRING_WITH_LEN
(
"blob"
));
const
Name
Type_handler_enum
::
m_name_enum
(
C_STRING_WITH_LEN
(
"enum"
)),
Type_handler_set
::
m_name_set
(
C_STRING_WITH_LEN
(
"set"
));
const
Name
Type_handler_tiny
::
m_name_tiny
(
C_STRING_WITH_LEN
(
"tinyint"
)),
Type_handler_short
::
m_name_short
(
C_STRING_WITH_LEN
(
"shortint"
)),
Type_handler_long
::
m_name_int
(
C_STRING_WITH_LEN
(
"int"
)),
Type_handler_longlong
::
m_name_longlong
(
C_STRING_WITH_LEN
(
"bigint"
)),
Type_handler_int24
::
m_name_mediumint
(
C_STRING_WITH_LEN
(
"mediumint"
)),
Type_handler_year
::
m_name_year
(
C_STRING_WITH_LEN
(
"year"
)),
Type_handler_bit
::
m_name_bit
(
C_STRING_WITH_LEN
(
"bit"
));
const
Name
Type_handler_float
::
m_name_float
(
C_STRING_WITH_LEN
(
"float"
)),
Type_handler_double
::
m_name_double
(
C_STRING_WITH_LEN
(
"double"
));
const
Name
Type_handler_olddecimal
::
m_name_decimal
(
C_STRING_WITH_LEN
(
"decimal"
)),
Type_handler_newdecimal
::
m_name_decimal
(
C_STRING_WITH_LEN
(
"decimal"
));
const
Name
Type_handler_time_common
::
m_name_time
(
C_STRING_WITH_LEN
(
"time"
)),
Type_handler_date_common
::
m_name_date
(
C_STRING_WITH_LEN
(
"date"
)),
Type_handler_datetime_common
::
m_name_datetime
(
C_STRING_WITH_LEN
(
"datetime"
)),
Type_handler_timestamp_common
::
m_name_timestamp
(
C_STRING_WITH_LEN
(
"timestamp"
));
/***************************************************************************/
const
Type_handler
*
Type_handler_int_result
::
type_handler_for_comparison
()
const
...
...
@@ -192,6 +264,113 @@ const Type_handler *Type_handler_row::type_handler_for_comparison() const
}
/***************************************************************************/
bool
Type_handler_hybrid_field_type
::
aggregate_for_result
(
const
Type_handler
*
other
)
{
if
(
m_type_handler
->
is_traditional_type
()
&&
other
->
is_traditional_type
())
{
m_type_handler
=
Type_handler
::
aggregate_for_result_traditional
(
m_type_handler
,
other
);
return
false
;
}
other
=
type_aggregator_for_result
.
find_handler
(
m_type_handler
,
other
);
if
(
!
other
)
return
true
;
m_type_handler
=
other
;
return
false
;
}
/**
@brief Aggregates field types from the array of items.
@param[in] items array of items to aggregate the type from
@param[in] nitems number of items in the array
@param[in] treat_bit_as_number - if BIT should be aggregated to a non-BIT
counterpart as a LONGLONG number or as a VARBINARY string.
Currently behaviour depends on the function:
- LEAST/GREATEST treat BIT as VARBINARY when
aggregating with a non-BIT counterpart.
Note, UNION also works this way.
- CASE, COALESCE, IF, IFNULL treat BIT as LONGLONG when
aggregating with a non-BIT counterpart;
This inconsistency may be changed in the future. See MDEV-8867.
Note, independently from "treat_bit_as_number":
- a single BIT argument gives BIT as a result
- two BIT couterparts give BIT as a result
@details This function aggregates field types from the array of items.
Found type is supposed to be used later as the result field type
of a multi-argument function.
Aggregation itself is performed by Type_handler::aggregate_for_result().
@note The term "aggregation" is used here in the sense of inferring the
result type of a function from its argument types.
@retval false - on success
@retval true - on error
*/
bool
Type_handler_hybrid_field_type
::
aggregate_for_result
(
const
char
*
funcname
,
Item
**
items
,
uint
nitems
,
bool
treat_bit_as_number
)
{
if
(
!
nitems
||
items
[
0
]
->
result_type
()
==
ROW_RESULT
)
{
DBUG_ASSERT
(
0
);
set_handler
(
&
type_handler_null
);
return
true
;
}
set_handler
(
items
[
0
]
->
type_handler
());
uint
unsigned_count
=
items
[
0
]
->
unsigned_flag
;
for
(
uint
i
=
1
;
i
<
nitems
;
i
++
)
{
const
Type_handler
*
cur
=
items
[
i
]
->
type_handler
();
if
(
treat_bit_as_number
&&
((
type_handler
()
==
&
type_handler_bit
)
^
(
cur
==
&
type_handler_bit
)))
{
if
(
type_handler
()
==
&
type_handler_bit
)
set_handler
(
&
type_handler_longlong
);
// BIT + non-BIT
else
cur
=
&
type_handler_longlong
;
// non-BIT + BIT
}
if
(
aggregate_for_result
(
cur
))
{
my_error
(
ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
,
MYF
(
0
),
type_handler
()
->
name
().
ptr
(),
cur
->
name
().
ptr
(),
funcname
);
return
true
;
}
unsigned_count
+=
items
[
i
]
->
unsigned_flag
;
}
switch
(
field_type
())
{
case
MYSQL_TYPE_TINY
:
case
MYSQL_TYPE_SHORT
:
case
MYSQL_TYPE_LONG
:
case
MYSQL_TYPE_LONGLONG
:
case
MYSQL_TYPE_INT24
:
case
MYSQL_TYPE_YEAR
:
case
MYSQL_TYPE_BIT
:
if
(
unsigned_count
!=
0
&&
unsigned_count
!=
nitems
)
{
/*
If all arguments are of INT-alike type but have different
unsigned_flag, then convert to DECIMAL.
*/
set_handler
(
&
type_handler_newdecimal
);
}
default:
break
;
}
return
false
;
}
/**
Collect built-in data type handlers for comparison.
This method is very similar to item_cmp_type() defined in item.cc.
...
...
@@ -719,6 +898,8 @@ Field *Type_handler_long_blob::make_conversion_table_field(TABLE *table,
#ifdef HAVE_SPATIAL
const
Name
Type_handler_geometry
::
m_name_geometry
(
C_STRING_WITH_LEN
(
"geometry"
));
Field
*
Type_handler_geometry
::
make_conversion_table_field
(
TABLE
*
table
,
uint
metadata
,
const
Field
*
target
)
...
...
sql/sql_type.h
View file @
8aa044e6
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment