From: Date: June 21 2005 7:27am Subject: bk commit into 5.0 tree (bell:1.1958) BUG#7448 List-Archive: http://lists.mysql.com/internals/26221 X-Bug: 7448 Message-Id: <20050621052713.5666C455D84@sanja.is.com.ua> Below is the list of changes that have just been committed into a local 5.0 repository of bell. When bell does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet 1.1958 05/06/21 08:27:05 bell@stripped +8 -0 fixed view fields names check and generation (changed after Trudy review: underlying field names treat as user set ones) (BUG#7448) sql/sql_yacc.yy 1.400 05/06/21 08:27:00 bell@stripped +6 -5 add flag indicates that name of item was auto-generated and so can be changed in view sql/sql_view.cc 1.48 05/06/21 08:27:00 bell@stripped +71 -5 fixed view field dublicates check: 1) used case system charset/collation to compare view filds 2) in case if duplicate field was auto-generated we build unique name sql/sql_show.cc 1.253 05/06/21 08:27:00 bell@stripped +9 -9 add flag indicates that name of item was auto-generated and so can be changed in view sql/item_func.cc 1.223 05/06/21 08:27:00 bell@stripped +3 -2 add flag indicates that name of item was auto-generated and so can be changed in view sql/item.h 1.141 05/06/21 08:27:00 bell@stripped +8 -5 add flag indicates that name of item was auto-generated and so can be changed in view sql/item.cc 1.137 05/06/21 08:27:00 bell@stripped +4 -2 add flag indicates that name of item was auto-generated and so can be changed in view mysql-test/t/view.test 1.72 05/06/21 08:27:00 bell@stripped +53 -0 test of view field names generation mysql-test/r/view.result 1.83 05/06/21 08:27:00 bell@stripped +55 -0 test of view field names generation # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: bell # Host: sanja.is.com.ua # Root: /home/bell/mysql/bk/work-bug4-5.0 --- 1.136/sql/item.cc Wed Jun 15 16:58:52 2005 +++ 1.137/sql/item.cc Tue Jun 21 08:27:00 2005 @@ -314,7 +314,7 @@ Item::Item(): rsize(0), name(0), orig_name(0), name_length(0), fixed(0), - collation(&my_charset_bin, DERIVATION_COERCIBLE) + autogenerated_name(TRUE), collation(&my_charset_bin, DERIVATION_COERCIBLE) { marker= 0; maybe_null=null_value=with_sum_func=unsigned_flag=0; @@ -544,8 +544,10 @@ } -void Item::set_name(const char *str, uint length, CHARSET_INFO *cs) +void Item::set_name(const char *str, uint length, CHARSET_INFO *cs, + bool generated) { + autogenerated_name= generated; if (!length) { /* Empty string, used by AS or internal function like last_insert_id() */ --- 1.140/sql/item.h Fri Jun 17 20:30:06 2005 +++ 1.141/sql/item.h Tue Jun 21 08:27:00 2005 @@ -269,6 +269,8 @@ my_bool unsigned_flag; my_bool with_sum_func; my_bool fixed; /* If item fixed with fix_fields */ + my_bool autogenerated_name; /* indicate was name of this Item + autogenerated or set by user */ DTCollation collation; // alloc & destruct is done as start of select using sql_alloc @@ -288,7 +290,8 @@ name=0; #endif } /*lint -e1509 */ - void set_name(const char *str,uint length, CHARSET_INFO *cs); + void set_name(const char *str, uint length, CHARSET_INFO *cs, + bool generated); void rename(char *new_name); void init_make_field(Send_field *tmp_field,enum enum_field_types type); virtual void cleanup(); @@ -642,9 +645,9 @@ Item *it= this_item(); if (name) - it->set_name(name, (uint) strlen(name), system_charset_info); + it->set_name(name, (uint) strlen(name), system_charset_info, TRUE); else - it->set_name(m_name.str, m_name.length, system_charset_info); + it->set_name(m_name.str, m_name.length, system_charset_info, TRUE); it->make_field(field); } @@ -1159,7 +1162,7 @@ divide the max_length with mbmaxlen). */ max_length= str_value.numchars()*cs->mbmaxlen; - set_name(str, length, cs); + set_name(str, length, cs, TRUE); decimals=NOT_FIXED_DEC; // it is constant => can be used without fix_fields (and frequently used) fixed= 1; @@ -1170,7 +1173,7 @@ collation.set(cs, dv); str_value.set_or_copy_aligned(str,length,cs); max_length= str_value.numchars()*cs->mbmaxlen; - set_name(name_par,0,cs); + set_name(name_par, 0, cs, TRUE); decimals=NOT_FIXED_DEC; // it is constant => can be used without fix_fields (and frequently used) fixed= 1; --- 1.222/sql/item_func.cc Fri Jun 17 20:30:06 2005 +++ 1.223/sql/item_func.cc Tue Jun 21 08:27:00 2005 @@ -4601,7 +4601,7 @@ pos+= base_name->length; // set_name() will allocate the name - item->set_name(buff,(uint) (pos-buff), system_charset_info); + item->set_name(buff,(uint) (pos-buff), system_charset_info, TRUE); return item; } @@ -4620,7 +4620,8 @@ if (!(item=var->item(thd, var_type, &null_lex_string))) return 0; // Impossible thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - item->set_name(item_name, 0, system_charset_info); // Will use original name + item->set_name(item_name, 0, system_charset_info, + TRUE); // Will use original name return item; } --- 1.252/sql/sql_show.cc Thu Jun 16 11:27:17 2005 +++ 1.253/sql/sql_show.cc Tue Jun 21 08:27:00 2005 @@ -3197,7 +3197,7 @@ } item->max_length= fields_info->field_length * cs->mbmaxlen; item->set_name(fields_info->field_name, - strlen(fields_info->field_name), cs); + strlen(fields_info->field_name), cs, TRUE); break; } field_list.push_back(item); @@ -3249,7 +3249,7 @@ { field->set_name(field_info->old_name, strlen(field_info->old_name), - system_charset_info); + system_charset_info, TRUE); if (add_item_to_list(thd, field)) return 1; } @@ -3280,7 +3280,7 @@ buffer.append(lex->wild->ptr()); buffer.append(")"); } - field->set_name(buffer.ptr(), buffer.length(), system_charset_info); + field->set_name(buffer.ptr(), buffer.length(), system_charset_info, TRUE); } return 0; } @@ -3305,16 +3305,16 @@ Item_field *field= new Item_field(NullS, NullS, field_info->field_name); if (add_item_to_list(thd, field)) return 1; - field->set_name(buffer.ptr(), buffer.length(), system_charset_info); + field->set_name(buffer.ptr(), buffer.length(), system_charset_info, TRUE); if (thd->lex->verbose) { - field->set_name(buffer.ptr(), buffer.length(), system_charset_info); + field->set_name(buffer.ptr(), buffer.length(), system_charset_info, TRUE); field_info= &schema_table->fields_info[3]; field= new Item_field(NullS, NullS, field_info->field_name); if (add_item_to_list(thd, field)) return 1; field->set_name(field_info->old_name, strlen(field_info->old_name), - system_charset_info); + system_charset_info, TRUE); } return 0; } @@ -3337,7 +3337,7 @@ { field->set_name(field_info->old_name, strlen(field_info->old_name), - system_charset_info); + system_charset_info, TRUE); if (add_item_to_list(thd, field)) return 1; } @@ -3359,7 +3359,7 @@ { field->set_name(field_info->old_name, strlen(field_info->old_name), - system_charset_info); + system_charset_info, TRUE); if (add_item_to_list(thd, field)) return 1; } @@ -3381,7 +3381,7 @@ { field->set_name(field_info->old_name, strlen(field_info->old_name), - system_charset_info); + system_charset_info, TRUE); if (add_item_to_list(thd, field)) return 1; } --- 1.399/sql/sql_yacc.yy Fri Jun 17 22:27:21 2005 +++ 1.400/sql/sql_yacc.yy Tue Jun 21 08:27:00 2005 @@ -4107,12 +4107,12 @@ if (add_item_to_list(YYTHD, $2)) YYABORT; if ($4.str) - $2->set_name($4.str,$4.length,system_charset_info); + $2->set_name($4.str, $4.length, system_charset_info, FALSE); else if (!$2->name) { char *str = $1; if (str[-1] == '`') str--; - $2->set_name(str,(uint) ($3 - str), YYTHD->charset()); + $2->set_name(str,(uint) ($3 - str), YYTHD->charset(), TRUE); } }; @@ -4913,9 +4913,9 @@ remember_name expr remember_end select_alias { if ($4.str) - $2->set_name($4.str,$4.length,system_charset_info); + $2->set_name($4.str, $4.length, system_charset_info, FALSE); else - $2->set_name($1,(uint) ($3 - $1), YYTHD->charset()); + $2->set_name($1, (uint) ($3 - $1), YYTHD->charset(), TRUE); $$= $2; } ; @@ -5691,7 +5691,8 @@ if (add_proc_to_list(lex->thd, $2)) YYABORT; if (!$2->name) - $2->set_name($1,(uint) ((char*) lex->tok_end - $1), YYTHD->charset()); + $2->set_name($1,(uint) ((char*) lex->tok_end - $1), + YYTHD->charset(), TRUE); } ; --- 1.82/mysql-test/r/view.result Fri Jun 17 17:27:42 2005 +++ 1.83/mysql-test/r/view.result Tue Jun 21 08:27:00 2005 @@ -1743,3 +1743,58 @@ cast(1 as decimal) 1.00 drop view v1; +create view v1 as select '\\','\\shazam'; +select * from v1; +\ \shazam +\ \shazam +drop view v1; +create view v1 as select '\'','\shazam'; +select * from v1; +' shazam +' shazam +drop view v1; +create view v1 as select 'k','K'; +select * from v1; +k My_exp_K +k K +drop view v1; +create table t1 (s1 int); +create view v1 as select s1, 's1' from t1; +select * from v1; +s1 My_exp_s1 +drop view v1; +create view v1 as select 's1', s1 from t1; +select * from v1; +My_exp_s1 s1 +drop view v1; +create view v1 as select 's1', s1, 1 as My_exp_s1 from t1; +select * from v1; +My_exp_1_s1 s1 My_exp_s1 +drop view v1; +create view v1 as select 1 as My_exp_s1, 's1', s1 from t1; +select * from v1; +My_exp_s1 My_exp_1_s1 s1 +drop view v1; +create view v1 as select 1 as s1, 's1', 's1' from t1; +select * from v1; +s1 My_exp_s1 My_exp_1_s1 +drop view v1; +create view v1 as select 's1', 's1', 1 as s1 from t1; +select * from v1; +My_exp_1_s1 My_exp_s1 s1 +drop view v1; +create view v1 as select s1, 's1', 's1' from t1; +select * from v1; +s1 My_exp_s1 My_exp_1_s1 +drop view v1; +create view v1 as select 's1', 's1', s1 from t1; +select * from v1; +My_exp_1_s1 My_exp_s1 s1 +drop view v1; +create view v1 as select 1 as s1, 's1', s1 from t1; +ERROR 42S21: Duplicate column name 's1' +create view v1 as select 's1', s1, 1 as s1 from t1; +ERROR 42S21: Duplicate column name 's1' +drop table t1; +create view v1(k, K) as select 1,2; +ERROR 42S21: Duplicate column name 'K' --- 1.71/mysql-test/t/view.test Fri Jun 17 17:27:42 2005 +++ 1.72/mysql-test/t/view.test Tue Jun 21 08:27:00 2005 @@ -1587,3 +1587,56 @@ create view v1 as select cast(1 as decimal); select * from v1; drop view v1; + +# +# Generation unique names for columns, and correct names check (BUG#7448) +# +# names with ' and \ +create view v1 as select '\\','\\shazam'; +select * from v1; +drop view v1; +create view v1 as select '\'','\shazam'; +select * from v1; +drop view v1; +# autogenerated names differ by case only +create view v1 as select 'k','K'; +select * from v1; +drop view v1; +create table t1 (s1 int); +# same autogenerated names +create view v1 as select s1, 's1' from t1; +select * from v1; +drop view v1; +create view v1 as select 's1', s1 from t1; +select * from v1; +drop view v1; +# set name as one of expected autogenerated +create view v1 as select 's1', s1, 1 as My_exp_s1 from t1; +select * from v1; +drop view v1; +create view v1 as select 1 as My_exp_s1, 's1', s1 from t1; +select * from v1; +drop view v1; +# set name conflict with autogenerated names +create view v1 as select 1 as s1, 's1', 's1' from t1; +select * from v1; +drop view v1; +create view v1 as select 's1', 's1', 1 as s1 from t1; +select * from v1; +drop view v1; +# underlying field name conflict with autogenerated names +create view v1 as select s1, 's1', 's1' from t1; +select * from v1; +drop view v1; +create view v1 as select 's1', 's1', s1 from t1; +select * from v1; +drop view v1; +# underlying field name conflict with set name +-- error 1060 +create view v1 as select 1 as s1, 's1', s1 from t1; +-- error 1060 +create view v1 as select 's1', s1, 1 as s1 from t1; +drop table t1; +# set names differ by case only +-- error 1060 +create view v1(k, K) as select 1,2; --- 1.47/sql/sql_view.cc Wed Jun 15 20:58:23 2005 +++ 1.48/sql/sql_view.cc Tue Jun 21 08:27:00 2005 @@ -36,6 +36,63 @@ /* + Make unique field for view + + SYNOPSIS + target reference to item for which new name have to be made + item_list list of items where we should check name unique + last_element last element for unique check in above list + + NOTE: unique name made by adding 'My_exp_' old name of field, if we get + alrerady exists name we add number 1 to name and will increase number + untill we get unique name. + If we get name longer then NAME_LEN, it will be cut. +*/ + +static void make_unique_view_field_name(Item *target, + List &item_list, + Item *last_element) +{ + int name_len; + char buff[NAME_LEN+1]; + bool attempt= 0; + for (;; attempt++) + { + Item *check; + List_iterator_fast itc(item_list); + bool ok= TRUE; + + if (attempt) + name_len= my_snprintf(buff, NAME_LEN, "My_exp_%d_%s", + attempt, + (target->orig_name ? + target->orig_name : + target->name)); + else + name_len= my_snprintf(buff, NAME_LEN, "My_exp_%s", + (target->orig_name ? + target->orig_name : + target->name)); + + do + { + check= itc++; + if (check != target && + my_strcasecmp(system_charset_info, buff, check->name) == 0) + { + ok = FALSE; + break; + } + } while (check != last_element); + if (ok) + break; + } + + target->orig_name= target->name; + target->set_name(buff, name_len, system_charset_info, TRUE); +} + +/* Creating/altering VIEW procedure SYNOPSIS @@ -240,24 +297,33 @@ goto err; } while ((item= it++, name= nm++)) - item->set_name(name->str, name->length, system_charset_info); + item->set_name(name->str, name->length, system_charset_info, FALSE); } /* Test absence of duplicates names */ { Item *item; List_iterator_fast it(select_lex->item_list); - it++; while ((item= it++)) { Item *check; List_iterator_fast itc(select_lex->item_list); + /* treat underlying fields like set by user names */ + if (item->real_item()->type() == Item::FIELD_ITEM) + item->autogenerated_name= FALSE; while ((check= itc++) && check != item) { - if (strcmp(item->name, check->name) == 0) + if (my_strcasecmp(system_charset_info, item->name, check->name) == 0) { - my_error(ER_DUP_FIELDNAME, MYF(0), item->name); - DBUG_RETURN(TRUE); + if (item->autogenerated_name) + make_unique_view_field_name(item, select_lex->item_list, item); + else if (check->autogenerated_name) + make_unique_view_field_name(check, select_lex->item_list, item); + else + { + my_error(ER_DUP_FIELDNAME, MYF(0), item->name); + DBUG_RETURN(TRUE); + } } } }