List:Internals« Previous MessageNext Message »
From:sanja Date:June 21 2005 7:30pm
Subject:bk commit into 5.0 tree (bell:1.1958) BUG#7448
View as plain text  
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 20:30:48 bell@stripped +7 -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 20:30:44 bell@stripped +11 -4
    add a flag that indicates that the name of the item was an auto-generated one and so
can be changed in a view

  sql/sql_view.cc
    1.48 05/06/21 20:30:44 bell@stripped +71 -4
    fixed checking of duplicates of view fields:
    1) case-insensitive system charset/collation is used now to compare view filds
    2) in case if the duplicate field name was of an auto-generated one, we create another
unique name for it

  sql/item_func.cc
    1.223 05/06/21 20:30:44 bell@stripped +1 -1
    line made less then 80 columns

  sql/item.h
    1.141 05/06/21 20:30:44 bell@stripped +4 -2
    add a flag that indicates that the name of the item was an auto-generated one and so
can be changed in a view
    layout fixed

  sql/item.cc
    1.137 05/06/21 20:30:44 bell@stripped +1 -0
    add a flag that indicates that the name of the item was an auto-generated one and so
can be changed in a view

  mysql-test/t/view.test
    1.72 05/06/21 20:30:44 bell@stripped +53 -0
    test of view field names generation

  mysql-test/r/view.result
    1.83 05/06/21 20:30:44 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 20:30:44 2005
@@ -314,6 +314,7 @@
 
 Item::Item():
   rsize(0), name(0), orig_name(0), name_length(0), fixed(0),
+  is_autogenerated_name(TRUE),
   collation(&my_charset_bin, DERIVATION_COERCIBLE)
 {
   marker= 0;

--- 1.140/sql/item.h	Fri Jun 17 20:30:06 2005
+++ 1.141/sql/item.h	Tue Jun 21 20:30:44 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 is_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,7 @@
     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);
   void rename(char *new_name);
   void init_make_field(Send_field *tmp_field,enum enum_field_types type);
   virtual void cleanup();
@@ -1170,7 +1172,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);
     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 20:30:44 2005
@@ -4620,7 +4620,7 @@
   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);  // Will use original name
   return item;
 }
 

--- 1.399/sql/sql_yacc.yy	Fri Jun 17 22:27:21 2005
+++ 1.400/sql/sql_yacc.yy	Tue Jun 21 20:30:44 2005
@@ -4107,7 +4107,10 @@
 	    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);
+              $2->is_autogenerated_name= FALSE;
+            }
 	    else if (!$2->name) {
 	      char *str = $1;
 	      if (str[-1] == '`')
@@ -4913,9 +4916,12 @@
 	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);
+            $2->is_autogenerated_name= FALSE;
+          }
 	  else
-	    $2->set_name($1,(uint) ($3 - $1), YYTHD->charset());
+	    $2->set_name($1, (uint) ($3 - $1), YYTHD->charset());
 	  $$= $2;
 	}
 	;
@@ -5691,7 +5697,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());
 	  }
           ;
 

--- 1.82/mysql-test/r/view.result	Fri Jun 17 17:27:42 2005
+++ 1.83/mysql-test/r/view.result	Tue Jun 21 20:30:44 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 20:30:44 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 20:30:44 2005
@@ -36,6 +36,61 @@
 
 
 /*
+  Make a unique name for an anonymous view column
+  SYNOPSIS
+    target        reference to the item for which a new name has to be made
+    item_list     list of items within which we should check uniqueness of
+                  the created name
+    last_element  the last element of the list above
+
+  NOTE
+    Unique names are generated by adding 'My_exp_' to the old name of the
+    column. In case the name that was created this way already exists, we
+    add a numeric postfix to its end (i.e. "1") and increase the number
+    until the name becomes unique. If the generated name is longer than
+    NAME_LEN, it is truncated.
+*/
+
+static void make_unique_view_field_name(Item *target,
+                                        List<Item> &item_list,
+                                        Item *last_element)
+{
+  char *name= (target->orig_name ?
+               target->orig_name :
+               target->name);
+  uint name_len;
+  uint attempt= 0;
+  char buff[NAME_LEN+1];
+  for (;; attempt++)
+  {
+    Item *check;
+    List_iterator_fast<Item> itc(item_list);
+    bool ok= TRUE;
+
+    if (attempt)
+      name_len= my_snprintf(buff, NAME_LEN, "My_exp_%d_%s", attempt, name);
+    else
+      name_len= my_snprintf(buff, NAME_LEN, "My_exp_%s", 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);
+}
+
+/*
   Creating/altering VIEW procedure
 
   SYNOPSIS
@@ -240,24 +295,36 @@
       goto err;
     }
     while ((item= it++, name= nm++))
+    {
       item->set_name(name->str, name->length, system_charset_info);
+      item->is_autogenerated_name= FALSE;
+    }
   }
 
   /* Test absence of duplicates names */
   {
     Item *item;
     List_iterator_fast<Item> it(select_lex->item_list);
-    it++;
     while ((item= it++))
     {
       Item *check;
       List_iterator_fast<Item> itc(select_lex->item_list);
+      /* treat underlying fields like set by user names */
+      if (item->real_item()->type() == Item::FIELD_ITEM)
+        item->is_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->is_autogenerated_name)
+            make_unique_view_field_name(item, select_lex->item_list, item);
+          else if (check->is_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);
+          }
         }
       }
     }
Thread
bk commit into 5.0 tree (bell:1.1958) BUG#7448sanja21 Jun