diff options
-rw-r--r-- | mysql-test/r/view.result | 17 | ||||
-rw-r--r-- | mysql-test/t/view.test | 18 | ||||
-rw-r--r-- | sql/item.h | 12 | ||||
-rw-r--r-- | sql/item_func.cc | 10 | ||||
-rw-r--r-- | sql/item_func.h | 39 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 2 | ||||
-rw-r--r-- | sql/item_strfunc.h | 2 | ||||
-rw-r--r-- | sql/item_sum.cc | 22 | ||||
-rw-r--r-- | sql/item_sum.h | 46 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 4 | ||||
-rw-r--r-- | sql/item_timefunc.h | 3 | ||||
-rw-r--r-- | sql/item_uniq.h | 2 |
12 files changed, 136 insertions, 41 deletions
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 84be086ae37..b178af1bb1c 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1726,3 +1726,20 @@ sum(a) drop procedure p1; drop view v1; drop table t1; +create table t1 (s1 int); +create view v1 as select sum(distinct s1) from t1; +select * from v1; +sum(distinct s1) +NULL +drop view v1; +create view v1 as select avg(distinct s1) from t1; +select * from v1; +avg(distinct s1) +NULL +drop view v1; +drop table t1; +create view v1 as select cast(1 as decimal); +select * from v1; +cast(1 as decimal) +1.00 +drop view v1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 0477ab0ea20..23d482254d1 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1569,3 +1569,21 @@ drop procedure p1; drop view v1; drop table t1; +# +# using sum(distinct ) & avg(distinct ) in views (BUG#7015) +# +create table t1 (s1 int); +create view v1 as select sum(distinct s1) from t1; +select * from v1; +drop view v1; +create view v1 as select avg(distinct s1) from t1; +select * from v1; +drop view v1; +drop table t1; + +# +# using cast(... as decimal) in views (BUG#11387); +# +create view v1 as select cast(1 as decimal); +select * from v1; +drop view v1; diff --git a/sql/item.h b/sql/item.h index 5ff2c726afd..6a1490a19d5 100644 --- a/sql/item.h +++ b/sql/item.h @@ -468,6 +468,18 @@ public: */ virtual bool const_during_execution() const { return (used_tables() & ~PARAM_TABLE_BIT) == 0; } + /* + This is an essential method for correct functioning of VIEWS. + To save a view in an .frm file we need its unequivocal + definition in SQL that takes into account sql_mode and + environmental settings. Currently such definition is restored + by traversing through the parsed tree of a view and + print()'ing SQL syntax of every node to a String buffer. This + method is used to print the SQL definition of an item. The + second use of this method is for EXPLAIN EXTENDED, to print + the SQL of a query after all optimizations of the parsed tree + have been done. + */ virtual void print(String *str_arg) { str_arg->append(full_name()); } void print_item_w_name(String *); virtual void update_used_tables() {} diff --git a/sql/item_func.cc b/sql/item_func.cc index 71620a68c34..4166605ae11 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1061,6 +1061,14 @@ my_decimal *Item_decimal_typecast::val_decimal(my_decimal *dec) } +void Item_decimal_typecast::print(String *str) +{ + str->append("cast(", 5); + args[0]->print(str); + str->append(" as decimal)", 12); +} + + double Item_func_plus::real_op() { double value= args[0]->val_real() + args[1]->val_real(); @@ -4111,7 +4119,7 @@ bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const return 1; // Same item is same. /* Check if other type is also a get_user_var() object */ if (item->type() != FUNC_ITEM || - ((Item_func*) item)->func_name() != func_name()) + ((Item_func*) item)->functype() != functype()) return 0; Item_func_get_user_var *other=(Item_func_get_user_var*) item; return (name.length == other->name.length && diff --git a/sql/item_func.h b/sql/item_func.h index 1ac1449760f..e0f14ceac75 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -54,7 +54,8 @@ public: SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN, NOT_FUNC, NOT_ALL_FUNC, NOW_FUNC, TRIG_COND_FUNC, - GUSERVAR_FUNC}; + GUSERVAR_FUNC, COLLATE_FUNC, + EXTRACT_FUNC, CHAR_TYPECAST_FUNC }; enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL, OPTIMIZE_EQUAL }; enum Type type() const { return FUNC_ITEM; } @@ -123,7 +124,17 @@ public: virtual optimize_type select_optimize() const { return OPTIMIZE_NONE; } virtual bool have_rev_func() const { return 0; } virtual Item *key_item() const { return args[0]; } - virtual const char *func_name() const { return "?"; } + /* + This method is used for debug purposes to print the name of an + item to the debug log. The second use of this method is as + a helper function of print(), where it is applicable. + To suit both goals it should return a meaningful, + distinguishable and sintactically correct string. This method + should not be used for runtime type identification, use enum + {Sum}Functype and Item_func::functype()/Item_sum::sum_func() + instead. + */ + virtual const char *func_name() const= 0; virtual bool const_item() const { return const_item_cache; } inline Item **arguments() const { return args; } void set_arguments(List<Item> &list); @@ -306,6 +317,8 @@ public: enum Item_result result_type () const { return DECIMAL_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; } void fix_length_and_dec() {}; + const char *func_name() const { return "decimal_typecast"; } + void print(String *); }; @@ -506,7 +519,7 @@ public: class Item_func_acos :public Item_dec_func { - public: +public: Item_func_acos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "acos"; } @@ -514,7 +527,7 @@ class Item_func_acos :public Item_dec_func class Item_func_asin :public Item_dec_func { - public: +public: Item_func_asin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "asin"; } @@ -522,7 +535,7 @@ class Item_func_asin :public Item_dec_func class Item_func_atan :public Item_dec_func { - public: +public: Item_func_atan(Item *a) :Item_dec_func(a) {} Item_func_atan(Item *a,Item *b) :Item_dec_func(a,b) {} double val_real(); @@ -531,7 +544,7 @@ class Item_func_atan :public Item_dec_func class Item_func_cos :public Item_dec_func { - public: +public: Item_func_cos(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "cos"; } @@ -539,7 +552,7 @@ class Item_func_cos :public Item_dec_func class Item_func_sin :public Item_dec_func { - public: +public: Item_func_sin(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "sin"; } @@ -547,7 +560,7 @@ class Item_func_sin :public Item_dec_func class Item_func_tan :public Item_dec_func { - public: +public: Item_func_tan(Item *a) :Item_dec_func(a) {} double val_real(); const char *func_name() const { return "tan"; } @@ -634,7 +647,7 @@ class Item_func_units :public Item_real_func { char *name; double mul,add; - public: +public: Item_func_units(char *name_arg,Item *a,double mul_arg,double add_arg) :Item_real_func(a),name(name_arg),mul(mul_arg),add(add_arg) {} double val_real(); @@ -853,7 +866,7 @@ public: class Item_func_benchmark :public Item_int_func { ulong loop_count; - public: +public: Item_func_benchmark(ulong loop_count_arg,Item *expr) :Item_int_func(expr), loop_count(loop_count_arg) {} @@ -868,7 +881,7 @@ class Item_func_benchmark :public Item_int_func class Item_udf_func :public Item_func { - protected: +protected: udf_handler udf; public: @@ -1046,7 +1059,7 @@ class Item_func_get_lock :public Item_int_func class Item_func_release_lock :public Item_int_func { String value; - public: +public: Item_func_release_lock(Item *a) :Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "release_lock"; } @@ -1058,7 +1071,7 @@ class Item_func_release_lock :public Item_int_func class Item_master_pos_wait :public Item_int_func { String value; - public: +public: Item_master_pos_wait(Item *a,Item *b) :Item_int_func(a,b) {} Item_master_pos_wait(Item *a,Item *b,Item *c) :Item_int_func(a,b,c) {} longlong val_int(); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 539bed58e66..9f7a44f6f47 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2297,7 +2297,7 @@ bool Item_func_set_collation::eq(const Item *item, bool binary_cmp) const return 0; Item_func *item_func=(Item_func*) item; if (arg_count != item_func->arg_count || - func_name() != item_func->func_name()) + functype() != item_func->functype()) return 0; Item_func_set_collation *item_func_sc=(Item_func_set_collation*) item; if (collation.collation != item_func_sc->collation.collation) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 6df90cebdff..8d2eb269915 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -573,6 +573,7 @@ public: max_length=args[0]->max_length; } void print(String *str); + const char *func_name() const { return "cast_as_binary"; } }; @@ -648,6 +649,7 @@ public: void fix_length_and_dec(); bool eq(const Item *item, bool binary_cmp) const; const char *func_name() const { return "collate"; } + enum Functype func_type() const { return COLLATE_FUNC; } void print(String *str); Item_field *filed_for_view_update() { diff --git a/sql/item_sum.cc b/sql/item_sum.cc index f7a158ceb5a..76f94801b49 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -86,7 +86,6 @@ void Item_sum::make_field(Send_field *tmp_field) void Item_sum::print(String *str) { str->append(func_name()); - str->append('('); for (uint i=0 ; i < arg_count ; i++) { if (i) @@ -2425,13 +2424,6 @@ longlong Item_sum_count_distinct::val_int() } -void Item_sum_count_distinct::print(String *str) -{ - str->append("count(distinct ", 15); - args[0]->print(str); - str->append(')'); -} - /**************************************************************************** ** Functions to handle dynamic loadable aggregates ** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su> @@ -2466,6 +2458,20 @@ void Item_udf_sum::cleanup() } +void Item_udf_sum::print(String *str) +{ + str->append(func_name()); + str->append('('); + for (uint i=0 ; i < arg_count ; i++) + { + if (i) + str->append(','); + args[i]->print(str); + } + str->append(')'); +} + + Item *Item_sum_udf_float::copy_or_same(THD* thd) { return new (thd->mem_root) Item_sum_udf_float(thd, this); diff --git a/sql/item_sum.h b/sql/item_sum.h index bb5d31b4b4f..b9a90ee5de5 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -81,7 +81,22 @@ public: virtual void update_field()=0; virtual bool keep_field_type(void) const { return 0; } virtual void fix_length_and_dec() { maybe_null=1; null_value=1; } - virtual const char *func_name() const { return "?"; } + /* + This method is used for debug purposes to print the name of an + item to the debug log. The second use of this method is as + a helper function of print(), where it is applicable. + To suit both goals it should return a meaningful, + distinguishable and sintactically correct string. This method + should not be used for runtime type identification, use enum + {Sum}Functype and Item_func::functype()/Item_sum::sum_func() + instead. + + NOTE: for Items inherited from Item_sum, func_name() return part of + function name till first argument (including '(') to make difference in + names for functions with 'distinct' clause and without 'distinct' and + also to make printing of items inherited from Item_sum uniform. + */ + virtual const char *func_name() const= 0; virtual Item *result_item(Field *field) { return new Item_field(field);} table_map used_tables() const { return ~(table_map) 0; } /* Not used */ @@ -159,7 +174,7 @@ public: void reset_field(); void update_field(); void no_rows_in_result() {} - const char *func_name() const { return "sum"; } + const char *func_name() const { return "sum("; } Item *copy_or_same(THD* thd); }; @@ -200,7 +215,6 @@ public: enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; } void reset_field() {} // not used void update_field() {} // not used - const char *func_name() const { return "sum_distinct"; } virtual void no_rows_in_result() {} void fix_length_and_dec(); enum Item_result result_type () const { return val.traits->type(); } @@ -224,7 +238,7 @@ public: Item_sum_sum_distinct(Item *item_arg) :Item_sum_distinct(item_arg) {} enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; } - const char *func_name() const { return "sum_distinct"; } + const char *func_name() const { return "sum(distinct "; } Item *copy_or_same(THD* thd) { return new Item_sum_sum_distinct(thd, this); } }; @@ -243,7 +257,7 @@ public: void fix_length_and_dec(); virtual void calculate_val_and_count(); enum Sumfunctype sum_func () const { return AVG_DISTINCT_FUNC; } - const char *func_name() const { return "avg_distinct"; } + const char *func_name() const { return "avg(distinct "; } Item *copy_or_same(THD* thd) { return new Item_sum_avg_distinct(thd, this); } }; @@ -272,7 +286,7 @@ class Item_sum_count :public Item_sum_int void reset_field(); void cleanup(); void update_field(); - const char *func_name() const { return "count"; } + const char *func_name() const { return "count("; } Item *copy_or_same(THD* thd); }; @@ -326,12 +340,11 @@ public: longlong val_int(); void reset_field() { return ;} // Never called void update_field() { return ; } // Never called - const char *func_name() const { return "count_distinct"; } + const char *func_name() const { return "count(distinct "; } bool setup(THD *thd); void make_unique(); Item *copy_or_same(THD* thd); void no_rows_in_result() {} - void print(String *str); }; @@ -389,7 +402,7 @@ public: Item *result_item(Field *field) { return new Item_avg_field(hybrid_type, this); } void no_rows_in_result() {} - const char *func_name() const { return "avg"; } + const char *func_name() const { return "avg("; } Item *copy_or_same(THD* thd); Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); }; @@ -466,7 +479,7 @@ public: Item *result_item(Field *field) { return new Item_variance_field(this); } void no_rows_in_result() {} - const char *func_name() const { return "variance"; } + const char *func_name() const { return "variance("; } Item *copy_or_same(THD* thd); Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); enum Item_result result_type () const { return hybrid_type; } @@ -501,7 +514,7 @@ class Item_sum_std :public Item_sum_variance double val_real(); Item *result_item(Field *field) { return new Item_std_field(this); } - const char *func_name() const { return "std"; } + const char *func_name() const { return "std("; } Item *copy_or_same(THD* thd); enum Item_result result_type () const { return REAL_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE;} @@ -565,7 +578,7 @@ public: enum Sumfunctype sum_func () const {return MIN_FUNC;} bool add(); - const char *func_name() const { return "min"; } + const char *func_name() const { return "min("; } Item *copy_or_same(THD* thd); }; @@ -578,7 +591,7 @@ public: enum Sumfunctype sum_func () const {return MAX_FUNC;} bool add(); - const char *func_name() const { return "max"; } + const char *func_name() const { return "max("; } Item *copy_or_same(THD* thd); }; @@ -609,7 +622,7 @@ public: Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} Item_sum_or(THD *thd, Item_sum_or *item) :Item_sum_bit(thd, item) {} bool add(); - const char *func_name() const { return "bit_or"; } + const char *func_name() const { return "bit_or("; } Item *copy_or_same(THD* thd); }; @@ -620,7 +633,7 @@ class Item_sum_and :public Item_sum_bit Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ULONGLONG_MAX) {} Item_sum_and(THD *thd, Item_sum_and *item) :Item_sum_bit(thd, item) {} bool add(); - const char *func_name() const { return "bit_and"; } + const char *func_name() const { return "bit_and("; } Item *copy_or_same(THD* thd); }; @@ -630,7 +643,7 @@ class Item_sum_xor :public Item_sum_bit Item_sum_xor(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} Item_sum_xor(THD *thd, Item_sum_xor *item) :Item_sum_bit(thd, item) {} bool add(); - const char *func_name() const { return "bit_xor"; } + const char *func_name() const { return "bit_xor("; } Item *copy_or_same(THD* thd); }; @@ -668,6 +681,7 @@ public: void reset_field() {}; void update_field() {}; void cleanup(); + void print(String *str); }; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 564c5e4b9cc..19386c15835 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2158,7 +2158,7 @@ bool Item_extract::eq(const Item *item, bool binary_cmp) const if (this == item) return 1; if (item->type() != FUNC_ITEM || - func_name() != ((Item_func*)item)->func_name()) + functype() != ((Item_func*)item)->functype()) return 0; Item_extract* ie= (Item_extract*)item; @@ -2176,7 +2176,7 @@ bool Item_char_typecast::eq(const Item *item, bool binary_cmp) const if (this == item) return 1; if (item->type() != FUNC_ITEM || - func_name() != ((Item_func*)item)->func_name()) + functype() != ((Item_func*)item)->functype()) return 0; Item_char_typecast *cast= (Item_char_typecast*)item; diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index c8fb2b39836..5c172b4698b 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -637,6 +637,7 @@ class Item_extract :public Item_int_func Item_extract(interval_type type_arg, Item *a) :Item_int_func(a), int_type(type_arg) {} longlong val_int(); + enum Functype functype() const { return EXTRACT_FUNC; } const char *func_name() const { return "extract"; } void fix_length_and_dec(); bool eq(const Item *item, bool binary_cmp) const; @@ -689,6 +690,7 @@ class Item_char_typecast :public Item_typecast public: Item_char_typecast(Item *a, int length_arg, CHARSET_INFO *cs_arg) :Item_typecast(a), cast_length(length_arg), cast_cs(cs_arg) {} + enum Functype functype() const { return CHAR_TYPECAST_FUNC; } bool eq(const Item *item, bool binary_cmp) const; const char *func_name() const { return "cast_as_char"; } const char* cast_type() const { return "char"; }; @@ -790,6 +792,7 @@ public: return (new Field_string(max_length, maybe_null, name, t_arg, &my_charset_bin)); } void print(String *str); + const char *func_name() const { return "add_time"; } }; class Item_func_timediff :public Item_str_func diff --git a/sql/item_uniq.h b/sql/item_uniq.h index 14b2e8d53bb..e95aa35101e 100644 --- a/sql/item_uniq.h +++ b/sql/item_uniq.h @@ -30,6 +30,7 @@ public: double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; } void fix_length_and_dec() { decimals=0; max_length=6; } void print(String *str) { str->append("0.0", 3); } + const char *func_name() const { return "unique_users"; } }; @@ -58,4 +59,5 @@ public: } void print(String *str) { str->append("0.0", 3); } Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); + const char *func_name() const { return "sum_unique_users"; } }; |