mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-12238 Add Type_handler::Item_func_{plus|minus|mul|div|mod}_fix_length_and_dec()
This commit is contained in:
@ -352,3 +352,56 @@ Note 1105 DBUG: types_compatible=yes bisect=yes
|
|||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
SET SESSION debug_dbug="-d,Predicant_to_list_comparator";
|
SET SESSION debug_dbug="-d,Predicant_to_list_comparator";
|
||||||
SET SESSION debug_dbug="-d,Item_func_in";
|
SET SESSION debug_dbug="-d,Item_func_in";
|
||||||
|
#
|
||||||
|
# MDEV-12238 Add Type_handler::Item_func_{plus|minus|mul|div|mod}_fix_length_and_dec()
|
||||||
|
#
|
||||||
|
SET debug_dbug='+d,num_op';
|
||||||
|
CREATE TABLE t1 AS SELECT
|
||||||
|
POINT(0,0)+POINT(0,0),
|
||||||
|
POINT(0,0)-POINT(0,0),
|
||||||
|
POINT(0,0)*POINT(0,0),
|
||||||
|
POINT(0,0)/POINT(0,0),
|
||||||
|
POINT(0,0) MOD POINT(0,0) LIMIT 0;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`POINT(0,0)+POINT(0,0)` geometry DEFAULT NULL,
|
||||||
|
`POINT(0,0)-POINT(0,0)` geometry DEFAULT NULL,
|
||||||
|
`POINT(0,0)*POINT(0,0)` geometry DEFAULT NULL,
|
||||||
|
`POINT(0,0)/POINT(0,0)` geometry DEFAULT NULL,
|
||||||
|
`POINT(0,0) MOD POINT(0,0)` geometry DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 AS SELECT
|
||||||
|
POINT(0,0)+'0',
|
||||||
|
POINT(0,0)-'0',
|
||||||
|
POINT(0,0)*'0',
|
||||||
|
POINT(0,0)/'0',
|
||||||
|
POINT(0,0) MOD '0' LIMIT 0;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`POINT(0,0)+'0'` longtext DEFAULT NULL,
|
||||||
|
`POINT(0,0)-'0'` longtext DEFAULT NULL,
|
||||||
|
`POINT(0,0)*'0'` longtext DEFAULT NULL,
|
||||||
|
`POINT(0,0)/'0'` longtext DEFAULT NULL,
|
||||||
|
`POINT(0,0) MOD '0'` longtext DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 AS SELECT
|
||||||
|
'0'+POINT(0,0),
|
||||||
|
'0'*POINT(0,0) LIMIT 0;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`'0'+POINT(0,0)` longtext DEFAULT NULL,
|
||||||
|
`'0'*POINT(0,0)` longtext DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 AS SELECT '0'-POINT(0,0) LIMIT 0;
|
||||||
|
ERROR HY000: Illegal parameter data types varchar and geometry for operation '-'
|
||||||
|
CREATE TABLE t1 AS SELECT '0'/POINT(0,0) LIMIT 0;
|
||||||
|
ERROR HY000: Illegal parameter data types varchar and geometry for operation '/'
|
||||||
|
CREATE TABLE t1 AS SELECT '0' MOD POINT(0,0) LIMIT 0;
|
||||||
|
ERROR HY000: Illegal parameter data types varchar and geometry for operation '%'
|
||||||
|
SET debug_dbug='-d,num_op';
|
||||||
|
@ -3837,5 +3837,70 @@ SELECT LENGTH(CAST(COALESCE(a) AS BINARY)) FROM t1;
|
|||||||
LENGTH(CAST(COALESCE(a) AS BINARY))
|
LENGTH(CAST(COALESCE(a) AS BINARY))
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
|
# MDEV-12238 Add Type_handler::Item_func_{plus|minus|mul|div|mod}_fix_length_and_dec()
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a GEOMETRY);
|
||||||
|
SELECT POINT(1,1) + 1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '+'
|
||||||
|
SELECT POINT(1,1) - 1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '-'
|
||||||
|
SELECT POINT(1,1) * 1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '*'
|
||||||
|
SELECT POINT(1,1) / 1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '/'
|
||||||
|
SELECT POINT(1,1) MOD 1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '%'
|
||||||
|
SELECT 1 + POINT(1,1);
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '+'
|
||||||
|
SELECT 1 - POINT(1,1);
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '-'
|
||||||
|
SELECT 1 * POINT(1,1);
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '*'
|
||||||
|
SELECT 1 / POINT(1,1);
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '/'
|
||||||
|
SELECT 1 MOD POINT(1,1);
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '%'
|
||||||
|
SELECT a + 1 FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '+'
|
||||||
|
SELECT a - 1 FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '-'
|
||||||
|
SELECT a * 1 FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '*'
|
||||||
|
SELECT a / 1 FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '/'
|
||||||
|
SELECT a MOD 1 FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '%'
|
||||||
|
SELECT 1 + a FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '+'
|
||||||
|
SELECT 1 - a FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '-'
|
||||||
|
SELECT 1 * a FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '*'
|
||||||
|
SELECT 1 / a FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '/'
|
||||||
|
SELECT 1 MOD a FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '%'
|
||||||
|
SELECT COALESCE(a) + 1 FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '+'
|
||||||
|
SELECT COALESCE(a) - 1 FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '-'
|
||||||
|
SELECT COALESCE(a) * 1 FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '*'
|
||||||
|
SELECT COALESCE(a) / 1 FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '/'
|
||||||
|
SELECT COALESCE(a) MOD 1 FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types geometry and bigint for operation '%'
|
||||||
|
SELECT 1 + COALESCE(a) FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '+'
|
||||||
|
SELECT 1 - COALESCE(a) FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '-'
|
||||||
|
SELECT 1 * COALESCE(a) FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '*'
|
||||||
|
SELECT 1 / COALESCE(a) FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '/'
|
||||||
|
SELECT 1 MOD COALESCE(a) FROM t1;
|
||||||
|
ERROR HY000: Illegal parameter data types bigint and geometry for operation '%'
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
# End of 10.3 tests
|
# End of 10.3 tests
|
||||||
#
|
#
|
||||||
|
@ -46,3 +46,68 @@ DROP TABLE t1;
|
|||||||
|
|
||||||
SET SESSION debug_dbug="-d,Predicant_to_list_comparator";
|
SET SESSION debug_dbug="-d,Predicant_to_list_comparator";
|
||||||
SET SESSION debug_dbug="-d,Item_func_in";
|
SET SESSION debug_dbug="-d,Item_func_in";
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-12238 Add Type_handler::Item_func_{plus|minus|mul|div|mod}_fix_length_and_dec()
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
# This tests is to check that operators '+' and '*' are commutative,
|
||||||
|
# while operators '/', '-' and 'MOD' are not commutative.
|
||||||
|
#
|
||||||
|
# It forces substitution of type_aggregator_for_{plus|minus|mul|div|mod} to
|
||||||
|
# type_aggregator_for_result / type_aggregator_non_commutative_test,
|
||||||
|
# which have pairs:
|
||||||
|
# (GEOMETRY,GEOMETRY)->GEOMETRY
|
||||||
|
# (GEOMETRY,VARCHAR)->GEOMETRY
|
||||||
|
# Note, they don't not have a pair:
|
||||||
|
# (VARCHAR,GEOMETRY)->GEOMETRY
|
||||||
|
#
|
||||||
|
# Commutative operators should work for all these argument type combinations:
|
||||||
|
# (GEOMETRY,GEOMETRY), (GEOMETRY,VARCHAR), (VARCHAR,GEOMETRY).
|
||||||
|
# Non-commutative operators should work for:
|
||||||
|
# (GEOMETRY,GEOMETRY), (GEOMETRY,VARCHAR),
|
||||||
|
# but should fail for (VARCHAR,GEOMETRY).
|
||||||
|
#
|
||||||
|
# Note, LIMIT 0 is needed to avoid calling str_op(), which does DBUG_ASSERT(0).
|
||||||
|
|
||||||
|
SET debug_dbug='+d,num_op';
|
||||||
|
|
||||||
|
# (GEOMETRY,GEOMETRY) gives GEOMETRY for all operators
|
||||||
|
CREATE TABLE t1 AS SELECT
|
||||||
|
POINT(0,0)+POINT(0,0),
|
||||||
|
POINT(0,0)-POINT(0,0),
|
||||||
|
POINT(0,0)*POINT(0,0),
|
||||||
|
POINT(0,0)/POINT(0,0),
|
||||||
|
POINT(0,0) MOD POINT(0,0) LIMIT 0;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
# (GEOMETRY,VARCHAR) gives GEOMETRY for all operators
|
||||||
|
CREATE TABLE t1 AS SELECT
|
||||||
|
POINT(0,0)+'0',
|
||||||
|
POINT(0,0)-'0',
|
||||||
|
POINT(0,0)*'0',
|
||||||
|
POINT(0,0)/'0',
|
||||||
|
POINT(0,0) MOD '0' LIMIT 0;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
# (VARCHAR,GEOMETRY) gives GEOMETRY for commutative operators
|
||||||
|
CREATE TABLE t1 AS SELECT
|
||||||
|
'0'+POINT(0,0),
|
||||||
|
'0'*POINT(0,0) LIMIT 0;
|
||||||
|
SHOW CREATE TABLE t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
# (VARCHAR,GEOMETRY) gives an error for non-commutative operators
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
CREATE TABLE t1 AS SELECT '0'-POINT(0,0) LIMIT 0;
|
||||||
|
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
CREATE TABLE t1 AS SELECT '0'/POINT(0,0) LIMIT 0;
|
||||||
|
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
CREATE TABLE t1 AS SELECT '0' MOD POINT(0,0) LIMIT 0;
|
||||||
|
|
||||||
|
SET debug_dbug='-d,num_op';
|
||||||
|
@ -2016,6 +2016,81 @@ SELECT LENGTH(CAST(COALESCE(a) AS BINARY)) FROM t1;
|
|||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-12238 Add Type_handler::Item_func_{plus|minus|mul|div|mod}_fix_length_and_dec()
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a GEOMETRY);
|
||||||
|
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT POINT(1,1) + 1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT POINT(1,1) - 1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT POINT(1,1) * 1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT POINT(1,1) / 1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT POINT(1,1) MOD 1;
|
||||||
|
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 + POINT(1,1);
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 - POINT(1,1);
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 * POINT(1,1);
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 / POINT(1,1);
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 MOD POINT(1,1);
|
||||||
|
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT a + 1 FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT a - 1 FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT a * 1 FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT a / 1 FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT a MOD 1 FROM t1;
|
||||||
|
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 + a FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 - a FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 * a FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 / a FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 MOD a FROM t1;
|
||||||
|
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT COALESCE(a) + 1 FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT COALESCE(a) - 1 FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT COALESCE(a) * 1 FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT COALESCE(a) / 1 FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT COALESCE(a) MOD 1 FROM t1;
|
||||||
|
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 + COALESCE(a) FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 - COALESCE(a) FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 * COALESCE(a) FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 / COALESCE(a) FROM t1;
|
||||||
|
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
|
||||||
|
SELECT 1 MOD COALESCE(a) FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # End of 10.3 tests
|
--echo # End of 10.3 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
191
sql/item_func.cc
191
sql/item_func.cc
@ -729,47 +729,31 @@ bool Item_func_connection_id::fix_fields(THD *thd, Item **ref)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
bool Item_num_op::fix_type_handler(const Type_aggregator *aggregator)
|
||||||
Check arguments here to determine result's type for a numeric
|
|
||||||
function of two arguments.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void Item_num_op::fix_length_and_dec(void)
|
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Item_num_op::fix_length_and_dec");
|
|
||||||
DBUG_PRINT("info", ("name %s", func_name()));
|
|
||||||
DBUG_ASSERT(arg_count == 2);
|
DBUG_ASSERT(arg_count == 2);
|
||||||
Item_result r0= args[0]->cast_to_int_type_handler()->cmp_type();
|
const Type_handler *h0= args[0]->cast_to_int_type_handler();
|
||||||
Item_result r1= args[1]->cast_to_int_type_handler()->cmp_type();
|
const Type_handler *h1= args[1]->cast_to_int_type_handler();
|
||||||
|
if (!aggregate_for_num_op(aggregator, h0, h1))
|
||||||
|
return false;
|
||||||
|
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
|
||||||
|
h0->name().ptr(), h1->name().ptr(), func_name());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (r0 == REAL_RESULT || r1 == REAL_RESULT ||
|
|
||||||
r0 == STRING_RESULT || r1 ==STRING_RESULT)
|
void Item_func_plus::fix_length_and_dec(void)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_func_plus::fix_length_and_dec");
|
||||||
|
DBUG_PRINT("info", ("name %s", func_name()));
|
||||||
|
const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_plus;
|
||||||
|
DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_for_result;);
|
||||||
|
DBUG_ASSERT(aggregator->is_commutative());
|
||||||
|
if (!fix_type_handler(aggregator))
|
||||||
{
|
{
|
||||||
count_real_length(args, arg_count);
|
Item_func_plus::type_handler()->Item_func_plus_fix_length_and_dec(this);
|
||||||
max_length= float_length(decimals);
|
DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
|
||||||
set_handler_by_result_type(REAL_RESULT);
|
|
||||||
}
|
}
|
||||||
else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT ||
|
|
||||||
r0 == TIME_RESULT || r1 == TIME_RESULT)
|
|
||||||
{
|
|
||||||
set_handler_by_result_type(DECIMAL_RESULT);
|
|
||||||
result_precision();
|
|
||||||
fix_decimals();
|
|
||||||
if ((r0 == TIME_RESULT || r1 == TIME_RESULT) && decimals == 0)
|
|
||||||
set_handler_by_result_type(INT_RESULT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
|
|
||||||
set_handler_by_result_type(INT_RESULT);
|
|
||||||
result_precision();
|
|
||||||
decimals= 0;
|
|
||||||
}
|
|
||||||
DBUG_PRINT("info", ("Type: %s",
|
|
||||||
(result_type() == REAL_RESULT ? "REAL_RESULT" :
|
|
||||||
result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
|
||||||
result_type() == INT_RESULT ? "INT_RESULT" :
|
|
||||||
"--ILLEGAL!!!--")));
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1299,11 +1283,6 @@ void Item_func_additive_op::result_precision()
|
|||||||
DBUG_ASSERT(arg1_int >= 0);
|
DBUG_ASSERT(arg1_int >= 0);
|
||||||
DBUG_ASSERT(arg2_int >= 0);
|
DBUG_ASSERT(arg2_int >= 0);
|
||||||
|
|
||||||
/* Integer operations keep unsigned_flag if one of arguments is unsigned */
|
|
||||||
if (result_type() == INT_RESULT)
|
|
||||||
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
|
|
||||||
else
|
|
||||||
unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
|
|
||||||
max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
|
max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
|
||||||
unsigned_flag);
|
unsigned_flag);
|
||||||
}
|
}
|
||||||
@ -1313,16 +1292,30 @@ void Item_func_additive_op::result_precision()
|
|||||||
The following function is here to allow the user to force
|
The following function is here to allow the user to force
|
||||||
subtraction of UNSIGNED BIGINT to return negative values.
|
subtraction of UNSIGNED BIGINT to return negative values.
|
||||||
*/
|
*/
|
||||||
|
void Item_func_minus::fix_unsigned_flag()
|
||||||
void Item_func_minus::fix_length_and_dec()
|
|
||||||
{
|
{
|
||||||
Item_num_op::fix_length_and_dec();
|
|
||||||
if (unsigned_flag &&
|
if (unsigned_flag &&
|
||||||
(current_thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
|
(current_thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
|
||||||
unsigned_flag=0;
|
unsigned_flag=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_func_minus::fix_length_and_dec()
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_func_minus::fix_length_and_dec");
|
||||||
|
DBUG_PRINT("info", ("name %s", func_name()));
|
||||||
|
const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_minus;
|
||||||
|
DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_non_commutative_test;);
|
||||||
|
DBUG_ASSERT(!aggregator->is_commutative());
|
||||||
|
if (!fix_type_handler(aggregator))
|
||||||
|
{
|
||||||
|
Item_func_minus::type_handler()->Item_func_minus_fix_length_and_dec(this);
|
||||||
|
DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
|
||||||
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
double Item_func_minus::real_op()
|
double Item_func_minus::real_op()
|
||||||
{
|
{
|
||||||
double value= args[0]->val_real() - args[1]->val_real();
|
double value= args[0]->val_real() - args[1]->val_real();
|
||||||
@ -1530,13 +1523,8 @@ my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value)
|
|||||||
|
|
||||||
void Item_func_mul::result_precision()
|
void Item_func_mul::result_precision()
|
||||||
{
|
{
|
||||||
/* Integer operations keep unsigned_flag if one of arguments is unsigned */
|
|
||||||
if (result_type() == INT_RESULT)
|
|
||||||
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
|
|
||||||
else
|
|
||||||
unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
|
|
||||||
decimals= MY_MIN(args[0]->decimal_scale() + args[1]->decimal_scale(),
|
decimals= MY_MIN(args[0]->decimal_scale() + args[1]->decimal_scale(),
|
||||||
DECIMAL_MAX_SCALE);
|
DECIMAL_MAX_SCALE);
|
||||||
uint est_prec = args[0]->decimal_precision() + args[1]->decimal_precision();
|
uint est_prec = args[0]->decimal_precision() + args[1]->decimal_precision();
|
||||||
uint precision= MY_MIN(est_prec, DECIMAL_MAX_PRECISION);
|
uint precision= MY_MIN(est_prec, DECIMAL_MAX_PRECISION);
|
||||||
max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
|
max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
|
||||||
@ -1544,6 +1532,22 @@ void Item_func_mul::result_precision()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_func_mul::fix_length_and_dec(void)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_func_mul::fix_length_and_dec");
|
||||||
|
DBUG_PRINT("info", ("name %s", func_name()));
|
||||||
|
const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_mul;
|
||||||
|
DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_for_result;);
|
||||||
|
DBUG_ASSERT(aggregator->is_commutative());
|
||||||
|
if (!fix_type_handler(aggregator))
|
||||||
|
{
|
||||||
|
Item_func_mul::type_handler()->Item_func_mul_fix_length_and_dec(this);
|
||||||
|
DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
|
||||||
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
double Item_func_div::real_op()
|
double Item_func_div::real_op()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
@ -1605,53 +1609,51 @@ void Item_func_div::result_precision()
|
|||||||
uint precision=MY_MIN(args[0]->decimal_precision() +
|
uint precision=MY_MIN(args[0]->decimal_precision() +
|
||||||
args[1]->divisor_precision_increment() + prec_increment,
|
args[1]->divisor_precision_increment() + prec_increment,
|
||||||
DECIMAL_MAX_PRECISION);
|
DECIMAL_MAX_PRECISION);
|
||||||
|
|
||||||
/* Integer operations keep unsigned_flag if one of arguments is unsigned */
|
|
||||||
if (result_type() == INT_RESULT)
|
|
||||||
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
|
|
||||||
else
|
|
||||||
unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
|
|
||||||
decimals= MY_MIN(args[0]->decimal_scale() + prec_increment, DECIMAL_MAX_SCALE);
|
decimals= MY_MIN(args[0]->decimal_scale() + prec_increment, DECIMAL_MAX_SCALE);
|
||||||
max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
|
max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
|
||||||
unsigned_flag);
|
unsigned_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Item_func_div::fix_length_and_dec()
|
void Item_func_div::fix_length_and_dec_double(void)
|
||||||
|
{
|
||||||
|
Item_num_op::fix_length_and_dec_double();
|
||||||
|
decimals= MY_MAX(args[0]->decimals, args[1]->decimals) + prec_increment;
|
||||||
|
set_if_smaller(decimals, NOT_FIXED_DEC);
|
||||||
|
uint tmp= float_length(decimals);
|
||||||
|
if (decimals == NOT_FIXED_DEC)
|
||||||
|
max_length= tmp;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
max_length=args[0]->max_length - args[0]->decimals + decimals;
|
||||||
|
set_if_smaller(max_length, tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_func_div::fix_length_and_dec_int(void)
|
||||||
|
{
|
||||||
|
set_handler(&type_handler_newdecimal);
|
||||||
|
DBUG_PRINT("info", ("Type changed: %s", type_handler()->name().ptr()));
|
||||||
|
Item_num_op::fix_length_and_dec_decimal();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Item_func_div::fix_length_and_dec(void)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Item_func_div::fix_length_and_dec");
|
DBUG_ENTER("Item_func_div::fix_length_and_dec");
|
||||||
|
DBUG_PRINT("info", ("name %s", func_name()));
|
||||||
prec_increment= current_thd->variables.div_precincrement;
|
prec_increment= current_thd->variables.div_precincrement;
|
||||||
Item_num_op::fix_length_and_dec();
|
|
||||||
switch (Item_func_div::result_type()) {
|
|
||||||
case REAL_RESULT:
|
|
||||||
{
|
|
||||||
decimals=MY_MAX(args[0]->decimals,args[1]->decimals)+prec_increment;
|
|
||||||
set_if_smaller(decimals, NOT_FIXED_DEC);
|
|
||||||
uint tmp=float_length(decimals);
|
|
||||||
if (decimals == NOT_FIXED_DEC)
|
|
||||||
max_length= tmp;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
max_length=args[0]->max_length - args[0]->decimals + decimals;
|
|
||||||
set_if_smaller(max_length,tmp);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case INT_RESULT:
|
|
||||||
set_handler_by_result_type(DECIMAL_RESULT);
|
|
||||||
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
|
|
||||||
result_precision();
|
|
||||||
break;
|
|
||||||
case DECIMAL_RESULT:
|
|
||||||
result_precision();
|
|
||||||
fix_decimals();
|
|
||||||
break;
|
|
||||||
case STRING_RESULT:
|
|
||||||
case ROW_RESULT:
|
|
||||||
case TIME_RESULT:
|
|
||||||
DBUG_ASSERT(0);
|
|
||||||
}
|
|
||||||
maybe_null= 1; // devision by zero
|
maybe_null= 1; // devision by zero
|
||||||
|
|
||||||
|
const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_div;
|
||||||
|
DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_non_commutative_test;);
|
||||||
|
DBUG_ASSERT(!aggregator->is_commutative());
|
||||||
|
if (!fix_type_handler(aggregator))
|
||||||
|
{
|
||||||
|
Item_func_div::type_handler()->Item_func_div_fix_length_and_dec(this);
|
||||||
|
DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
|
||||||
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1823,9 +1825,18 @@ void Item_func_mod::result_precision()
|
|||||||
|
|
||||||
void Item_func_mod::fix_length_and_dec()
|
void Item_func_mod::fix_length_and_dec()
|
||||||
{
|
{
|
||||||
Item_num_op::fix_length_and_dec();
|
DBUG_ENTER("Item_func_mod::fix_length_and_dec");
|
||||||
maybe_null= 1;
|
DBUG_PRINT("info", ("name %s", func_name()));
|
||||||
unsigned_flag= args[0]->unsigned_flag;
|
maybe_null= true; // division by zero
|
||||||
|
const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_mod;
|
||||||
|
DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_non_commutative_test;);
|
||||||
|
DBUG_ASSERT(!aggregator->is_commutative());
|
||||||
|
if (!fix_type_handler(aggregator))
|
||||||
|
{
|
||||||
|
Item_func_mod::type_handler()->Item_func_mod_fix_length_and_dec(this);
|
||||||
|
DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
|
||||||
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -695,7 +695,31 @@ class Item_num_op :public Item_func_numhybrid
|
|||||||
{
|
{
|
||||||
print_op(str, query_type);
|
print_op(str, query_type);
|
||||||
}
|
}
|
||||||
void fix_length_and_dec();
|
bool fix_type_handler(const Type_aggregator *aggregator);
|
||||||
|
void fix_length_and_dec_double()
|
||||||
|
{
|
||||||
|
count_real_length(args, arg_count);
|
||||||
|
max_length= float_length(decimals);
|
||||||
|
}
|
||||||
|
void fix_length_and_dec_decimal()
|
||||||
|
{
|
||||||
|
unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
|
||||||
|
result_precision();
|
||||||
|
fix_decimals();
|
||||||
|
}
|
||||||
|
void fix_length_and_dec_int()
|
||||||
|
{
|
||||||
|
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
|
||||||
|
result_precision();
|
||||||
|
decimals= 0;
|
||||||
|
}
|
||||||
|
void fix_length_and_dec_temporal()
|
||||||
|
{
|
||||||
|
set_handler(&type_handler_newdecimal);
|
||||||
|
fix_length_and_dec_decimal();
|
||||||
|
if (decimals == 0)
|
||||||
|
set_handler(&type_handler_longlong);
|
||||||
|
}
|
||||||
bool need_parentheses_in_default() { return true; }
|
bool need_parentheses_in_default() { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -949,6 +973,7 @@ public:
|
|||||||
Item_func_additive_op(thd, a, b) {}
|
Item_func_additive_op(thd, a, b) {}
|
||||||
const char *func_name() const { return "+"; }
|
const char *func_name() const { return "+"; }
|
||||||
enum precedence precedence() const { return ADD_PRECEDENCE; }
|
enum precedence precedence() const { return ADD_PRECEDENCE; }
|
||||||
|
void fix_length_and_dec();
|
||||||
longlong int_op();
|
longlong int_op();
|
||||||
double real_op();
|
double real_op();
|
||||||
my_decimal *decimal_op(my_decimal *);
|
my_decimal *decimal_op(my_decimal *);
|
||||||
@ -967,6 +992,22 @@ public:
|
|||||||
double real_op();
|
double real_op();
|
||||||
my_decimal *decimal_op(my_decimal *);
|
my_decimal *decimal_op(my_decimal *);
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
|
void fix_unsigned_flag();
|
||||||
|
void fix_length_and_dec_double()
|
||||||
|
{
|
||||||
|
Item_func_additive_op::fix_length_and_dec_double();
|
||||||
|
fix_unsigned_flag();
|
||||||
|
}
|
||||||
|
void fix_length_and_dec_decimal()
|
||||||
|
{
|
||||||
|
Item_func_additive_op::fix_length_and_dec_decimal();
|
||||||
|
fix_unsigned_flag();
|
||||||
|
}
|
||||||
|
void fix_length_and_dec_int()
|
||||||
|
{
|
||||||
|
Item_func_additive_op::fix_length_and_dec_int();
|
||||||
|
fix_unsigned_flag();
|
||||||
|
}
|
||||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||||
{ return get_item_copy<Item_func_minus>(thd, mem_root, this); }
|
{ return get_item_copy<Item_func_minus>(thd, mem_root, this); }
|
||||||
};
|
};
|
||||||
@ -983,6 +1024,7 @@ public:
|
|||||||
double real_op();
|
double real_op();
|
||||||
my_decimal *decimal_op(my_decimal *);
|
my_decimal *decimal_op(my_decimal *);
|
||||||
void result_precision();
|
void result_precision();
|
||||||
|
void fix_length_and_dec();
|
||||||
bool check_partition_func_processor(void *int_arg) {return FALSE;}
|
bool check_partition_func_processor(void *int_arg) {return FALSE;}
|
||||||
bool check_vcol_func_processor(void *arg) { return FALSE;}
|
bool check_vcol_func_processor(void *arg) { return FALSE;}
|
||||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||||
@ -1001,6 +1043,8 @@ public:
|
|||||||
const char *func_name() const { return "/"; }
|
const char *func_name() const { return "/"; }
|
||||||
enum precedence precedence() const { return MUL_PRECEDENCE; }
|
enum precedence precedence() const { return MUL_PRECEDENCE; }
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
|
void fix_length_and_dec_double();
|
||||||
|
void fix_length_and_dec_int();
|
||||||
void result_precision();
|
void result_precision();
|
||||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||||
{ return get_item_copy<Item_func_div>(thd, mem_root, this); }
|
{ return get_item_copy<Item_func_div>(thd, mem_root, this); }
|
||||||
@ -1040,6 +1084,22 @@ public:
|
|||||||
enum precedence precedence() const { return MUL_PRECEDENCE; }
|
enum precedence precedence() const { return MUL_PRECEDENCE; }
|
||||||
void result_precision();
|
void result_precision();
|
||||||
void fix_length_and_dec();
|
void fix_length_and_dec();
|
||||||
|
void fix_length_and_dec_double()
|
||||||
|
{
|
||||||
|
Item_num_op::fix_length_and_dec_double();
|
||||||
|
unsigned_flag= args[0]->unsigned_flag;
|
||||||
|
}
|
||||||
|
void fix_length_and_dec_decimal()
|
||||||
|
{
|
||||||
|
Item_num_op::fix_length_and_dec_decimal();
|
||||||
|
unsigned_flag= args[0]->unsigned_flag;
|
||||||
|
}
|
||||||
|
void fix_length_and_dec_int()
|
||||||
|
{
|
||||||
|
max_length= MY_MAX(args[0]->max_length, args[1]->max_length);
|
||||||
|
decimals= 0;
|
||||||
|
unsigned_flag= args[0]->unsigned_flag;
|
||||||
|
}
|
||||||
bool check_partition_func_processor(void *int_arg) {return FALSE;}
|
bool check_partition_func_processor(void *int_arg) {return FALSE;}
|
||||||
bool check_vcol_func_processor(void *arg) { return FALSE;}
|
bool check_vcol_func_processor(void *arg) { return FALSE;}
|
||||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||||
|
313
sql/sql_type.cc
313
sql/sql_type.cc
@ -60,6 +60,17 @@ Type_handler_geometry type_handler_geometry;
|
|||||||
bool Type_handler_data::init()
|
bool Type_handler_data::init()
|
||||||
{
|
{
|
||||||
#ifdef HAVE_SPATIAL
|
#ifdef HAVE_SPATIAL
|
||||||
|
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
if (m_type_aggregator_non_commutative_test.add(&type_handler_geometry,
|
||||||
|
&type_handler_geometry,
|
||||||
|
&type_handler_geometry) ||
|
||||||
|
m_type_aggregator_non_commutative_test.add(&type_handler_geometry,
|
||||||
|
&type_handler_varchar,
|
||||||
|
&type_handler_long_blob))
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
|
||||||
return
|
return
|
||||||
m_type_aggregator_for_result.add(&type_handler_geometry,
|
m_type_aggregator_for_result.add(&type_handler_geometry,
|
||||||
&type_handler_null,
|
&type_handler_null,
|
||||||
@ -466,6 +477,63 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Type_handler *
|
||||||
|
Type_handler::aggregate_for_num_op_traditional(const Type_handler *h0,
|
||||||
|
const Type_handler *h1)
|
||||||
|
{
|
||||||
|
Item_result r0= h0->cmp_type();
|
||||||
|
Item_result r1= h1->cmp_type();
|
||||||
|
|
||||||
|
if (r0 == REAL_RESULT || r1 == REAL_RESULT ||
|
||||||
|
r0 == STRING_RESULT || r1 ==STRING_RESULT)
|
||||||
|
return &type_handler_double;
|
||||||
|
|
||||||
|
if (r0 == TIME_RESULT || r1 == TIME_RESULT)
|
||||||
|
return &type_handler_datetime;
|
||||||
|
|
||||||
|
if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT)
|
||||||
|
return &type_handler_newdecimal;
|
||||||
|
|
||||||
|
DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
|
||||||
|
return &type_handler_longlong;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Type_aggregator::Pair*
|
||||||
|
Type_aggregator::find_pair(const Type_handler *handler1,
|
||||||
|
const Type_handler *handler2) const
|
||||||
|
{
|
||||||
|
for (uint i= 0; i < m_array.elements(); i++)
|
||||||
|
{
|
||||||
|
const Pair& el= m_array.at(i);
|
||||||
|
if (el.eq(handler1, handler2) ||
|
||||||
|
(m_is_commutative && el.eq(handler2, handler1)))
|
||||||
|
return ⪙
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Type_handler_hybrid_field_type::aggregate_for_num_op(const Type_aggregator *agg,
|
||||||
|
const Type_handler *h0,
|
||||||
|
const Type_handler *h1)
|
||||||
|
{
|
||||||
|
const Type_handler *hres;
|
||||||
|
if (h0->is_traditional_type() && h1->is_traditional_type())
|
||||||
|
{
|
||||||
|
set_handler(Type_handler::aggregate_for_num_op_traditional(h0, h1));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((hres= agg->find_handler(h0, h1)))
|
||||||
|
{
|
||||||
|
set_handler(hres);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
const Type_handler *
|
const Type_handler *
|
||||||
@ -2709,3 +2777,248 @@ bool Type_handler_geometry::
|
|||||||
#endif /* HAVE_SPATIAL */
|
#endif /* HAVE_SPATIAL */
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
|
bool Type_handler_row::
|
||||||
|
Item_func_plus_fix_length_and_dec(Item_func_plus *item) const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_int_result::
|
||||||
|
Item_func_plus_fix_length_and_dec(Item_func_plus *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_int();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_real_result::
|
||||||
|
Item_func_plus_fix_length_and_dec(Item_func_plus *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_double();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_decimal_result::
|
||||||
|
Item_func_plus_fix_length_and_dec(Item_func_plus *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_decimal();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_temporal_result::
|
||||||
|
Item_func_plus_fix_length_and_dec(Item_func_plus *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_temporal();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_string_result::
|
||||||
|
Item_func_plus_fix_length_and_dec(Item_func_plus *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_double();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
bool Type_handler_row::
|
||||||
|
Item_func_minus_fix_length_and_dec(Item_func_minus *item) const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_int_result::
|
||||||
|
Item_func_minus_fix_length_and_dec(Item_func_minus *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_int();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_real_result::
|
||||||
|
Item_func_minus_fix_length_and_dec(Item_func_minus *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_double();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_decimal_result::
|
||||||
|
Item_func_minus_fix_length_and_dec(Item_func_minus *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_decimal();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_temporal_result::
|
||||||
|
Item_func_minus_fix_length_and_dec(Item_func_minus *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_temporal();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_string_result::
|
||||||
|
Item_func_minus_fix_length_and_dec(Item_func_minus *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_double();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
bool Type_handler_row::
|
||||||
|
Item_func_mul_fix_length_and_dec(Item_func_mul *item) const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_int_result::
|
||||||
|
Item_func_mul_fix_length_and_dec(Item_func_mul *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_int();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_real_result::
|
||||||
|
Item_func_mul_fix_length_and_dec(Item_func_mul *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_double();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_decimal_result::
|
||||||
|
Item_func_mul_fix_length_and_dec(Item_func_mul *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_decimal();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_temporal_result::
|
||||||
|
Item_func_mul_fix_length_and_dec(Item_func_mul *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_temporal();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_string_result::
|
||||||
|
Item_func_mul_fix_length_and_dec(Item_func_mul *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_double();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
bool Type_handler_row::
|
||||||
|
Item_func_div_fix_length_and_dec(Item_func_div *item) const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_int_result::
|
||||||
|
Item_func_div_fix_length_and_dec(Item_func_div *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_int();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_real_result::
|
||||||
|
Item_func_div_fix_length_and_dec(Item_func_div *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_double();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_decimal_result::
|
||||||
|
Item_func_div_fix_length_and_dec(Item_func_div *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_decimal();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_temporal_result::
|
||||||
|
Item_func_div_fix_length_and_dec(Item_func_div *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_temporal();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_string_result::
|
||||||
|
Item_func_div_fix_length_and_dec(Item_func_div *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_double();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
|
||||||
|
bool Type_handler_row::
|
||||||
|
Item_func_mod_fix_length_and_dec(Item_func_mod *item) const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_int_result::
|
||||||
|
Item_func_mod_fix_length_and_dec(Item_func_mod *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_int();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_real_result::
|
||||||
|
Item_func_mod_fix_length_and_dec(Item_func_mod *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_double();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_decimal_result::
|
||||||
|
Item_func_mod_fix_length_and_dec(Item_func_mod *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_decimal();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_temporal_result::
|
||||||
|
Item_func_mod_fix_length_and_dec(Item_func_mod *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_temporal();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Type_handler_string_result::
|
||||||
|
Item_func_mod_fix_length_and_dec(Item_func_mod *item) const
|
||||||
|
{
|
||||||
|
item->fix_length_and_dec_double();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************/
|
||||||
|
@ -51,6 +51,11 @@ class Item_char_typecast;
|
|||||||
class Item_time_typecast;
|
class Item_time_typecast;
|
||||||
class Item_date_typecast;
|
class Item_date_typecast;
|
||||||
class Item_datetime_typecast;
|
class Item_datetime_typecast;
|
||||||
|
class Item_func_plus;
|
||||||
|
class Item_func_minus;
|
||||||
|
class Item_func_mul;
|
||||||
|
class Item_func_div;
|
||||||
|
class Item_func_mod;
|
||||||
class cmp_item;
|
class cmp_item;
|
||||||
class in_vector;
|
class in_vector;
|
||||||
class Type_std_attributes;
|
class Type_std_attributes;
|
||||||
@ -303,6 +308,9 @@ public:
|
|||||||
static const
|
static const
|
||||||
Type_handler *aggregate_for_result_traditional(const Type_handler *h1,
|
Type_handler *aggregate_for_result_traditional(const Type_handler *h1,
|
||||||
const Type_handler *h2);
|
const Type_handler *h2);
|
||||||
|
static const
|
||||||
|
Type_handler *aggregate_for_num_op_traditional(const Type_handler *h1,
|
||||||
|
const Type_handler *h2);
|
||||||
|
|
||||||
virtual const Name name() const= 0;
|
virtual const Name name() const= 0;
|
||||||
virtual enum_field_types field_type() const= 0;
|
virtual enum_field_types field_type() const= 0;
|
||||||
@ -497,6 +505,17 @@ public:
|
|||||||
Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const;
|
Item_date_typecast_fix_length_and_dec(Item_date_typecast *item) const;
|
||||||
virtual bool
|
virtual bool
|
||||||
Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item) const;
|
Item_datetime_typecast_fix_length_and_dec(Item_datetime_typecast *item) const;
|
||||||
|
|
||||||
|
virtual bool
|
||||||
|
Item_func_plus_fix_length_and_dec(Item_func_plus *func) const= 0;
|
||||||
|
virtual bool
|
||||||
|
Item_func_minus_fix_length_and_dec(Item_func_minus *func) const= 0;
|
||||||
|
virtual bool
|
||||||
|
Item_func_mul_fix_length_and_dec(Item_func_mul *func) const= 0;
|
||||||
|
virtual bool
|
||||||
|
Item_func_div_fix_length_and_dec(Item_func_div *func) const= 0;
|
||||||
|
virtual bool
|
||||||
|
Item_func_mod_fix_length_and_dec(Item_func_mod *func) const= 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -708,6 +727,12 @@ public:
|
|||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const;
|
||||||
|
bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const;
|
||||||
|
bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const;
|
||||||
|
bool Item_func_div_fix_length_and_dec(Item_func_div *) const;
|
||||||
|
bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -784,6 +809,11 @@ public:
|
|||||||
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
|
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
|
||||||
bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
|
bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
|
||||||
bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
|
bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
|
||||||
|
bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const;
|
||||||
|
bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const;
|
||||||
|
bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const;
|
||||||
|
bool Item_func_div_fix_length_and_dec(Item_func_div *) const;
|
||||||
|
bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -833,6 +863,11 @@ public:
|
|||||||
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
|
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
|
||||||
bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
|
bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
|
||||||
bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
|
bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
|
||||||
|
bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const;
|
||||||
|
bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const;
|
||||||
|
bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const;
|
||||||
|
bool Item_func_div_fix_length_and_dec(Item_func_div *) const;
|
||||||
|
bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -881,6 +916,11 @@ public:
|
|||||||
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
|
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
|
||||||
bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
|
bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
|
||||||
bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
|
bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
|
||||||
|
bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const;
|
||||||
|
bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const;
|
||||||
|
bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const;
|
||||||
|
bool Item_func_div_fix_length_and_dec(Item_func_div *) const;
|
||||||
|
bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -933,6 +973,11 @@ public:
|
|||||||
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
|
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
|
||||||
bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
|
bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
|
||||||
bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
|
bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
|
||||||
|
bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const;
|
||||||
|
bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const;
|
||||||
|
bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const;
|
||||||
|
bool Item_func_div_fix_length_and_dec(Item_func_div *) const;
|
||||||
|
bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -999,6 +1044,11 @@ public:
|
|||||||
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
|
bool Item_func_int_val_fix_length_and_dec(Item_func_int_val *) const;
|
||||||
bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
|
bool Item_func_abs_fix_length_and_dec(Item_func_abs *) const;
|
||||||
bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
|
bool Item_func_neg_fix_length_and_dec(Item_func_neg *) const;
|
||||||
|
bool Item_func_plus_fix_length_and_dec(Item_func_plus *) const;
|
||||||
|
bool Item_func_minus_fix_length_and_dec(Item_func_minus *) const;
|
||||||
|
bool Item_func_mul_fix_length_and_dec(Item_func_mul *) const;
|
||||||
|
bool Item_func_div_fix_length_and_dec(Item_func_div *) const;
|
||||||
|
bool Item_func_mod_fix_length_and_dec(Item_func_mod *) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1528,6 +1578,8 @@ public:
|
|||||||
bool aggregate_for_result(const Type_handler *other);
|
bool aggregate_for_result(const Type_handler *other);
|
||||||
bool aggregate_for_result(const char *funcname,
|
bool aggregate_for_result(const char *funcname,
|
||||||
Item **item, uint nitems, bool treat_bit_as_number);
|
Item **item, uint nitems, bool treat_bit_as_number);
|
||||||
|
bool aggregate_for_num_op(const class Type_aggregator *aggregator,
|
||||||
|
const Type_handler *h0, const Type_handler *h1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1547,6 +1599,7 @@ extern Type_handler_set type_handler_set;
|
|||||||
|
|
||||||
class Type_aggregator
|
class Type_aggregator
|
||||||
{
|
{
|
||||||
|
bool m_is_commutative;
|
||||||
class Pair
|
class Pair
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -1566,18 +1619,10 @@ class Type_aggregator
|
|||||||
};
|
};
|
||||||
Dynamic_array<Pair> m_array;
|
Dynamic_array<Pair> m_array;
|
||||||
const Pair* find_pair(const Type_handler *handler1,
|
const Pair* find_pair(const Type_handler *handler1,
|
||||||
const Type_handler *handler2) const
|
const Type_handler *handler2) const;
|
||||||
{
|
|
||||||
for (uint i= 0; i < m_array.elements(); i++)
|
|
||||||
{
|
|
||||||
const Pair& el= m_array.at(i);
|
|
||||||
if (el.eq(handler1, handler2) || el.eq(handler2, handler1))
|
|
||||||
return ⪙
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
public:
|
public:
|
||||||
Type_aggregator()
|
Type_aggregator(bool is_commutative= false)
|
||||||
|
:m_is_commutative(is_commutative)
|
||||||
{ }
|
{ }
|
||||||
bool add(const Type_handler *handler1,
|
bool add(const Type_handler *handler1,
|
||||||
const Type_handler *handler2,
|
const Type_handler *handler2,
|
||||||
@ -1591,14 +1636,35 @@ public:
|
|||||||
const Pair* el= find_pair(handler1, handler2);
|
const Pair* el= find_pair(handler1, handler2);
|
||||||
return el ? el->m_result : NULL;
|
return el ? el->m_result : NULL;
|
||||||
}
|
}
|
||||||
|
bool is_commutative() const { return m_is_commutative; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Type_aggregator_commutative: public Type_aggregator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Type_aggregator_commutative()
|
||||||
|
:Type_aggregator(true)
|
||||||
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Type_handler_data
|
class Type_handler_data
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Type_aggregator m_type_aggregator_for_result;
|
Type_aggregator_commutative m_type_aggregator_for_result;
|
||||||
Type_aggregator m_type_aggregator_for_comparison;
|
Type_aggregator_commutative m_type_aggregator_for_comparison;
|
||||||
|
|
||||||
|
Type_aggregator_commutative m_type_aggregator_for_plus;
|
||||||
|
Type_aggregator_commutative m_type_aggregator_for_mul;
|
||||||
|
|
||||||
|
Type_aggregator m_type_aggregator_for_minus;
|
||||||
|
Type_aggregator m_type_aggregator_for_div;
|
||||||
|
Type_aggregator m_type_aggregator_for_mod;
|
||||||
|
#ifndef DBUG_OFF
|
||||||
|
// This is used for mtr purposes in debug builds
|
||||||
|
Type_aggregator m_type_aggregator_non_commutative_test;
|
||||||
|
#endif
|
||||||
bool init();
|
bool init();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user