Commit 552072e4 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-12239 Add Type_handler::Item_sum_{sum|avg|variance}_fix_length_and_dec()

parent 7d0c354f
......@@ -3749,5 +3749,34 @@ ERROR HY000: Illegal parameter data type geometry for operation 'ceiling'
SELECT FLOOR(POINT(1,1));
ERROR HY000: Illegal parameter data type geometry for operation 'floor'
#
# MDEV-12239 Add Type_handler::Item_sum_{sum|avg|variance}_fix_length_and_dec()
#
CREATE TABLE t1 (a GEOMETRY);
SELECT SUM(POINT(1,1)) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'sum'
SELECT SUM(a) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'sum'
SELECT SUM(COALESCE(a)) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'sum'
SELECT AVG(POINT(1,1)) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'avg'
SELECT AVG(a) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'avg'
SELECT AVG(COALESCE(a)) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'avg'
SELECT VARIANCE(POINT(1,1)) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'variance('
SELECT VARIANCE(a) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'variance('
SELECT VARIANCE(COALESCE(a)) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'variance('
SELECT STDDEV(POINT(1,1)) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'std('
SELECT STDDEV(a) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'std('
SELECT STDDEV(COALESCE(a)) FROM t1;
ERROR HY000: Illegal parameter data type geometry for operation 'std('
DROP TABLE t1;
#
# End of 10.3 tests
#
......@@ -5263,9 +5263,7 @@ UNION ALL
SELECT coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
AS foo
;
coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
0.0000
0.0000
ERROR HY000: Illegal parameter data type geometry for operation 'avg'
CREATE table t1(a text);
INSERT INTO t1 VALUES (''), ('');
SELECT avg(distinct(t1.a)) FROM t1, t1 t2
......
......@@ -5274,9 +5274,7 @@ UNION ALL
SELECT coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
AS foo
;
coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
0.0000
0.0000
ERROR HY000: Illegal parameter data type geometry for operation 'avg'
CREATE table t1(a text);
INSERT INTO t1 VALUES (''), ('');
SELECT avg(distinct(t1.a)) FROM t1, t1 t2
......
......@@ -5263,9 +5263,7 @@ UNION ALL
SELECT coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
AS foo
;
coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
0.0000
0.0000
ERROR HY000: Illegal parameter data type geometry for operation 'avg'
CREATE table t1(a text);
INSERT INTO t1 VALUES (''), ('');
SELECT avg(distinct(t1.a)) FROM t1, t1 t2
......
......@@ -1915,6 +1915,44 @@ SELECT CEILING(POINT(1,1));
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT FLOOR(POINT(1,1));
--echo #
--echo # MDEV-12239 Add Type_handler::Item_sum_{sum|avg|variance}_fix_length_and_dec()
--echo #
CREATE TABLE t1 (a GEOMETRY);
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT SUM(POINT(1,1)) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT SUM(a) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT SUM(COALESCE(a)) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT AVG(POINT(1,1)) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT AVG(a) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT AVG(COALESCE(a)) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT VARIANCE(POINT(1,1)) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT VARIANCE(a) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT VARIANCE(COALESCE(a)) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT STDDEV(POINT(1,1)) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT STDDEV(a) FROM t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT STDDEV(COALESCE(a)) FROM t1;
DROP TABLE t1;
--echo #
--echo # End of 10.3 tests
--echo #
......@@ -4427,6 +4427,7 @@ DROP TABLE t1;
--echo # Bug #57203 Assertion `field_length <= 255' failed.
--echo #
--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
SELECT coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
UNION ALL
SELECT coalesce((avg(distinct (geomfromtext("point(25379 -22010)")))))
......
......@@ -1290,41 +1290,35 @@ void Item_sum_sum::clear()
}
void Item_sum_sum::fix_length_and_dec_double()
{
set_handler(&type_handler_double); // Change FLOAT to DOUBLE
decimals= args[0]->decimals;
sum= 0.0;
}
void Item_sum_sum::fix_length_and_dec_decimal()
{
set_handler(&type_handler_newdecimal); // Change temporal to new DECIMAL
decimals= args[0]->decimals;
/* SUM result can't be longer than length(arg) + length(MAX_ROWS) */
int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS;
max_length= my_decimal_precision_to_length_no_truncation(precision,
decimals,
unsigned_flag);
curr_dec_buff= 0;
my_decimal_set_zero(dec_buffs);
}
void Item_sum_sum::fix_length_and_dec()
{
DBUG_ENTER("Item_sum_sum::fix_length_and_dec");
maybe_null=null_value=1;
decimals= args[0]->decimals;
switch (args[0]->cast_to_int_type_handler()->cmp_type()) {
case REAL_RESULT:
case STRING_RESULT:
set_handler_by_field_type(MYSQL_TYPE_DOUBLE);
sum= 0.0;
break;
case INT_RESULT:
case TIME_RESULT:
case DECIMAL_RESULT:
{
/* SUM result can't be longer than length(arg) + length(MAX_ROWS) */
int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS;
max_length= my_decimal_precision_to_length_no_truncation(precision,
decimals,
unsigned_flag);
curr_dec_buff= 0;
set_handler_by_field_type(MYSQL_TYPE_NEWDECIMAL);
my_decimal_set_zero(dec_buffs);
break;
}
case ROW_RESULT:
DBUG_ASSERT(0);
}
DBUG_PRINT("info", ("Type: %s (%d, %d)",
(result_type() == REAL_RESULT ? "REAL_RESULT" :
result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
result_type() == INT_RESULT ? "INT_RESULT" :
"--ILLEGAL!!!--"),
max_length,
(int)decimals));
args[0]->cast_to_int_type_handler()->Item_sum_sum_fix_length_and_dec(this);
DBUG_PRINT("info", ("Type: %s (%d, %d)", type_handler()->name().ptr(),
max_length, (int) decimals));
DBUG_VOID_RETURN;
}
......@@ -1625,28 +1619,39 @@ void Item_sum_count::cleanup()
/*
Avgerage
*/
void Item_sum_avg::fix_length_and_dec_decimal()
{
Item_sum_sum::fix_length_and_dec_decimal();
int precision= args[0]->decimal_precision() + prec_increment;
decimals= MY_MIN(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
max_length= my_decimal_precision_to_length_no_truncation(precision,
decimals,
unsigned_flag);
f_precision= MY_MIN(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION);
f_scale= args[0]->decimals;
dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale);
}
void Item_sum_avg::fix_length_and_dec_double()
{
Item_sum_sum::fix_length_and_dec_double();
decimals= MY_MIN(args[0]->decimals + prec_increment,
FLOATING_POINT_DECIMALS);
max_length= MY_MIN(args[0]->max_length + prec_increment, float_length(decimals));
}
void Item_sum_avg::fix_length_and_dec()
{
Item_sum_sum::fix_length_and_dec();
maybe_null=null_value=1;
DBUG_ENTER("Item_sum_avg::fix_length_and_dec");
prec_increment= current_thd->variables.div_precincrement;
if (Item_sum_avg::result_type() == DECIMAL_RESULT)
{
int precision= args[0]->decimal_precision() + prec_increment;
decimals= MY_MIN(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
max_length= my_decimal_precision_to_length_no_truncation(precision,
decimals,
unsigned_flag);
f_precision= MY_MIN(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION);
f_scale= args[0]->decimals;
dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale);
}
else
{
decimals= MY_MIN(args[0]->decimals + prec_increment,
FLOATING_POINT_DECIMALS);
max_length= MY_MIN(args[0]->max_length + prec_increment, float_length(decimals));
}
maybe_null=null_value=1;
args[0]->cast_to_int_type_handler()->Item_sum_avg_fix_length_and_dec(this);
DBUG_PRINT("info", ("Type: %s (%d, %d)", type_handler()->name().ptr(),
max_length, (int) decimals));
DBUG_VOID_RETURN;
}
......@@ -1845,6 +1850,25 @@ Item_sum_variance::Item_sum_variance(THD *thd, Item_sum_variance *item):
}
void Item_sum_variance::fix_length_and_dec_double()
{
DBUG_ASSERT(Item_sum_variance::type_handler() == &type_handler_double);
decimals= MY_MIN(args[0]->decimals + 4, FLOATING_POINT_DECIMALS);
}
void Item_sum_variance::fix_length_and_dec_decimal()
{
DBUG_ASSERT(Item_sum_variance::type_handler() == &type_handler_double);
int precision= args[0]->decimal_precision() * 2 + prec_increment;
decimals= MY_MIN(args[0]->decimals + prec_increment,
FLOATING_POINT_DECIMALS - 1);
max_length= my_decimal_precision_to_length_no_truncation(precision,
decimals,
unsigned_flag);
}
void Item_sum_variance::fix_length_and_dec()
{
DBUG_ENTER("Item_sum_variance::fix_length_and_dec");
......@@ -1858,28 +1882,9 @@ void Item_sum_variance::fix_length_and_dec()
type.
*/
switch (args[0]->result_type()) {
case REAL_RESULT:
case STRING_RESULT:
decimals= MY_MIN(args[0]->decimals + 4, FLOATING_POINT_DECIMALS);
break;
case INT_RESULT:
case DECIMAL_RESULT:
{
int precision= args[0]->decimal_precision()*2 + prec_increment;
decimals= MY_MIN(args[0]->decimals + prec_increment,
FLOATING_POINT_DECIMALS-1);
max_length= my_decimal_precision_to_length_no_truncation(precision,
decimals,
unsigned_flag);
break;
}
case ROW_RESULT:
case TIME_RESULT:
DBUG_ASSERT(0);
}
DBUG_PRINT("info", ("Type: REAL_RESULT (%d, %d)", max_length, (int)decimals));
args[0]->type_handler()->Item_sum_variance_fix_length_and_dec(this);
DBUG_PRINT("info", ("Type: %s (%d, %d)", type_handler()->name().ptr(),
max_length, (int)decimals));
DBUG_VOID_RETURN;
}
......
......@@ -790,6 +790,8 @@ class Item_sum_sum :public Item_sum_num,
{ return Type_handler_hybrid_field_type::result_type(); }
enum Item_result cmp_type () const
{ return Type_handler_hybrid_field_type::cmp_type(); }
void fix_length_and_dec_double();
void fix_length_and_dec_decimal();
void reset_field();
void update_field();
void no_rows_in_result() {}
......@@ -889,6 +891,8 @@ class Item_sum_avg :public Item_sum_sum
:Item_sum_sum(thd, item), count(item->count),
prec_increment(item->prec_increment) {}
void fix_length_and_dec_double();
void fix_length_and_dec_decimal();
void fix_length_and_dec();
enum Sumfunctype sum_func () const
{
......@@ -963,6 +967,8 @@ class Item_sum_variance : public Item_sum_num
{}
Item_sum_variance(THD *thd, Item_sum_variance *item);
enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
void fix_length_and_dec_double();
void fix_length_and_dec_decimal();
void clear();
bool add();
double val_real();
......
......@@ -1398,6 +1398,166 @@ bool Type_handler_temporal_result::
return false;
}
/*************************************************************************/
bool Type_handler_int_result::
Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const
{
item->fix_length_and_dec_decimal();
return false;
}
bool Type_handler_decimal_result::
Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const
{
item->fix_length_and_dec_decimal();
return false;
}
bool Type_handler_temporal_result::
Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const
{
item->fix_length_and_dec_decimal();
return false;
}
bool Type_handler_real_result::
Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const
{
item->fix_length_and_dec_double();
return false;
}
bool Type_handler_string_result::
Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const
{
item->fix_length_and_dec_double();
return false;
}
#ifdef HAVE_SPATIAL
bool Type_handler_geometry::
Item_sum_sum_fix_length_and_dec(Item_sum_sum *item) const
{
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
type_handler_geometry.name().ptr(), "sum");
return false;
}
#endif
/*************************************************************************/
bool Type_handler_int_result::
Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const
{
item->fix_length_and_dec_decimal();
return false;
}
bool Type_handler_decimal_result::
Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const
{
item->fix_length_and_dec_decimal();
return false;
}
bool Type_handler_temporal_result::
Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const
{
item->fix_length_and_dec_decimal();
return false;
}
bool Type_handler_real_result::
Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const
{
item->fix_length_and_dec_double();
return false;
}
bool Type_handler_string_result::
Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const
{
item->fix_length_and_dec_double();
return false;
}
#ifdef HAVE_SPATIAL
bool Type_handler_geometry::
Item_sum_avg_fix_length_and_dec(Item_sum_avg *item) const
{
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
type_handler_geometry.name().ptr(), "avg");
return false;
}
#endif
/*************************************************************************/
bool Type_handler_int_result::
Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const
{
item->fix_length_and_dec_decimal();
return false;
}
bool Type_handler_decimal_result::
Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const
{
item->fix_length_and_dec_decimal();
return false;
}
bool Type_handler_temporal_result::
Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const
{
item->fix_length_and_dec_decimal();
return false;
}
bool Type_handler_real_result::
Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const
{
item->fix_length_and_dec_double();
return false;
}
bool Type_handler_string_result::
Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const
{
item->fix_length_and_dec_double();
return false;
}
#ifdef HAVE_SPATIAL
bool Type_handler_geometry::
Item_sum_variance_fix_length_and_dec(Item_sum_variance *item) const
{
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION, MYF(0),
type_handler_geometry.name().ptr(), item->func_name());
return false;
}
#endif
/*************************************************************************/
String *
......
......@@ -28,6 +28,9 @@ class Field;
class Item;
class Item_cache;
class Item_sum_hybrid;
class Item_sum_sum;
class Item_sum_avg;
class Item_sum_variance;
class Item_func_hex;
class Item_hybrid_func;
class Item_func_min_max;
......@@ -403,6 +406,11 @@ class Type_handler
Item **items,
uint nitems) const= 0;
virtual bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const= 0;
virtual bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const= 0;
virtual bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const= 0;
virtual
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const= 0;
virtual String *Item_func_hex_val_str_ascii(Item_func_hex *item,
String *str) const= 0;
......@@ -540,6 +548,21 @@ class Type_handler_row: public Type_handler
DBUG_ASSERT(0);
return true;
}
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const
{
DBUG_ASSERT(0);
return true;
}
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const
{
DBUG_ASSERT(0);
return true;
}
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const
{
DBUG_ASSERT(0);
return true;
}
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const
{
DBUG_ASSERT(0);
......@@ -662,6 +685,9 @@ class Type_handler_real_result: public Type_handler_numeric
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
String *) const;
......@@ -709,6 +735,9 @@ class Type_handler_decimal_result: public Type_handler_numeric
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
String *) const;
......@@ -754,6 +783,9 @@ class Type_handler_int_result: public Type_handler_numeric
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
String *) const;
......@@ -799,6 +831,9 @@ class Type_handler_temporal_result: public Type_handler
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
String *) const;
......@@ -860,6 +895,9 @@ class Type_handler_string_result: public Type_handler
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Item **items, uint nitems) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
String *Item_func_hex_val_str_ascii(Item_func_hex *item, String *str) const;
String *Item_func_hybrid_field_type_val_str(Item_func_hybrid_field_type *,
String *) const;
......@@ -1307,6 +1345,9 @@ class Type_handler_geometry: public Type_handler_string_result
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_neg_fix_length_and_dec(Item_func_neg *) const;
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
};
extern Type_handler_geometry type_handler_geometry;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment