mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-8865 Wrong field type or metadata for COALESCE(signed_int_column, unsigned_int_column)
Item_func_hybrid_field_type did not return correct field_type(), cmp_type() and result_type() in some cases, because cached_result_type and cached_field_type were set in independent pieces of the code and did not properly match to each other. Fix: - Removing Item_func_hybrid_result_type - Deriving Item_func_hybrid_field_type directly from Item_func - Introducing a new class Type_handler which guarantees that field_type(), cmp_type() and result_type() are always properly synchronized and using the new class in Item_func_hybrid_field_type.
This commit is contained in:
@ -104,6 +104,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
|
|||||||
../sql/sql_explain.cc ../sql/sql_explain.h
|
../sql/sql_explain.cc ../sql/sql_explain.h
|
||||||
../sql/sql_analyze_stmt.cc ../sql/sql_analyze_stmt.h
|
../sql/sql_analyze_stmt.cc ../sql/sql_analyze_stmt.h
|
||||||
../sql/compat56.cc
|
../sql/compat56.cc
|
||||||
|
../sql/sql_type.cc ../sql/sql_type.h
|
||||||
../sql/table_cache.cc ../sql/mf_iocache_encr.cc
|
../sql/table_cache.cc ../sql/mf_iocache_encr.cc
|
||||||
../sql/item_inetfunc.cc
|
../sql/item_inetfunc.cc
|
||||||
../sql/wsrep_dummy.cc ../sql/encryption.cc
|
../sql/wsrep_dummy.cc ../sql/encryption.cc
|
||||||
|
81
mysql-test/include/func_hybrid_type.inc
Normal file
81
mysql-test/include/func_hybrid_type.inc
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
# "mtr --ps" returns different values in "Max length"
|
||||||
|
--disable_ps_protocol
|
||||||
|
--enable_metadata
|
||||||
|
--vertical_results
|
||||||
|
SELECT
|
||||||
|
a AS ___________a,
|
||||||
|
CASE WHEN a IS NOT NULL THEN a END AS case_______a,
|
||||||
|
CASE WHEN a IS NOT NULL THEN a ELSE a END AS case_____a_a,
|
||||||
|
COALESCE(a) AS coalesce___a,
|
||||||
|
COALESCE(a, a) AS coalesce_a_a,
|
||||||
|
IF(a IS NULL, a, a) AS if_______a_a,
|
||||||
|
IFNULL(a, a) AS ifnull___a_a,
|
||||||
|
LEAST(a, a) AS least____a_a,
|
||||||
|
GREATEST(a, a) AS greatest_a_a,
|
||||||
|
b AS ___________b,
|
||||||
|
CASE WHEN a IS NOT NULL THEN b END AS case_______b,
|
||||||
|
CASE WHEN a IS NOT NULL THEN b ELSE b END AS case_____b_b,
|
||||||
|
COALESCE(b) AS coalesce___b,
|
||||||
|
COALESCE(b, b) AS coalesce_b_b,
|
||||||
|
IF(a IS NULL, b, b) AS if_______b_b,
|
||||||
|
IFNULL(b, b) AS ifnull___b_b,
|
||||||
|
LEAST(b, b) AS least____b_b,
|
||||||
|
GREATEST(b, b) AS greatest_b_b
|
||||||
|
FROM t1;
|
||||||
|
SELECT
|
||||||
|
CASE WHEN a IS NOT NULL THEN a ELSE b END AS case_____a_b,
|
||||||
|
CASE WHEN a IS NOT NULL THEN b ELSE a END AS case_____b_a,
|
||||||
|
COALESCE(a, b) AS coalesce_a_b,
|
||||||
|
COALESCE(b, a) AS coalesce_b_a,
|
||||||
|
IF(a IS NULL, a, b) AS if_______a_b,
|
||||||
|
IF(a IS NULL, b, a) AS if_______b_a,
|
||||||
|
IFNULL(a, b) AS ifnull___a_b,
|
||||||
|
IFNULL(b, a) AS ifnull___b_a,
|
||||||
|
LEAST(a, b) AS least____a_b,
|
||||||
|
LEAST(b, a) AS least____b_a,
|
||||||
|
GREATEST(a, b) AS greatest_a_b,
|
||||||
|
GREATEST(b, a) AS greatest_b_a
|
||||||
|
FROM t1;
|
||||||
|
--horizontal_results
|
||||||
|
--disable_metadata
|
||||||
|
--enable_ps_protocol
|
||||||
|
CREATE TABLE t2 AS
|
||||||
|
SELECT
|
||||||
|
a AS ___________a,
|
||||||
|
CASE WHEN a IS NOT NULL THEN a END AS case_______a,
|
||||||
|
CASE WHEN a IS NOT NULL THEN a ELSE a END AS case_____a_a,
|
||||||
|
COALESCE(a) AS coalesce___a,
|
||||||
|
COALESCE(a, a) AS coalesce_a_a,
|
||||||
|
IF(a IS NULL, a, a) AS if_______a_a,
|
||||||
|
IFNULL(a, a) AS ifnull___a_a,
|
||||||
|
LEAST(a, a) AS least____a_a,
|
||||||
|
GREATEST(a, a) AS greatest_a_a,
|
||||||
|
b AS ___________b,
|
||||||
|
CASE WHEN a IS NOT NULL THEN b END AS case_______b,
|
||||||
|
CASE WHEN a IS NOT NULL THEN b ELSE b END AS case_____b_b,
|
||||||
|
COALESCE(b) AS coalesce___b,
|
||||||
|
COALESCE(b, b) AS coalesce_b_b,
|
||||||
|
IF(a IS NULL, b, b) AS if_______b_b,
|
||||||
|
IFNULL(b, b) AS ifnull___b_b,
|
||||||
|
LEAST(b, b) AS least____b_b,
|
||||||
|
GREATEST(b, b) AS greatest_b_b
|
||||||
|
FROM t1;
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
DROP TABLE t2;
|
||||||
|
CREATE TABLE t2 AS
|
||||||
|
SELECT
|
||||||
|
CASE WHEN a IS NOT NULL THEN a ELSE b END AS case_____a_b,
|
||||||
|
CASE WHEN a IS NOT NULL THEN b ELSE a END AS case_____b_a,
|
||||||
|
COALESCE(a, b) AS coalesce_a_b,
|
||||||
|
COALESCE(b, a) AS coalesce_b_a,
|
||||||
|
IF(a IS NULL, a, b) AS if_______a_b,
|
||||||
|
IF(a IS NULL, b, a) AS if_______b_a,
|
||||||
|
IFNULL(a, b) AS ifnull___a_b,
|
||||||
|
IFNULL(b, a) AS ifnull___b_a,
|
||||||
|
LEAST(a, b) AS least____a_b,
|
||||||
|
LEAST(b, a) AS least____b_a,
|
||||||
|
GREATEST(a, b) AS greatest_a_b,
|
||||||
|
GREATEST(b, a) AS greatest_b_a
|
||||||
|
FROM t1;
|
||||||
|
SHOW CREATE TABLE t2;
|
||||||
|
DROP TABLE t2;
|
1396
mysql-test/r/func_hybrid_type.result
Normal file
1396
mysql-test/r/func_hybrid_type.result
Normal file
File diff suppressed because it is too large
Load Diff
63
mysql-test/t/func_hybrid_type.test
Normal file
63
mysql-test/t/func_hybrid_type.test
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
--echo #
|
||||||
|
--echo # Start of 10.1 tests
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-8865 Wrong field type or metadata for COALESCE(signed_int_column, unsigned_int_column)
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1 (a INT, b INT UNSIGNED);
|
||||||
|
INSERT INTO t1 VALUES (1,1);
|
||||||
|
INSERT INTO t1 VALUES (-1,1);
|
||||||
|
INSERT INTO t1 VALUES (-2147483648,4294967295);
|
||||||
|
--source include/func_hybrid_type.inc
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1 (a INT, b INT);
|
||||||
|
INSERT INTO t1 VALUES (1,1);
|
||||||
|
INSERT INTO t1 VALUES (-2147483648,2147483647);
|
||||||
|
--source include/func_hybrid_type.inc
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
|
||||||
|
INSERT INTO t1 VALUES (1,1);
|
||||||
|
INSERT INTO t1 VALUES (-9223372036854775808,0xFFFFFFFFFFFFFFFF);
|
||||||
|
--source include/func_hybrid_type.inc
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1 (a BIGINT, b BIGINT);
|
||||||
|
INSERT INTO t1 VALUES (1,1);
|
||||||
|
INSERT INTO t1 VALUES (-9223372036854775808,9223372036854775807);
|
||||||
|
--source include/func_hybrid_type.inc
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
# Testing BIT(N) types.
|
||||||
|
# Using safe BIT(N) type and value to make sure
|
||||||
|
# that "file func_hybrid_type.test" tells "ASCII text".
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1 (a INT, b BIT(8));
|
||||||
|
INSERT INTO t1 VALUES (-2147483648,0x32);
|
||||||
|
--source include/func_hybrid_type.inc
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1 (a INT UNSIGNED, b BIT(8));
|
||||||
|
INSERT INTO t1 VALUES (4294967295,0x32);
|
||||||
|
--source include/func_hybrid_type.inc
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1 (a BIT(7), b BIT(8));
|
||||||
|
INSERT INTO t1 VALUES (0x32,0x32);
|
||||||
|
--source include/func_hybrid_type.inc
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # End of 10.1 tests
|
||||||
|
--echo #
|
@ -135,6 +135,7 @@ SET (SQL_SOURCE
|
|||||||
my_apc.cc my_apc.h mf_iocache_encr.cc
|
my_apc.cc my_apc.h mf_iocache_encr.cc
|
||||||
my_json_writer.cc my_json_writer.h
|
my_json_writer.cc my_json_writer.h
|
||||||
rpl_gtid.cc rpl_parallel.cc
|
rpl_gtid.cc rpl_parallel.cc
|
||||||
|
sql_type.cc sql_type.h
|
||||||
${WSREP_SOURCES}
|
${WSREP_SOURCES}
|
||||||
table_cache.cc encryption.cc
|
table_cache.cc encryption.cc
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc
|
${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc
|
||||||
|
11
sql/item.h
11
sql/item.h
@ -28,6 +28,7 @@
|
|||||||
#include "unireg.h" // REQUIRED: for other includes
|
#include "unireg.h" // REQUIRED: for other includes
|
||||||
#include "thr_malloc.h" /* sql_calloc */
|
#include "thr_malloc.h" /* sql_calloc */
|
||||||
#include "field.h" /* Derivation */
|
#include "field.h" /* Derivation */
|
||||||
|
#include "sql_type.h"
|
||||||
|
|
||||||
C_MODE_START
|
C_MODE_START
|
||||||
#include <ma_dyncol.h>
|
#include <ma_dyncol.h>
|
||||||
@ -602,7 +603,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item: public Value_source, public Type_std_attributes
|
class Item: public Value_source,
|
||||||
|
public Type_std_attributes,
|
||||||
|
public Type_handler
|
||||||
{
|
{
|
||||||
Item(const Item &); /* Prevent use of these */
|
Item(const Item &); /* Prevent use of these */
|
||||||
void operator=(Item &);
|
void operator=(Item &);
|
||||||
@ -752,12 +755,12 @@ public:
|
|||||||
virtual bool send(Protocol *protocol, String *str);
|
virtual bool send(Protocol *protocol, String *str);
|
||||||
virtual bool eq(const Item *, bool binary_cmp) const;
|
virtual bool eq(const Item *, bool binary_cmp) const;
|
||||||
/* result_type() of an item specifies how the value should be returned */
|
/* result_type() of an item specifies how the value should be returned */
|
||||||
virtual Item_result result_type() const { return REAL_RESULT; }
|
Item_result result_type() const { return REAL_RESULT; }
|
||||||
/* ... while cmp_type() specifies how it should be compared */
|
/* ... while cmp_type() specifies how it should be compared */
|
||||||
virtual Item_result cmp_type() const;
|
Item_result cmp_type() const;
|
||||||
virtual Item_result cast_to_int_type() const { return cmp_type(); }
|
virtual Item_result cast_to_int_type() const { return cmp_type(); }
|
||||||
virtual enum_field_types string_field_type() const;
|
virtual enum_field_types string_field_type() const;
|
||||||
virtual enum_field_types field_type() const;
|
enum_field_types field_type() const;
|
||||||
virtual enum Type type() const =0;
|
virtual enum Type type() const =0;
|
||||||
/*
|
/*
|
||||||
real_type() is the type of base item. This is same as type() for
|
real_type() is the type of base item. This is same as type() for
|
||||||
|
@ -34,47 +34,6 @@
|
|||||||
#include "sql_time.h" // make_truncated_value_warning
|
#include "sql_time.h" // make_truncated_value_warning
|
||||||
#include "sql_base.h" // dynamic_column_error_message
|
#include "sql_base.h" // dynamic_column_error_message
|
||||||
|
|
||||||
static Item_result item_store_type(Item_result a, Item *item,
|
|
||||||
my_bool unsigned_flag)
|
|
||||||
{
|
|
||||||
Item_result b= item->result_type();
|
|
||||||
|
|
||||||
if (a == STRING_RESULT || b == STRING_RESULT)
|
|
||||||
return STRING_RESULT;
|
|
||||||
else if (a == REAL_RESULT || b == REAL_RESULT)
|
|
||||||
return REAL_RESULT;
|
|
||||||
else if (a == DECIMAL_RESULT || b == DECIMAL_RESULT ||
|
|
||||||
unsigned_flag != item->unsigned_flag)
|
|
||||||
return DECIMAL_RESULT;
|
|
||||||
else
|
|
||||||
return INT_RESULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void agg_result_type(Item_result *type, Item **items, uint nitems)
|
|
||||||
{
|
|
||||||
Item **item, **item_end;
|
|
||||||
my_bool unsigned_flag= 0;
|
|
||||||
|
|
||||||
*type= STRING_RESULT;
|
|
||||||
/* Skip beginning NULL items */
|
|
||||||
for (item= items, item_end= item + nitems; item < item_end; item++)
|
|
||||||
{
|
|
||||||
if ((*item)->type() != Item::NULL_ITEM)
|
|
||||||
{
|
|
||||||
*type= (*item)->result_type();
|
|
||||||
unsigned_flag= (*item)->unsigned_flag;
|
|
||||||
item++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Combine result types. Note: NULL items don't affect the result */
|
|
||||||
for (; item < item_end; item++)
|
|
||||||
{
|
|
||||||
if ((*item)->type() != Item::NULL_ITEM)
|
|
||||||
*type= item_store_type(*type, *item, unsigned_flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
find an temporal type (item) that others will be converted to
|
find an temporal type (item) that others will be converted to
|
||||||
@ -185,6 +144,22 @@ static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
|
|||||||
|
|
||||||
@param[in] items array of items to aggregate the type from
|
@param[in] items array of items to aggregate the type from
|
||||||
@paran[in] nitems number of items in the array
|
@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.
|
@details This function aggregates field types from the array of items.
|
||||||
Found type is supposed to be used later as the result field type
|
Found type is supposed to be used later as the result field type
|
||||||
@ -198,14 +173,50 @@ static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
|
|||||||
@return aggregated field type.
|
@return aggregated field type.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum_field_types agg_field_type(Item **items, uint nitems)
|
enum_field_types agg_field_type(Item **items, uint nitems,
|
||||||
|
bool treat_bit_as_number)
|
||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
if (!nitems || items[0]->result_type() == ROW_RESULT )
|
if (!nitems || items[0]->result_type() == ROW_RESULT)
|
||||||
return (enum_field_types)-1;
|
{
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return MYSQL_TYPE_NULL;
|
||||||
|
}
|
||||||
enum_field_types res= items[0]->field_type();
|
enum_field_types res= items[0]->field_type();
|
||||||
|
uint unsigned_count= items[0]->unsigned_flag;
|
||||||
for (i= 1 ; i < nitems ; i++)
|
for (i= 1 ; i < nitems ; i++)
|
||||||
res= Field::field_type_merge(res, items[i]->field_type());
|
{
|
||||||
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2261,13 +2272,13 @@ void
|
|||||||
Item_func_case_abbreviation2::fix_length_and_dec2(Item **args)
|
Item_func_case_abbreviation2::fix_length_and_dec2(Item **args)
|
||||||
{
|
{
|
||||||
uint32 char_length;
|
uint32 char_length;
|
||||||
agg_result_type(&cached_result_type, args, 2);
|
set_handler_by_field_type(agg_field_type(args, 2, true));
|
||||||
cached_field_type= agg_field_type(args, 2);
|
|
||||||
maybe_null=args[0]->maybe_null || args[1]->maybe_null;
|
maybe_null=args[0]->maybe_null || args[1]->maybe_null;
|
||||||
decimals= MY_MAX(args[0]->decimals, args[1]->decimals);
|
decimals= MY_MAX(args[0]->decimals, args[1]->decimals);
|
||||||
unsigned_flag= args[0]->unsigned_flag && args[1]->unsigned_flag;
|
unsigned_flag= args[0]->unsigned_flag && args[1]->unsigned_flag;
|
||||||
|
|
||||||
if (cached_result_type == DECIMAL_RESULT || cached_result_type == INT_RESULT)
|
if (Item_func_case_abbreviation2::result_type() == DECIMAL_RESULT ||
|
||||||
|
Item_func_case_abbreviation2::result_type() == INT_RESULT)
|
||||||
{
|
{
|
||||||
int len0= args[0]->max_char_length() - args[0]->decimals
|
int len0= args[0]->max_char_length() - args[0]->decimals
|
||||||
- (args[0]->unsigned_flag ? 0 : 1);
|
- (args[0]->unsigned_flag ? 0 : 1);
|
||||||
@ -2280,9 +2291,10 @@ Item_func_case_abbreviation2::fix_length_and_dec2(Item **args)
|
|||||||
else
|
else
|
||||||
char_length= MY_MAX(args[0]->max_char_length(), args[1]->max_char_length());
|
char_length= MY_MAX(args[0]->max_char_length(), args[1]->max_char_length());
|
||||||
|
|
||||||
switch (cached_result_type) {
|
switch (Item_func_case_abbreviation2::result_type()) {
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
if (count_string_result_length(cached_field_type, args, 2))
|
if (count_string_result_length(Item_func_case_abbreviation2::field_type(),
|
||||||
|
args, 2))
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
@ -2459,8 +2471,7 @@ void Item_func_if::fix_after_pullout(st_select_lex *new_parent, Item **ref)
|
|||||||
void Item_func_if::cache_type_info(Item *source)
|
void Item_func_if::cache_type_info(Item *source)
|
||||||
{
|
{
|
||||||
Type_std_attributes::set(source);
|
Type_std_attributes::set(source);
|
||||||
cached_field_type= source->field_type();
|
set_handler_by_field_type(source->field_type());
|
||||||
cached_result_type= source->result_type();
|
|
||||||
maybe_null= source->maybe_null;
|
maybe_null= source->maybe_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2475,7 +2486,7 @@ Item_func_if::fix_length_and_dec()
|
|||||||
maybe_null= true;
|
maybe_null= true;
|
||||||
// If both arguments are NULL, make resulting type BINARY(0).
|
// If both arguments are NULL, make resulting type BINARY(0).
|
||||||
if (args[2]->type() == NULL_ITEM)
|
if (args[2]->type() == NULL_ITEM)
|
||||||
cached_field_type= MYSQL_TYPE_STRING;
|
set_handler_by_field_type(MYSQL_TYPE_STRING);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (args[2]->type() == NULL_ITEM)
|
if (args[2]->type() == NULL_ITEM)
|
||||||
@ -2546,8 +2557,7 @@ Item_func_nullif::fix_length_and_dec()
|
|||||||
if (!args[2]) // Only false if EOM
|
if (!args[2]) // Only false if EOM
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cached_result_type= args[2]->result_type();
|
set_handler_by_field_type(args[2]->field_type());
|
||||||
cached_field_type= args[2]->field_type();
|
|
||||||
collation.set(args[2]->collation);
|
collation.set(args[2]->collation);
|
||||||
decimals= args[2]->decimals;
|
decimals= args[2]->decimals;
|
||||||
unsigned_flag= args[2]->unsigned_flag;
|
unsigned_flag= args[2]->unsigned_flag;
|
||||||
@ -2961,12 +2971,11 @@ void Item_func_case::fix_length_and_dec()
|
|||||||
if (else_expr_num != -1)
|
if (else_expr_num != -1)
|
||||||
agg[nagg++]= args[else_expr_num];
|
agg[nagg++]= args[else_expr_num];
|
||||||
|
|
||||||
agg_result_type(&cached_result_type, agg, nagg);
|
set_handler_by_field_type(agg_field_type(agg, nagg, true));
|
||||||
cached_field_type= agg_field_type(agg, nagg);
|
|
||||||
|
|
||||||
if (cached_result_type == STRING_RESULT)
|
if (Item_func_case::result_type() == STRING_RESULT)
|
||||||
{
|
{
|
||||||
if (count_string_result_length(cached_field_type, agg, nagg))
|
if (count_string_result_length(Item_func_case::field_type(), agg, nagg))
|
||||||
return;
|
return;
|
||||||
/*
|
/*
|
||||||
Copy all THEN and ELSE items back to args[] array.
|
Copy all THEN and ELSE items back to args[] array.
|
||||||
@ -3295,11 +3304,11 @@ my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
|
|||||||
|
|
||||||
void Item_func_coalesce::fix_length_and_dec()
|
void Item_func_coalesce::fix_length_and_dec()
|
||||||
{
|
{
|
||||||
cached_field_type= agg_field_type(args, arg_count);
|
set_handler_by_field_type(agg_field_type(args, arg_count, true));
|
||||||
agg_result_type(&cached_result_type, args, arg_count);
|
switch (Item_func_coalesce::result_type()) {
|
||||||
switch (cached_result_type) {
|
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
if (count_string_result_length(cached_field_type, args, arg_count))
|
if (count_string_result_length(Item_func_coalesce::field_type(),
|
||||||
|
args, arg_count))
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
|
@ -800,28 +800,28 @@ void Item_num_op::fix_length_and_dec(void)
|
|||||||
{
|
{
|
||||||
count_real_length();
|
count_real_length();
|
||||||
max_length= float_length(decimals);
|
max_length= float_length(decimals);
|
||||||
cached_result_type= REAL_RESULT;
|
set_handler_by_result_type(REAL_RESULT);
|
||||||
}
|
}
|
||||||
else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT ||
|
else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT ||
|
||||||
r0 == TIME_RESULT || r1 == TIME_RESULT)
|
r0 == TIME_RESULT || r1 == TIME_RESULT)
|
||||||
{
|
{
|
||||||
cached_result_type= DECIMAL_RESULT;
|
set_handler_by_result_type(DECIMAL_RESULT);
|
||||||
result_precision();
|
result_precision();
|
||||||
fix_decimals();
|
fix_decimals();
|
||||||
if ((r0 == TIME_RESULT || r1 == TIME_RESULT) && decimals == 0)
|
if ((r0 == TIME_RESULT || r1 == TIME_RESULT) && decimals == 0)
|
||||||
cached_result_type= INT_RESULT;
|
set_handler_by_result_type(INT_RESULT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
|
DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
|
||||||
cached_result_type=INT_RESULT;
|
set_handler_by_result_type(INT_RESULT);
|
||||||
result_precision();
|
result_precision();
|
||||||
decimals= 0;
|
decimals= 0;
|
||||||
}
|
}
|
||||||
DBUG_PRINT("info", ("Type: %s",
|
DBUG_PRINT("info", ("Type: %s",
|
||||||
(cached_result_type == REAL_RESULT ? "REAL_RESULT" :
|
(result_type() == REAL_RESULT ? "REAL_RESULT" :
|
||||||
cached_result_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
||||||
cached_result_type == INT_RESULT ? "INT_RESULT" :
|
result_type() == INT_RESULT ? "INT_RESULT" :
|
||||||
"--ILLEGAL!!!--")));
|
"--ILLEGAL!!!--")));
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -837,20 +837,22 @@ void Item_func_num1::fix_length_and_dec()
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("Item_func_num1::fix_length_and_dec");
|
DBUG_ENTER("Item_func_num1::fix_length_and_dec");
|
||||||
DBUG_PRINT("info", ("name %s", func_name()));
|
DBUG_PRINT("info", ("name %s", func_name()));
|
||||||
switch (cached_result_type= args[0]->cast_to_int_type()) {
|
// Note, cast_to_int_type() can return TIME_RESULT
|
||||||
|
switch (args[0]->cast_to_int_type()) {
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
|
set_handler_by_result_type(INT_RESULT);
|
||||||
max_length= args[0]->max_length;
|
max_length= args[0]->max_length;
|
||||||
unsigned_flag= args[0]->unsigned_flag;
|
unsigned_flag= args[0]->unsigned_flag;
|
||||||
break;
|
break;
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
cached_result_type= REAL_RESULT;
|
set_handler_by_result_type(REAL_RESULT);
|
||||||
decimals= args[0]->decimals; // Preserve NOT_FIXED_DEC
|
decimals= args[0]->decimals; // Preserve NOT_FIXED_DEC
|
||||||
max_length= float_length(decimals);
|
max_length= float_length(decimals);
|
||||||
break;
|
break;
|
||||||
case TIME_RESULT:
|
case TIME_RESULT:
|
||||||
cached_result_type= DECIMAL_RESULT;
|
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
|
set_handler_by_result_type(DECIMAL_RESULT);
|
||||||
decimals= args[0]->decimal_scale(); // Do not preserve NOT_FIXED_DEC
|
decimals= args[0]->decimal_scale(); // Do not preserve NOT_FIXED_DEC
|
||||||
max_length= args[0]->max_length;
|
max_length= args[0]->max_length;
|
||||||
break;
|
break;
|
||||||
@ -858,18 +860,18 @@ void Item_func_num1::fix_length_and_dec()
|
|||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
}
|
}
|
||||||
DBUG_PRINT("info", ("Type: %s",
|
DBUG_PRINT("info", ("Type: %s",
|
||||||
(cached_result_type == REAL_RESULT ? "REAL_RESULT" :
|
(result_type() == REAL_RESULT ? "REAL_RESULT" :
|
||||||
cached_result_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
||||||
cached_result_type == INT_RESULT ? "INT_RESULT" :
|
result_type() == INT_RESULT ? "INT_RESULT" :
|
||||||
"--ILLEGAL!!!--")));
|
"--ILLEGAL!!!--")));
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String *Item_func_hybrid_result_type::val_str(String *str)
|
String *Item_func_hybrid_field_type::val_str(String *str)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
switch (cached_result_type) {
|
switch (Item_func_hybrid_field_type::result_type()) {
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
{
|
{
|
||||||
my_decimal decimal_value, *val;
|
my_decimal decimal_value, *val;
|
||||||
@ -921,10 +923,10 @@ String *Item_func_hybrid_result_type::val_str(String *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
double Item_func_hybrid_result_type::val_real()
|
double Item_func_hybrid_field_type::val_real()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
switch (cached_result_type) {
|
switch (Item_func_hybrid_field_type::result_type()) {
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
{
|
{
|
||||||
my_decimal decimal_value, *val;
|
my_decimal decimal_value, *val;
|
||||||
@ -966,10 +968,10 @@ double Item_func_hybrid_result_type::val_real()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Item_func_hybrid_result_type::val_int()
|
longlong Item_func_hybrid_field_type::val_int()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
switch (cached_result_type) {
|
switch (Item_func_hybrid_field_type::result_type()) {
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
{
|
{
|
||||||
my_decimal decimal_value, *val;
|
my_decimal decimal_value, *val;
|
||||||
@ -1008,11 +1010,11 @@ longlong Item_func_hybrid_result_type::val_int()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
my_decimal *Item_func_hybrid_result_type::val_decimal(my_decimal *decimal_value)
|
my_decimal *Item_func_hybrid_field_type::val_decimal(my_decimal *decimal_value)
|
||||||
{
|
{
|
||||||
my_decimal *val= decimal_value;
|
my_decimal *val= decimal_value;
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
switch (cached_result_type) {
|
switch (Item_func_hybrid_field_type::result_type()) {
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
val= decimal_op(decimal_value);
|
val= decimal_op(decimal_value);
|
||||||
break;
|
break;
|
||||||
@ -1054,11 +1056,11 @@ my_decimal *Item_func_hybrid_result_type::val_decimal(my_decimal *decimal_value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Item_func_hybrid_result_type::get_date(MYSQL_TIME *ltime,
|
bool Item_func_hybrid_field_type::get_date(MYSQL_TIME *ltime,
|
||||||
ulonglong fuzzydate)
|
ulonglong fuzzydate)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
switch (cached_result_type) {
|
switch (Item_func_hybrid_field_type::result_type()) {
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
{
|
{
|
||||||
my_decimal value, *res;
|
my_decimal value, *res;
|
||||||
@ -1812,7 +1814,7 @@ void Item_func_div::fix_length_and_dec()
|
|||||||
DBUG_ENTER("Item_func_div::fix_length_and_dec");
|
DBUG_ENTER("Item_func_div::fix_length_and_dec");
|
||||||
prec_increment= current_thd->variables.div_precincrement;
|
prec_increment= current_thd->variables.div_precincrement;
|
||||||
Item_num_op::fix_length_and_dec();
|
Item_num_op::fix_length_and_dec();
|
||||||
switch (cached_result_type) {
|
switch (Item_func_div::result_type()) {
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
{
|
{
|
||||||
decimals=MY_MAX(args[0]->decimals,args[1]->decimals)+prec_increment;
|
decimals=MY_MAX(args[0]->decimals,args[1]->decimals)+prec_increment;
|
||||||
@ -1828,7 +1830,7 @@ void Item_func_div::fix_length_and_dec()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
cached_result_type= DECIMAL_RESULT;
|
set_handler_by_result_type(DECIMAL_RESULT);
|
||||||
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
|
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
|
||||||
result_precision();
|
result_precision();
|
||||||
break;
|
break;
|
||||||
@ -2075,7 +2077,7 @@ void Item_func_neg::fix_length_and_dec()
|
|||||||
Use val() to get value as arg_type doesn't mean that item is
|
Use val() to get value as arg_type doesn't mean that item is
|
||||||
Item_int or Item_float due to existence of Item_param.
|
Item_int or Item_float due to existence of Item_param.
|
||||||
*/
|
*/
|
||||||
if (cached_result_type == INT_RESULT && args[0]->const_item())
|
if (Item_func_neg::result_type() == INT_RESULT && args[0]->const_item())
|
||||||
{
|
{
|
||||||
longlong val= args[0]->val_int();
|
longlong val= args[0]->val_int();
|
||||||
if ((ulonglong) val >= (ulonglong) LONGLONG_MIN &&
|
if ((ulonglong) val >= (ulonglong) LONGLONG_MIN &&
|
||||||
@ -2086,7 +2088,7 @@ void Item_func_neg::fix_length_and_dec()
|
|||||||
Ensure that result is converted to DECIMAL, as longlong can't hold
|
Ensure that result is converted to DECIMAL, as longlong can't hold
|
||||||
the negated number
|
the negated number
|
||||||
*/
|
*/
|
||||||
cached_result_type= DECIMAL_RESULT;
|
set_handler_by_result_type(DECIMAL_RESULT);
|
||||||
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
|
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2388,11 +2390,12 @@ void Item_func_int_val::fix_length_and_dec()
|
|||||||
set_if_smaller(max_length,tmp);
|
set_if_smaller(max_length,tmp);
|
||||||
decimals= 0;
|
decimals= 0;
|
||||||
|
|
||||||
switch (cached_result_type= args[0]->cast_to_int_type())
|
// Note, cast_to_int_type() can return TIME_RESULT
|
||||||
|
switch (args[0]->cast_to_int_type())
|
||||||
{
|
{
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
cached_result_type= REAL_RESULT;
|
set_handler_by_result_type(REAL_RESULT);
|
||||||
max_length= float_length(decimals);
|
max_length= float_length(decimals);
|
||||||
break;
|
break;
|
||||||
case INT_RESULT:
|
case INT_RESULT:
|
||||||
@ -2405,21 +2408,21 @@ void Item_func_int_val::fix_length_and_dec()
|
|||||||
if ((args[0]->max_length - args[0]->decimals) >=
|
if ((args[0]->max_length - args[0]->decimals) >=
|
||||||
(DECIMAL_LONGLONG_DIGITS - 2))
|
(DECIMAL_LONGLONG_DIGITS - 2))
|
||||||
{
|
{
|
||||||
cached_result_type= DECIMAL_RESULT;
|
set_handler_by_result_type(DECIMAL_RESULT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned_flag= args[0]->unsigned_flag;
|
unsigned_flag= args[0]->unsigned_flag;
|
||||||
cached_result_type= INT_RESULT;
|
set_handler_by_result_type(INT_RESULT);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ROW_RESULT:
|
case ROW_RESULT:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
}
|
}
|
||||||
DBUG_PRINT("info", ("Type: %s",
|
DBUG_PRINT("info", ("Type: %s",
|
||||||
(cached_result_type == REAL_RESULT ? "REAL_RESULT" :
|
(result_type() == REAL_RESULT ? "REAL_RESULT" :
|
||||||
cached_result_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
||||||
cached_result_type == INT_RESULT ? "INT_RESULT" :
|
result_type() == INT_RESULT ? "INT_RESULT" :
|
||||||
"--ILLEGAL!!!--")));
|
"--ILLEGAL!!!--")));
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -2534,10 +2537,10 @@ void Item_func_round::fix_length_and_dec()
|
|||||||
if (args[0]->result_type() == DECIMAL_RESULT)
|
if (args[0]->result_type() == DECIMAL_RESULT)
|
||||||
{
|
{
|
||||||
max_length++;
|
max_length++;
|
||||||
cached_result_type= DECIMAL_RESULT;
|
set_handler_by_result_type(DECIMAL_RESULT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
cached_result_type= REAL_RESULT;
|
set_handler_by_result_type(REAL_RESULT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2555,14 +2558,14 @@ void Item_func_round::fix_length_and_dec()
|
|||||||
{
|
{
|
||||||
decimals= MY_MIN(decimals_to_set, NOT_FIXED_DEC);
|
decimals= MY_MIN(decimals_to_set, NOT_FIXED_DEC);
|
||||||
max_length= float_length(decimals);
|
max_length= float_length(decimals);
|
||||||
cached_result_type= REAL_RESULT;
|
set_handler_by_result_type(REAL_RESULT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (args[0]->result_type()) {
|
switch (args[0]->result_type()) {
|
||||||
case REAL_RESULT:
|
case REAL_RESULT:
|
||||||
case STRING_RESULT:
|
case STRING_RESULT:
|
||||||
cached_result_type= REAL_RESULT;
|
set_handler_by_result_type(REAL_RESULT);
|
||||||
decimals= MY_MIN(decimals_to_set, NOT_FIXED_DEC);
|
decimals= MY_MIN(decimals_to_set, NOT_FIXED_DEC);
|
||||||
max_length= float_length(decimals);
|
max_length= float_length(decimals);
|
||||||
break;
|
break;
|
||||||
@ -2573,14 +2576,14 @@ void Item_func_round::fix_length_and_dec()
|
|||||||
!val1_unsigned);
|
!val1_unsigned);
|
||||||
max_length= args[0]->max_length + length_can_increase;
|
max_length= args[0]->max_length + length_can_increase;
|
||||||
/* Here we can keep INT_RESULT */
|
/* Here we can keep INT_RESULT */
|
||||||
cached_result_type= INT_RESULT;
|
set_handler_by_result_type(INT_RESULT);
|
||||||
decimals= 0;
|
decimals= 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case DECIMAL_RESULT:
|
case DECIMAL_RESULT:
|
||||||
{
|
{
|
||||||
cached_result_type= DECIMAL_RESULT;
|
set_handler_by_result_type(DECIMAL_RESULT);
|
||||||
decimals_to_set= MY_MIN(DECIMAL_MAX_SCALE, decimals_to_set);
|
decimals_to_set= MY_MIN(DECIMAL_MAX_SCALE, decimals_to_set);
|
||||||
int decimals_delta= args[0]->decimals - decimals_to_set;
|
int decimals_delta= args[0]->decimals - decimals_to_set;
|
||||||
int precision= args[0]->decimal_precision();
|
int precision= args[0]->decimal_precision();
|
||||||
@ -2884,7 +2887,7 @@ void Item_func_min_max::fix_length_and_dec()
|
|||||||
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
|
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
cached_field_type= agg_field_type(args, arg_count);
|
cached_field_type= agg_field_type(args, arg_count, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -373,29 +373,32 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Item_func_hybrid_result_type: public Item_func
|
class Item_func_hybrid_field_type: public Item_func,
|
||||||
|
public Type_handler_hybrid_field_type
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
Item_result cached_result_type;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Item_func_hybrid_result_type(THD *thd):
|
Item_func_hybrid_field_type(THD *thd):
|
||||||
Item_func(thd), cached_result_type(REAL_RESULT)
|
Item_func(thd)
|
||||||
{ collation.set_numeric(); }
|
{ collation.set_numeric(); }
|
||||||
Item_func_hybrid_result_type(THD *thd, Item *a):
|
Item_func_hybrid_field_type(THD *thd, Item *a):
|
||||||
Item_func(thd, a), cached_result_type(REAL_RESULT)
|
Item_func(thd, a)
|
||||||
{ collation.set_numeric(); }
|
{ collation.set_numeric(); }
|
||||||
Item_func_hybrid_result_type(THD *thd, Item *a, Item *b):
|
Item_func_hybrid_field_type(THD *thd, Item *a, Item *b):
|
||||||
Item_func(thd, a, b), cached_result_type(REAL_RESULT)
|
Item_func(thd, a, b)
|
||||||
{ collation.set_numeric(); }
|
{ collation.set_numeric(); }
|
||||||
Item_func_hybrid_result_type(THD *thd, Item *a, Item *b, Item *c):
|
Item_func_hybrid_field_type(THD *thd, Item *a, Item *b, Item *c):
|
||||||
Item_func(thd, a, b, c), cached_result_type(REAL_RESULT)
|
Item_func(thd, a, b, c)
|
||||||
{ collation.set_numeric(); }
|
{ collation.set_numeric(); }
|
||||||
Item_func_hybrid_result_type(THD *thd, List<Item> &list):
|
Item_func_hybrid_field_type(THD *thd, List<Item> &list):
|
||||||
Item_func(thd, list), cached_result_type(REAL_RESULT)
|
Item_func(thd, list)
|
||||||
{ collation.set_numeric(); }
|
{ collation.set_numeric(); }
|
||||||
|
|
||||||
enum Item_result result_type () const { return cached_result_type; }
|
enum_field_types field_type() const
|
||||||
|
{ return Type_handler_hybrid_field_type::field_type(); }
|
||||||
|
enum Item_result result_type () const
|
||||||
|
{ return Type_handler_hybrid_field_type::result_type(); }
|
||||||
|
enum Item_result cmp_type () const
|
||||||
|
{ return Type_handler_hybrid_field_type::cmp_type(); }
|
||||||
|
|
||||||
double val_real();
|
double val_real();
|
||||||
longlong val_int();
|
longlong val_int();
|
||||||
@ -449,33 +452,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Item_func_numhybrid: public Item_func_hybrid_field_type
|
||||||
class Item_func_hybrid_field_type :public Item_func_hybrid_result_type
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
enum_field_types cached_field_type;
|
|
||||||
public:
|
|
||||||
Item_func_hybrid_field_type(THD *thd):
|
|
||||||
Item_func_hybrid_result_type(thd), cached_field_type(MYSQL_TYPE_DOUBLE)
|
|
||||||
{}
|
|
||||||
Item_func_hybrid_field_type(THD *thd, Item *a, Item *b):
|
|
||||||
Item_func_hybrid_result_type(thd, a, b),
|
|
||||||
cached_field_type(MYSQL_TYPE_DOUBLE)
|
|
||||||
{}
|
|
||||||
Item_func_hybrid_field_type(THD *thd, Item *a, Item *b, Item *c):
|
|
||||||
Item_func_hybrid_result_type(thd, a, b, c),
|
|
||||||
cached_field_type(MYSQL_TYPE_DOUBLE)
|
|
||||||
{}
|
|
||||||
Item_func_hybrid_field_type(THD *thd, List<Item> &list):
|
|
||||||
Item_func_hybrid_result_type(thd, list),
|
|
||||||
cached_field_type(MYSQL_TYPE_DOUBLE)
|
|
||||||
{}
|
|
||||||
enum_field_types field_type() const { return cached_field_type; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Item_func_numhybrid: public Item_func_hybrid_result_type
|
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@ -487,18 +464,18 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Item_func_numhybrid(THD *thd): Item_func_hybrid_result_type(thd)
|
Item_func_numhybrid(THD *thd): Item_func_hybrid_field_type(thd)
|
||||||
{ }
|
{ }
|
||||||
Item_func_numhybrid(THD *thd, Item *a): Item_func_hybrid_result_type(thd, a)
|
Item_func_numhybrid(THD *thd, Item *a): Item_func_hybrid_field_type(thd, a)
|
||||||
{ }
|
{ }
|
||||||
Item_func_numhybrid(THD *thd, Item *a, Item *b):
|
Item_func_numhybrid(THD *thd, Item *a, Item *b):
|
||||||
Item_func_hybrid_result_type(thd, a, b)
|
Item_func_hybrid_field_type(thd, a, b)
|
||||||
{ }
|
{ }
|
||||||
Item_func_numhybrid(THD *thd, Item *a, Item *b, Item *c):
|
Item_func_numhybrid(THD *thd, Item *a, Item *b, Item *c):
|
||||||
Item_func_hybrid_result_type(thd, a, b, c)
|
Item_func_hybrid_field_type(thd, a, b, c)
|
||||||
{ }
|
{ }
|
||||||
Item_func_numhybrid(THD *thd, List<Item> &list):
|
Item_func_numhybrid(THD *thd, List<Item> &list):
|
||||||
Item_func_hybrid_result_type(thd, list)
|
Item_func_hybrid_field_type(thd, list)
|
||||||
{ }
|
{ }
|
||||||
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
|
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
|
||||||
bool date_op(MYSQL_TIME *ltime, uint fuzzydate) { DBUG_ASSERT(0); return true; }
|
bool date_op(MYSQL_TIME *ltime, uint fuzzydate) { DBUG_ASSERT(0); return true; }
|
||||||
@ -2169,7 +2146,8 @@ public:
|
|||||||
Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
|
Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
|
||||||
LEX_STRING component);
|
LEX_STRING component);
|
||||||
extern bool check_reserved_words(LEX_STRING *name);
|
extern bool check_reserved_words(LEX_STRING *name);
|
||||||
extern enum_field_types agg_field_type(Item **items, uint nitems);
|
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);
|
Item *find_date_time_item(Item **args, uint nargs, uint col);
|
||||||
double my_double_round(double value, longlong dec, bool dec_unsigned,
|
double my_double_round(double value, longlong dec, bool dec_unsigned,
|
||||||
bool truncate);
|
bool truncate);
|
||||||
|
@ -421,7 +421,7 @@ public:
|
|||||||
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
|
set_if_smaller(decimals, TIME_SECOND_PART_DIGITS);
|
||||||
max_length=17 + (decimals ? decimals + 1 : 0);
|
max_length=17 + (decimals ? decimals + 1 : 0);
|
||||||
maybe_null= true;
|
maybe_null= true;
|
||||||
cached_result_type= decimals ? DECIMAL_RESULT : INT_RESULT;
|
set_handler_by_result_type(decimals ? DECIMAL_RESULT : INT_RESULT);
|
||||||
}
|
}
|
||||||
double real_op() { DBUG_ASSERT(0); return 0; }
|
double real_op() { DBUG_ASSERT(0); return 0; }
|
||||||
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
|
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
|
||||||
|
106
sql/sql_type.cc
Normal file
106
sql/sql_type.cc
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2015 MariaDB Foundation.
|
||||||
|
|
||||||
|
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 */
|
||||||
|
|
||||||
|
#include "sql_type.h"
|
||||||
|
|
||||||
|
static Type_handler_tiny type_handler_tiny;
|
||||||
|
static Type_handler_short type_handler_short;
|
||||||
|
static Type_handler_long type_handler_long;
|
||||||
|
static Type_handler_longlong type_handler_longlong;
|
||||||
|
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;
|
||||||
|
static Type_handler_date type_handler_date;
|
||||||
|
static Type_handler_datetime type_handler_datetime;
|
||||||
|
static Type_handler_timestamp type_handler_timestamp;
|
||||||
|
static Type_handler_olddecimal type_handler_olddecimal;
|
||||||
|
static Type_handler_newdecimal type_handler_newdecimal;
|
||||||
|
static Type_handler_null type_handler_null;
|
||||||
|
static Type_handler_string type_handler_string;
|
||||||
|
static Type_handler_varchar type_handler_varchar;
|
||||||
|
static Type_handler_tiny_blob type_handler_tiny_blob;
|
||||||
|
static Type_handler_medium_blob type_handler_medium_blob;
|
||||||
|
static Type_handler_long_blob type_handler_long_blob;
|
||||||
|
static Type_handler_blob type_handler_blob;
|
||||||
|
static Type_handler_geometry type_handler_geometry;
|
||||||
|
|
||||||
|
|
||||||
|
Type_handler_hybrid_field_type::Type_handler_hybrid_field_type()
|
||||||
|
:m_type_handler(&type_handler_double)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Type_handler *
|
||||||
|
Type_handler_hybrid_field_type::get_handler_by_result_type(Item_result type)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case REAL_RESULT: return &type_handler_double;
|
||||||
|
case INT_RESULT: return &type_handler_longlong;
|
||||||
|
case DECIMAL_RESULT: return &type_handler_newdecimal;
|
||||||
|
case STRING_RESULT: return &type_handler_string;
|
||||||
|
case TIME_RESULT:
|
||||||
|
case ROW_RESULT:
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
}
|
||||||
|
return &type_handler_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Type_handler *
|
||||||
|
Type_handler_hybrid_field_type::get_handler_by_field_type(enum_field_types type)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case MYSQL_TYPE_DECIMAL: return &type_handler_olddecimal;
|
||||||
|
case MYSQL_TYPE_NEWDECIMAL: return &type_handler_newdecimal;
|
||||||
|
case MYSQL_TYPE_TINY: return &type_handler_tiny;
|
||||||
|
case MYSQL_TYPE_SHORT: return &type_handler_short;
|
||||||
|
case MYSQL_TYPE_LONG: return &type_handler_long;
|
||||||
|
case MYSQL_TYPE_LONGLONG: return &type_handler_longlong;
|
||||||
|
case MYSQL_TYPE_INT24: return &type_handler_int24;
|
||||||
|
case MYSQL_TYPE_YEAR: return &type_handler_year;
|
||||||
|
case MYSQL_TYPE_BIT: return &type_handler_bit;
|
||||||
|
case MYSQL_TYPE_FLOAT: return &type_handler_float;
|
||||||
|
case MYSQL_TYPE_DOUBLE: return &type_handler_double;
|
||||||
|
case MYSQL_TYPE_NULL: return &type_handler_null;
|
||||||
|
case MYSQL_TYPE_VARCHAR: return &type_handler_varchar;
|
||||||
|
case MYSQL_TYPE_TINY_BLOB: return &type_handler_tiny_blob;
|
||||||
|
case MYSQL_TYPE_MEDIUM_BLOB: return &type_handler_medium_blob;
|
||||||
|
case MYSQL_TYPE_LONG_BLOB: return &type_handler_long_blob;
|
||||||
|
case MYSQL_TYPE_BLOB: return &type_handler_blob;
|
||||||
|
case MYSQL_TYPE_VAR_STRING: return &type_handler_varchar; // Map to VARCHAR
|
||||||
|
case MYSQL_TYPE_STRING: return &type_handler_string;
|
||||||
|
case MYSQL_TYPE_ENUM: return &type_handler_varchar; // Map to VARCHAR
|
||||||
|
case MYSQL_TYPE_SET: return &type_handler_varchar; // Map to VARCHAR
|
||||||
|
case MYSQL_TYPE_GEOMETRY: return &type_handler_geometry;
|
||||||
|
case MYSQL_TYPE_TIMESTAMP: return &type_handler_timestamp;
|
||||||
|
case MYSQL_TYPE_TIMESTAMP2: return &type_handler_timestamp;
|
||||||
|
case MYSQL_TYPE_DATE: return &type_handler_date;
|
||||||
|
case MYSQL_TYPE_TIME: return &type_handler_time;
|
||||||
|
case MYSQL_TYPE_TIME2: return &type_handler_time;
|
||||||
|
case MYSQL_TYPE_DATETIME: return &type_handler_datetime;
|
||||||
|
case MYSQL_TYPE_DATETIME2: return &type_handler_datetime;
|
||||||
|
case MYSQL_TYPE_NEWDATE: return &type_handler_date;
|
||||||
|
};
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return &type_handler_string;
|
||||||
|
}
|
||||||
|
|
286
sql/sql_type.h
Normal file
286
sql/sql_type.h
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
#ifndef SQL_TYPE_H_INCLUDED
|
||||||
|
#define SQL_TYPE_H_INCLUDED
|
||||||
|
/*
|
||||||
|
Copyright (c) 2015 MariaDB Foundation.
|
||||||
|
|
||||||
|
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 */
|
||||||
|
|
||||||
|
#ifdef USE_PRAGMA_INTERFACE
|
||||||
|
#pragma interface /* gcc class implementation */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#include "mysqld.h"
|
||||||
|
|
||||||
|
class Type_handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual enum_field_types field_type() const= 0;
|
||||||
|
virtual Item_result result_type() const= 0;
|
||||||
|
virtual Item_result cmp_type() const= 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*** Abstract classes for every XXX_RESULT */
|
||||||
|
|
||||||
|
class Type_handler_real_result: public Type_handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Item_result result_type() const { return REAL_RESULT; }
|
||||||
|
Item_result cmp_type() const { return REAL_RESULT; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_decimal_result: public Type_handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Item_result result_type() const { return DECIMAL_RESULT; }
|
||||||
|
Item_result cmp_type() const { return DECIMAL_RESULT; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_int_result: public Type_handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Item_result result_type() const { return INT_RESULT; }
|
||||||
|
Item_result cmp_type() const { return INT_RESULT; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_temporal_result: public Type_handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Item_result result_type() const { return STRING_RESULT; }
|
||||||
|
Item_result cmp_type() const { return TIME_RESULT; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_string_result: public Type_handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Item_result result_type() const { return STRING_RESULT; }
|
||||||
|
Item_result cmp_type() const { return STRING_RESULT; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/***
|
||||||
|
Instantiable classes for every MYSQL_TYPE_XXX
|
||||||
|
|
||||||
|
There are no Type_handler_xxx for the following types:
|
||||||
|
- MYSQL_TYPE_VAR_STRING (old VARCHAR) - mapped to MYSQL_TYPE_VARSTRING
|
||||||
|
- MYSQL_TYPE_ENUM - mapped to MYSQL_TYPE_VARSTRING
|
||||||
|
- MYSQL_TYPE_SET: - mapped to MYSQL_TYPE_VARSTRING
|
||||||
|
|
||||||
|
because the functionality that currently uses Type_handler
|
||||||
|
(e.g. hybrid type functions) does not need to distinguish between
|
||||||
|
these types and VARCHAR.
|
||||||
|
For example:
|
||||||
|
CREATE TABLE t2 AS SELECT COALESCE(enum_column) FROM t1;
|
||||||
|
creates a VARCHAR column.
|
||||||
|
|
||||||
|
There most likely be Type_handler_enum and Type_handler_set later,
|
||||||
|
when the Type_handler infrastructure gets used in more pieces of the code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_tiny: public Type_handler_int_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_TINY; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_short: public Type_handler_int_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_SHORT; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_long: public Type_handler_int_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_LONG; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_longlong: public Type_handler_int_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_int24: public Type_handler_int_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_INT24; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_year: public Type_handler_int_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_YEAR; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_bit: public Type_handler_int_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_BIT; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_float: public Type_handler_real_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_FLOAT; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_double: public Type_handler_real_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_time: public Type_handler_temporal_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_date: public Type_handler_temporal_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_datetime: public Type_handler_temporal_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_timestamp: public Type_handler_temporal_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_olddecimal: public Type_handler_decimal_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_newdecimal: public Type_handler_decimal_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_null: public Type_handler_string_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_string: public Type_handler_string_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_varchar: public Type_handler_string_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_tiny_blob: public Type_handler_string_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_TINY_BLOB; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_medium_blob: public Type_handler_string_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_MEDIUM_BLOB; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_long_blob: public Type_handler_string_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_blob: public Type_handler_string_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_handler_geometry: public Type_handler_string_result
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
A handler for hybrid type functions, e.g.
|
||||||
|
COALESCE(), IF(), IFNULL(), NULLIF(), CASE,
|
||||||
|
numeric operators,
|
||||||
|
UNIX_TIMESTAMP(), TIME_TO_SEC().
|
||||||
|
|
||||||
|
Makes sure that field_type(), cmp_type() and result_type()
|
||||||
|
are always in sync to each other for hybrid functions.
|
||||||
|
*/
|
||||||
|
class Type_handler_hybrid_field_type: public Type_handler
|
||||||
|
{
|
||||||
|
const Type_handler *m_type_handler;
|
||||||
|
const Type_handler *get_handler_by_result_type(Item_result type) const;
|
||||||
|
const Type_handler *get_handler_by_field_type(enum_field_types type) const;
|
||||||
|
public:
|
||||||
|
Type_handler_hybrid_field_type();
|
||||||
|
enum_field_types field_type() const { return m_type_handler->field_type(); }
|
||||||
|
Item_result result_type() const { return m_type_handler->result_type(); }
|
||||||
|
Item_result cmp_type() const { return m_type_handler->cmp_type(); }
|
||||||
|
const Type_handler *set_handler_by_result_type(Item_result type)
|
||||||
|
{
|
||||||
|
return (m_type_handler= get_handler_by_result_type(type));
|
||||||
|
}
|
||||||
|
const Type_handler *set_handler_by_field_type(enum_field_types type)
|
||||||
|
{
|
||||||
|
return (m_type_handler= get_handler_by_field_type(type));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* SQL_TYPE_H_INCLUDED */
|
Reference in New Issue
Block a user