diff options
-rw-r--r-- | mysql-test/r/group_by.result | 18 | ||||
-rw-r--r-- | mysql-test/t/group_by.test | 22 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 43 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 2 | ||||
-rw-r--r-- | sql/item_func.cc | 11 | ||||
-rw-r--r-- | sql/item_func.h | 1 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 39 | ||||
-rw-r--r-- | sql/item_strfunc.h | 6 | ||||
-rw-r--r-- | sql/mysql_priv.h | 2 | ||||
-rw-r--r-- | sql/sql_db.cc | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 24 | ||||
-rw-r--r-- | sql/sql_show.cc | 2 | ||||
-rw-r--r-- | sql/table.cc | 24 |
13 files changed, 174 insertions, 22 deletions
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 35867cf6532..167b7b8ef1f 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -529,3 +529,21 @@ table type possible_keys key key_len ref rows Extra t1 ALL NULL NULL NULL NULL 6 Using temporary t2 ALL a NULL NULL NULL 4 Using where drop table t1,t2; +a MAX(b) INTERVAL (MAX(b), 1,3,10,30,39,40,50,60,100,1000) +1 4 2 +10 43 6 +a MAX(b) CASE MAX(b) when 4 then 4 when 43 then 43 else 0 end +1 4 4 +10 43 43 +a MAX(b) FIELD(MAX(b), '43', '4', '5') +1 4 2 +10 43 1 +a MAX(b) CONCAT_WS(MAX(b), '43', '4', '5') +1 4 434445 +10 43 43434435 +a MAX(b) ELT(MAX(b), 'a', 'b', 'c', 'd', 'e', 'f') +1 4 d +10 43 NULL +a MAX(b) MAKE_SET(MAX(b), 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h') +1 4 c +10 43 a,b,d,f diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 98b1ee238b1..e54c32d0beb 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -386,3 +386,25 @@ select t1.a,t2.b from t1,t2 where t1.a=t2.a group by t1.a,t2.b ORDER BY NULL; explain select t1.a,t2.b from t1,t2 where t1.a=t2.a group by t1.a,t2.b; explain select t1.a,t2.b from t1,t2 where t1.a=t2.a group by t1.a,t2.b ORDER BY NULL; drop table t1,t2; + +# +# group function arguments in some functions +# + +create table t1 (a int, b int); +insert into t1 values (1, 4); +insert into t1 values (10, 40); +insert into t1 values (1, 4); +insert into t1 values (10, 43); +insert into t1 values (1, 4); +insert into t1 values (10, 41); +insert into t1 values (1, 4); +insert into t1 values (10, 43); +insert into t1 values (1, 4); +select a, MAX(b), INTERVAL (MAX(b), 1,3,10,30,39,40,50,60,100,1000) from t1 group by a; +select a, MAX(b), CASE MAX(b) when 4 then 4 when 43 then 43 else 0 end from t1 group by a; +select a, MAX(b), FIELD(MAX(b), '43', '4', '5') from t1 group by a; +select a, MAX(b), CONCAT_WS(MAX(b), '43', '4', '5') from t1 group by a; +select a, MAX(b), ELT(MAX(b), 'a', 'b', 'c', 'd', 'e', 'f') from t1 group by a; +select a, MAX(b), MAKE_SET(MAX(b), 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h') from t1 group by a; +drop table t1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 2a363164656..55e8ef7c4b5 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -293,6 +293,19 @@ void Item_func_interval::fix_length_and_dec() } maybe_null=0; max_length=2; used_tables_cache|=item->used_tables(); + with_sum_func= with_sum_func || item->with_sum_func; +} + +void Item_func_interval::split_sum_func(List<Item> &fields) +{ + if (item->with_sum_func && item->type() != SUM_FUNC_ITEM) + item->split_sum_func(fields); + else if (item->used_tables() || item->type() == SUM_FUNC_ITEM) + { + fields.push_front(item); + item= new Item_ref((Item**) fields.head_ref(), 0, item->name); + } + Item_int_func::split_sum_func(fields); } /* @@ -781,17 +794,45 @@ Item_func_case::fix_fields(THD *thd,TABLE_LIST *tables) { used_tables_cache|=(first_expr)->used_tables(); const_item_cache&= (first_expr)->const_item(); + with_sum_func= with_sum_func || (first_expr)->with_sum_func; } if (else_expr) { used_tables_cache|=(else_expr)->used_tables(); const_item_cache&= (else_expr)->const_item(); + with_sum_func= with_sum_func || (else_expr)->with_sum_func; } if (!else_expr || else_expr->maybe_null) maybe_null=1; // The result may be NULL return 0; } +void Item_func_case::split_sum_func(List<Item> &fields) +{ + if (first_expr) + { + if (first_expr->with_sum_func && first_expr->type() != SUM_FUNC_ITEM) + first_expr->split_sum_func(fields); + else if (first_expr->used_tables() || first_expr->type() == SUM_FUNC_ITEM) + { + fields.push_front(first_expr); + first_expr= new Item_ref((Item**) fields.head_ref(), 0, + first_expr->name); + } + } + if (else_expr) + { + if (else_expr->with_sum_func && else_expr->type() != SUM_FUNC_ITEM) + else_expr->split_sum_func(fields); + else if (else_expr->used_tables() || else_expr->type() == SUM_FUNC_ITEM) + { + fields.push_front(else_expr); + else_expr= new Item_ref((Item**) fields.head_ref(), 0, else_expr->name); + } + } + Item_func::split_sum_func(fields); +} + void Item_func_case::update_used_tables() { Item_func::update_used_tables(); @@ -1081,7 +1122,7 @@ void Item_func_in::split_sum_func(List<Item> &fields) else if (item->used_tables() || item->type() == SUM_FUNC_ITEM) { fields.push_front(item); - item=new Item_ref((Item**) fields.head_ref(),0,item->name); + item= new Item_ref((Item**) fields.head_ref(), 0, item->name); } Item_func::split_sum_func(fields); } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index d9068e0e024..aaa15f415e7 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -184,6 +184,7 @@ public: { return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); } + void split_sum_func(List<Item> &fields); void fix_length_and_dec(); ~Item_func_interval() { delete item; } const char *func_name() const { return "interval"; } @@ -273,6 +274,7 @@ public: const char *func_name() const { return "case"; } void print(String *str); bool fix_fields(THD *thd,struct st_table_list *tlist); + void split_sum_func(List<Item> &fields); Item *find_item(String *str); unsigned int size_of() { return sizeof(*this);} }; diff --git a/sql/item_func.cc b/sql/item_func.cc index 02ae03b217f..ef629098d2a 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -971,6 +971,17 @@ longlong Item_func_field::val_int() return 0; } +void Item_func_field::split_sum_func(List<Item> &fields) +{ + if (item->with_sum_func && item->type() != SUM_FUNC_ITEM) + item->split_sum_func(fields); + else if (item->used_tables() || item->type() == SUM_FUNC_ITEM) + { + fields.push_front(item); + item= new Item_ref((Item**) fields.head_ref(), 0, item->name); + } + Item_func::split_sum_func(fields); +} longlong Item_func_ascii::val_int() { diff --git a/sql/item_func.h b/sql/item_func.h index be8ae6b57c8..68e5335dc7e 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -585,6 +585,7 @@ public: { return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); } + void split_sum_func(List<Item> &fields); void update_used_tables() { item->update_used_tables() ; Item_func::update_used_tables(); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1d058a7d810..f1e37889d5f 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -587,6 +587,17 @@ null: return 0; } +void Item_func_concat_ws::split_sum_func(List<Item> &fields) +{ + if (separator->with_sum_func && separator->type() != SUM_FUNC_ITEM) + separator->split_sum_func(fields); + else if (separator->used_tables() || separator->type() == SUM_FUNC_ITEM) + { + fields.push_front(separator); + separator= new Item_ref((Item**) fields.head_ref(), 0, separator->name); + } + Item_str_func::split_sum_func(fields); +} void Item_func_concat_ws::fix_length_and_dec() { @@ -600,6 +611,7 @@ void Item_func_concat_ws::fix_length_and_dec() } used_tables_cache|=separator->used_tables(); const_item_cache&=separator->const_item(); + with_sum_func= with_sum_func || separator->with_sum_func; } void Item_func_concat_ws::update_used_tables() @@ -1501,6 +1513,19 @@ void Item_func_elt::fix_length_and_dec() } +void Item_func_elt::split_sum_func(List<Item> &fields) +{ + if (item->with_sum_func && item->type() != SUM_FUNC_ITEM) + item->split_sum_func(fields); + else if (item->used_tables() || item->type() == SUM_FUNC_ITEM) + { + fields.push_front(item); + item= new Item_ref((Item**) fields.head_ref(), 0, item->name); + } + Item_str_func::split_sum_func(fields); +} + + void Item_func_elt::update_used_tables() { Item_func::update_used_tables(); @@ -1547,6 +1572,19 @@ String *Item_func_elt::val_str(String *str) } +void Item_func_make_set::split_sum_func(List<Item> &fields) +{ + if (item->with_sum_func && item->type() != SUM_FUNC_ITEM) + item->split_sum_func(fields); + else if (item->used_tables() || item->type() == SUM_FUNC_ITEM) + { + fields.push_front(item); + item= new Item_ref((Item**) fields.head_ref(), 0, item->name); + } + Item_str_func::split_sum_func(fields); +} + + void Item_func_make_set::fix_length_and_dec() { max_length=arg_count-1; @@ -1554,6 +1592,7 @@ void Item_func_make_set::fix_length_and_dec() max_length+=args[i]->max_length; used_tables_cache|=item->used_tables(); const_item_cache&=item->const_item(); + with_sum_func= with_sum_func || item->with_sum_func; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 181aa8fb6ba..5c9706ed633 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -108,8 +108,8 @@ public: return (separator->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); } - const char *func_name() const { return "concat_ws"; } - unsigned int size_of() { return sizeof(*this);} + void split_sum_func(List<Item> &fields); + const char *func_name() const { return "concat_ws"; } }; class Item_func_reverse :public Item_str_func @@ -368,6 +368,7 @@ public: { return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); } + void split_sum_func(List<Item> &fields); void fix_length_and_dec(); void update_used_tables(); const char *func_name() const { return "elt"; } @@ -388,6 +389,7 @@ public: { return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist)); } + void split_sum_func(List<Item> &fields); void fix_length_and_dec(); void update_used_tables(); const char *func_name() const { return "make_set"; } diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index ae536618e76..2afc4a5754e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -789,7 +789,7 @@ int create_frm(char *name,uint reclength,uchar *fileinfo, HA_CREATE_INFO *create_info, uint keys); void update_create_info_from_table(HA_CREATE_INFO *info, TABLE *form); int rename_file_ext(const char * from,const char * to,const char * ext); -bool check_db_name(const char *db); +bool check_db_name(char *db); bool check_column_name(const char *name); bool check_table_name(const char *name, uint length); char *get_field(MEM_ROOT *mem,TABLE *table,uint fieldnr); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 4cb46c00bed..900c87d83a5 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -351,8 +351,6 @@ bool mysql_change_db(THD *thd,const char *name) x_free(dbname); DBUG_RETURN(1); } - if (lower_case_table_names) - casedn_str(dbname); DBUG_PRINT("info",("Use database: %s", dbname)); if (test_all_bits(thd->master_access,DB_ACLS)) db_access=DB_ACLS; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index df35e41556c..130f3ead5c7 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000-2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -828,16 +828,19 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) table_list->real_name = table_list->alias = tbl_name; table_list->lock_type = TL_READ_NO_INSERT; table_list->next = 0; - remove_escape(table_list->real_name); - - if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT))) - DBUG_RETURN(1); if (!db || check_db_name(db)) { net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL"); goto err; } + if (lower_case_table_names) + casedn_str(tbl_name); + remove_escape(tbl_name); + + if (!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT))) + DBUG_RETURN(1); + if (check_access(thd, SELECT_ACL, db, &table_list->grant.privilege)) goto err; if (grant_option && check_grant(thd, SELECT_ACL, table_list)) @@ -1059,6 +1062,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1))) break; mysql_log.write(thd,command,"%s %s",table_list.real_name,fields); + if (lower_case_table_names) + casedn_str(table_list.real_name); remove_escape(table_list.real_name); // This can't have wildcards if (check_access(thd,SELECT_ACL,table_list.db,&thd->col_access)) @@ -1088,8 +1093,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL"); break; } - if (lower_case_table_names) - casedn_str(db); if (check_access(thd,CREATE_ACL,db,0,1)) break; mysql_log.write(thd,command,packet); @@ -1106,8 +1109,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd, net_printf(&thd->net,ER_WRONG_DB_NAME, db ? db : "NULL"); break; } - if (lower_case_table_names) - casedn_str(db); if (check_access(thd,DROP_ACL,db,0,1)) break; if (thd->locked_tables || thd->active_transaction()) @@ -2277,8 +2278,6 @@ mysql_execute_command(void) net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); break; } - if (lower_case_table_names) - casedn_str(lex->name); /* If in a slave thread : DROP DATABASE DB may not be preceded by USE DB. @@ -3246,10 +3245,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, ptr->alias= alias_str; if (lower_case_table_names) - { - casedn_str(ptr->db); casedn_str(table->table.str); - } ptr->real_name=table->table.str; ptr->real_name_length=table->table.length; ptr->lock_type= lock_type; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 50ee78c1ebc..4faee7d248f 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -308,6 +308,8 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild) net_store_data(packet,convert, file_name); table_list.db=(char*) db; table_list.real_name= table_list.alias= file_name; + if (lower_case_table_names) + casedn_str(file_name); if (!(table = open_ltable(thd, &table_list, TL_READ))) { for (uint i=0 ; i < field_list.elements ; i++) diff --git a/sql/table.cc b/sql/table.cc index 7e284c89871..9eaea728007 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1100,9 +1100,29 @@ char *get_field(MEM_ROOT *mem, TABLE *table, uint fieldnr) return to; } -bool check_db_name(const char *name) + +/* + Check if database name is valid + + SYNPOSIS + check_db_name() + name Name of database + + NOTES + If lower_case_table_names is set then database is converted to lower case + + RETURN + 0 ok + 1 error +*/ + +bool check_db_name(char *name) { - const char *start=name; + char *start=name; + + if (lower_case_table_names) + casedn_str(name); + while (*name) { #if defined(USE_MB) && defined(USE_MB_IDENT) |