From 29ec367edd81aff7b8fc4b6abbbfff5e2620be19 Mon Sep 17 00:00:00 2001
From: unknown <bell@sanja.is.com.ua>
Date: Thu, 16 Sep 2004 23:45:20 +0300
Subject: [PATCH] updateability of field with collation support (BUG#5506)

mysql-test/r/view.result:
   Collation with view update
mysql-test/t/view.test:
   Collation with view update
sql/item.h:
  updateability of field with collation support
sql/item_strfunc.h:
  updateability of field with collation support
sql/sql_insert.cc:
  updateability of field with collation support
sql/sql_update.cc:
  updateability of field with collation support
sql/sql_view.cc:
  updateability of field with collation support
---
 mysql-test/r/view.result | 16 ++++++++++++++++
 mysql-test/t/view.test   | 14 ++++++++++++++
 sql/item.h               |  3 +++
 sql/item_strfunc.h       |  5 +++++
 sql/sql_insert.cc        |  4 ++--
 sql/sql_update.cc        |  5 +++--
 sql/sql_view.cc          | 24 ++++++++++++++----------
 7 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 2551977200..62f0e849cb 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -1311,3 +1311,19 @@ a	a	a
 3	3	3
 drop view v1;
 drop table t1;
+create table t1 (s1 char);
+create view v1 as select s1 collate latin1_german1_ci as s1 from t1;
+insert into v1 values ('a');
+select * from v1;
+s1
+a
+update v1 set s1='b';
+select * from v1;
+s1
+b
+update v1,t1 set v1.s1='c' where t1.s1=v1.s1;
+select * from v1;
+s1
+c
+drop view v1;
+drop table t1;
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index 682646a6c0..ac582c71c5 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -1271,3 +1271,17 @@ select * from t1 left join (t2 as t, v1) on v1.a=t1.a;
 select * from t1 left join (t2 as t, t2) on t2.a=t1.a;
 drop view v1;
 drop table t1;
+
+#
+# Collation with view update
+#
+create table t1 (s1 char);
+create view v1 as select s1 collate latin1_german1_ci as s1 from t1;
+insert into v1 values ('a');
+select * from v1;
+update v1 set s1='b';
+select * from v1;
+update v1,t1 set v1.s1='c' where t1.s1=v1.s1;
+select * from v1;
+drop view v1;
+drop table t1;
diff --git a/sql/item.h b/sql/item.h
index a237e7ce6f..c96db6b89c 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -22,6 +22,7 @@
 class Protocol;
 struct st_table_list;
 void item_init(void);			/* Init item functions */
+class Item_field;
 
 
 /*
@@ -276,6 +277,7 @@ public:
   virtual void bring_value() {}
 
   Field *tmp_table_field_from_field_type(TABLE *table);
+  virtual Item_field *filed_for_view_update() { return 0; }
 
   virtual Item *neg_transformer(THD *thd) { return NULL; }
   void delete_self()
@@ -496,6 +498,7 @@ public:
   Item *get_tmp_table_item(THD *thd);
   void cleanup();
   inline uint32 max_disp_length() { return field->max_length(); }
+  Item_field *filed_for_view_update() { return this; }
   friend class Item_default_value;
   friend class Item_insert_value;
   friend class st_select_lex_unit;
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index df8861b2ee..c4881a465a 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -636,6 +636,11 @@ public:
   bool eq(const Item *item, bool binary_cmp) const;
   const char *func_name() const { return "collate"; }
   void print(String *str);
+  Item_field *filed_for_view_update()
+  {
+    /* this function is transparent for view updating */
+    return args[0]->filed_for_view_update();
+  }
 };
 
 class Item_func_charset :public Item_str_func
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index ac63445c1d..9890e234ec 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -490,13 +490,13 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
   {
     Item_field *field;
     /* simple SELECT list entry (field without expression) */
-    if ((*trans)->type() != Item::FIELD_ITEM)
+    if (!(field= (*trans)->filed_for_view_update()))
       DBUG_RETURN(TRUE);
-    field= (Item_field *)(*trans);
     if (field->field->unireg_check == Field::NEXT_NUMBER)
       view->contain_auto_increment= 1;
     /* prepare unique test */
     field->field->query_id= other_query_id;
+    *trans= field; // remove collation if we have it
   }
   /* unique test */
   for (trans= trans_start; trans != trans_end; trans++)
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index dc86796826..7a9b0af242 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -67,9 +67,10 @@ static bool check_fields(THD *thd, List<Item> &items)
 {
   List_iterator<Item> it(items);
   Item *item;
+  Item_field *field;
   while ((item= it++))
   {
-    if (item->type() != Item::FIELD_ITEM)
+    if (!(field= item->filed_for_view_update()))
     {
       /* as far as item comes from VIEW select list it has name */
       my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), item->name);
@@ -79,7 +80,7 @@ static bool check_fields(THD *thd, List<Item> &items)
       we make temporary copy of Item_field, to avoid influence of changing
       result_field on Item_ref which refer on this field
     */
-    Item_field *field= new Item_field(thd, (Item_field *)item);
+    field= new Item_field(thd, field);
     it.replace(field);
     ((Item_field *)item)->register_item_tree_changing(it.ref());
   }
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 2364be228f..8238d3d484 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -148,8 +148,9 @@ int mysql_create_view(THD *thd,
     Item *item;
     while ((item= it++))
     {
-      if (item->type() == Item::FIELD_ITEM)
-        ((Item_field *)item)->any_privileges= 1;
+      Item_field *field;
+      if ((field= item->filed_for_view_update()))
+        field->any_privileges= 1;
     }
   }
 #endif
@@ -237,12 +238,12 @@ int mysql_create_view(THD *thd,
                                     view->real_name);
     while ((item= it++))
     {
+      Item_field *fld;
       uint priv= (get_column_grant(thd, &view->grant, db,
                                     view->real_name, item->name) &
                   VIEW_ANY_ACL);
-      if (item->type() == Item::FIELD_ITEM)
+      if ((fld= item->filed_for_view_update()))
       {
-        Item_field *fld= (Item_field *)item;
         /*
           There are no any privileges on VIEW column or there are
           some other privileges then we have for underlaying table
@@ -903,8 +904,9 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
         uint k;
         for (k= 0; k < elements_in_view; k++)
         {
-          if (trans[k]->type() == Item::FIELD_ITEM &&
-              ((Item_field *)trans[k])->field == key_part->field) 
+          Item_field *field;
+          if ((field= trans[k]->filed_for_view_update()) &&
+              field->field == key_part->field)
             break;
         }
         if (k == elements_in_view)
@@ -923,8 +925,9 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
     {
       for (i= 0; i < elements_in_view; i++)
       {
-        if (trans[i]->type() == Item::FIELD_ITEM &&
-            ((Item_field *)trans[i])->field == *field_ptr)
+        Item_field *field;
+        if ((field= trans[i]->filed_for_view_update()) &&
+            field->field == *field_ptr)
           break;
       }
       if (i == elements_in_view)                // If field didn't exists
@@ -976,8 +979,9 @@ void insert_view_fields(List<Item> *list, TABLE_LIST *view)
 
   for (uint i= 0; i < elements_in_view; i++)
   {
-    if (trans[i]->type() == Item::FIELD_ITEM)
-      list->push_back(trans[i]);
+    Item_field *fld;
+    if ((fld= trans[i]->filed_for_view_update()))
+      list->push_back(fld);
   }
   DBUG_VOID_RETURN;
 }
-- 
2.30.9