summaryrefslogtreecommitdiff
path: root/sql/item_sum.h
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2015-10-08 19:19:21 +0400
committerAlexander Barkov <bar@mariadb.org>2015-10-08 19:19:21 +0400
commit7091b7852d27e6c8a1875b2acc0d1adbfb29984f (patch)
treef21b02377c02ecda4bde859d843a72d36e072f70 /sql/item_sum.h
parent174a0b9eb70d33965677d375472db0694f6047fd (diff)
downloadmariadb-git-7091b7852d27e6c8a1875b2acc0d1adbfb29984f.tar.gz
MDEV-8918 Wrong result for CAST(AVG(bigint_column) AS SIGNED)
- Moving Item_xxx_field declarations after Item_sum_xxx declarations, so Item_xxx_field constructors can be defined directly in item_sum.h rather than item_sum.cc. This removes some duplicate code, e.g. initialization of the following members at constructor time: name, decimals, max_length, unsigned_flag, field, maybe_null. - Adding Item_sum_field as a common parent for Item_avg_field and Item_variance_field - Deriving Item_sum_field directly from Item rather that Item_result_field, as Item_sum_field descendants do not need anything from Item_result_field. - Removing hybrid infrastructure from Item_avg_field, adding Item_avg_field_decimal and Item_avg_field_double instead, as desired result type is already known at constructor time (not only at fix_fields time). This simplifies the code. - Changing Item_avg_field_decimal::val_int() to call val_int_from_decimal() instead of doing { return (longlong) rint(val_real()); } This is the fix itself.
Diffstat (limited to 'sql/item_sum.h')
-rw-r--r--sql/item_sum.h177
1 files changed, 111 insertions, 66 deletions
diff --git a/sql/item_sum.h b/sql/item_sum.h
index ce50c07a5e0..9cfbc6ca40b 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -820,37 +820,6 @@ class Item_sum_count :public Item_sum_int
};
-/* Item to get the value of a stored sum function */
-
-class Item_sum_avg;
-
-class Item_avg_field :public Item_result_field
-{
- Field *field;
- Item_result hybrid_type;
- uint f_precision, f_scale, dec_bin_size;
- uint prec_increment;
-public:
- Item_avg_field(THD *thd, Item_result res_type, Item_sum_avg *item);
- enum Type type() const { return FIELD_AVG_ITEM; }
- double val_real();
- longlong val_int();
- my_decimal *val_decimal(my_decimal *);
- bool is_null() { update_null_value(); return null_value; }
- String *val_str(String*);
- enum_field_types field_type() const
- {
- return hybrid_type == DECIMAL_RESULT ?
- MYSQL_TYPE_NEWDECIMAL : MYSQL_TYPE_DOUBLE;
- }
- enum Item_result result_type () const { return hybrid_type; }
- bool check_vcol_func_processor(uchar *int_arg)
- {
- return trace_unsupported_by_check_vcol_func_processor("avg_field");
- }
-};
-
-
class Item_sum_avg :public Item_sum_sum
{
public:
@@ -894,31 +863,6 @@ public:
}
};
-class Item_sum_variance;
-
-class Item_variance_field :public Item_result_field
-{
- Field *field;
- uint sample;
-public:
- Item_variance_field(THD *thd, Item_sum_variance *item);
- enum Type type() const {return FIELD_VARIANCE_ITEM; }
- double val_real();
- longlong val_int()
- { /* can't be fix_fields()ed */ return (longlong) rint(val_real()); }
- String *val_str(String *str)
- { return val_string_from_real(str); }
- my_decimal *val_decimal(my_decimal *dec_buf)
- { return val_decimal_from_real(dec_buf); }
- bool is_null() { update_null_value(); return null_value; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
- enum Item_result result_type () const { return REAL_RESULT; }
- bool check_vcol_func_processor(uchar *int_arg)
- {
- return trace_unsupported_by_check_vcol_func_processor("var_field");
- }
-};
-
/*
variance(a) =
@@ -977,16 +921,6 @@ public:
}
};
-class Item_sum_std;
-
-class Item_std_field :public Item_variance_field
-{
-public:
- Item_std_field(THD *thd, Item_sum_std *item);
- enum Type type() const { return FIELD_STD_ITEM; }
- double val_real();
-};
-
/*
standard_deviation(a) = sqrt(variance(a))
*/
@@ -1144,6 +1078,117 @@ class Item_sum_xor :public Item_sum_bit
};
+/* Items to get the value of a stored sum function */
+
+class Item_sum_field :public Item
+{
+protected:
+ Field *field;
+public:
+ Item_sum_field(THD *thd, Item_sum *item)
+ :Item(thd), field(item->result_field)
+ {
+ name= item->name;
+ maybe_null= true;
+ decimals= item->decimals;
+ max_length= item->max_length;
+ unsigned_flag= item->unsigned_flag;
+ }
+ table_map used_tables() const { return (table_map) 1L; }
+ Field *get_tmp_table_field() { DBUG_ASSERT(0); return NULL; }
+ Field *tmp_table_field(TABLE *) { DBUG_ASSERT(0); return NULL; }
+ void set_result_field(Field *) { DBUG_ASSERT(0); }
+ void save_in_result_field(bool no_conversions) { DBUG_ASSERT(0); }
+};
+
+
+class Item_avg_field :public Item_sum_field
+{
+protected:
+ uint prec_increment;
+public:
+ Item_avg_field(THD *thd, Item_sum_avg *item)
+ :Item_sum_field(thd, item), prec_increment(item->prec_increment)
+ { }
+ enum Type type() const { return FIELD_AVG_ITEM; }
+ bool is_null() { update_null_value(); return null_value; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("avg_field");
+ }
+};
+
+
+class Item_avg_field_double :public Item_avg_field
+{
+public:
+ Item_avg_field_double(THD *thd, Item_sum_avg *item)
+ :Item_avg_field(thd, item)
+ { }
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ enum Item_result result_type () const { return REAL_RESULT; }
+ longlong val_int() { return (longlong) rint(val_real()); }
+ my_decimal *val_decimal(my_decimal *dec) { return val_decimal_from_real(dec); }
+ String *val_str(String *str) { return val_string_from_real(str); }
+ double val_real();
+};
+
+
+class Item_avg_field_decimal :public Item_avg_field
+{
+ uint f_precision, f_scale, dec_bin_size;
+public:
+ Item_avg_field_decimal(THD *thd, Item_sum_avg *item)
+ :Item_avg_field(thd, item),
+ f_precision(item->f_precision),
+ f_scale(item->f_scale),
+ dec_bin_size(item->dec_bin_size)
+ { }
+ enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
+ enum Item_result result_type () const { return DECIMAL_RESULT; }
+ double val_real() { return val_real_from_decimal(); }
+ longlong val_int() { return val_int_from_decimal(); }
+ String *val_str(String *str) { return val_string_from_decimal(str); }
+ my_decimal *val_decimal(my_decimal *);
+};
+
+
+class Item_variance_field :public Item_sum_field
+{
+ uint sample;
+public:
+ Item_variance_field(THD *thd, Item_sum_variance *item)
+ :Item_sum_field(thd, item), sample(item->sample)
+ { }
+ enum Type type() const {return FIELD_VARIANCE_ITEM; }
+ double val_real();
+ longlong val_int()
+ { /* can't be fix_fields()ed */ return (longlong) rint(val_real()); }
+ String *val_str(String *str)
+ { return val_string_from_real(str); }
+ my_decimal *val_decimal(my_decimal *dec_buf)
+ { return val_decimal_from_real(dec_buf); }
+ bool is_null() { update_null_value(); return null_value; }
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ enum Item_result result_type () const { return REAL_RESULT; }
+ bool check_vcol_func_processor(uchar *int_arg)
+ {
+ return trace_unsupported_by_check_vcol_func_processor("var_field");
+ }
+};
+
+
+class Item_std_field :public Item_variance_field
+{
+public:
+ Item_std_field(THD *thd, Item_sum_std *item)
+ :Item_variance_field(thd, item)
+ { }
+ enum Type type() const { return FIELD_STD_ITEM; }
+ double val_real();
+};
+
+
/*
User defined aggregates
*/