diff --git a/include/hash.h b/include/hash.h
index 4ca8dc0e8bfe99fe3cc253c54f8f9fcd934414ae..1f094d48585a5e62f0512217d12d6703583b7721 100644
--- a/include/hash.h
+++ b/include/hash.h
@@ -21,6 +21,40 @@
 extern "C" {
 #endif
 
+/*
+  There was a problem on MacOSX with a shared object ha_example.so.
+  It used hash_search(). During build of ha_example.so no libmysys
+  was specified. Since MacOSX had a hash_search() in the system
+  library, it built the shared object so that the dynamic linker
+  linked hash_search() to the system library, which caused a crash
+  when called. To come around this, we renamed hash_search() to
+  my_hash_search(), as we did long ago with hash_insert() and
+  hash_reset(). However, this time we made the move complete with
+  all names. To keep compatibility, we redefine the old names.
+  Since every C and C++ file, that uses HASH, needs to include
+  this file, the change is complete. Both names could be used
+  in the code, but the my_* versions are recommended now.
+*/
+#define hash_get_key    my_hash_get_key
+#define hash_free_key   my_hash_free_key
+#define hash_init       my_hash_init
+#define hash_init2      my_hash_init2
+#define _hash_init      _my_hash_init
+#define hash_free       my_hash_free
+#define hash_reset      my_hash_reset
+#define hash_element    my_hash_element
+#define hash_search     my_hash_search
+#define hash_first      my_hash_first
+#define hash_next       my_hash_next
+#define hash_insert     my_hash_insert
+#define hash_delete     my_hash_delete
+#define hash_update     my_hash_update
+#define hash_replace    my_hash_replace
+#define hash_check      my_hash_check
+#define hash_clear      my_hash_clear
+#define hash_inited     my_hash_inited
+#define hash_init_opt   my_hash_init_opt
+
 /*
   Overhead to store an element in hash
   Can be used to approximate memory consumption for a hash
@@ -30,8 +64,8 @@ extern "C" {
 /* flags for hash_init */
 #define HASH_UNIQUE     1       /* hash_insert fails on duplicate key */
 
-typedef uchar *(*hash_get_key)(const uchar *,size_t*,my_bool);
-typedef void (*hash_free_key)(void *);
+typedef uchar *(*my_hash_get_key)(const uchar *,size_t*,my_bool);
+typedef void (*my_hash_free_key)(void *);
 
 typedef struct st_hash {
   size_t key_offset,key_length;		/* Length of key if const length */
@@ -39,7 +73,7 @@ typedef struct st_hash {
   ulong records;
   uint flags;
   DYNAMIC_ARRAY array;				/* Place for hash_keys */
-  hash_get_key get_key;
+  my_hash_get_key get_key;
   void (*free)(void *);
   CHARSET_INFO *charset;
 } HASH;
@@ -47,30 +81,34 @@ typedef struct st_hash {
 /* A search iterator state */
 typedef uint HASH_SEARCH_STATE;
 
-#define hash_init(A,B,C,D,E,F,G,H) _hash_init(A,0,B,C,D,E,F,G,H CALLER_INFO)
-#define hash_init2(A,B,C,D,E,F,G,H,I) _hash_init(A,B,C,D,E,F,G,H,I CALLER_INFO)
-my_bool _hash_init(HASH *hash, uint growth_size,CHARSET_INFO *charset,
-		   ulong default_array_elements, size_t key_offset,
-		   size_t key_length, hash_get_key get_key,
-		   void (*free_element)(void*), uint flags CALLER_INFO_PROTO);
-void hash_free(HASH *tree);
+#define my_hash_init(A,B,C,D,E,F,G,H) \
+          _my_hash_init(A,0,B,C,D,E,F,G,H CALLER_INFO)
+#define my_hash_init2(A,B,C,D,E,F,G,H,I) \
+          _my_hash_init(A,B,C,D,E,F,G,H,I CALLER_INFO)
+my_bool _my_hash_init(HASH *hash, uint growth_size, CHARSET_INFO *charset,
+                      ulong default_array_elements, size_t key_offset,
+                      size_t key_length, my_hash_get_key get_key,
+                      void (*free_element)(void*),
+                      uint flags CALLER_INFO_PROTO);
+void my_hash_free(HASH *tree);
 void my_hash_reset(HASH *hash);
-uchar *hash_element(HASH *hash,ulong idx);
-uchar *hash_search(const HASH *info, const uchar *key, size_t length);
-uchar *hash_first(const HASH *info, const uchar *key, size_t length,
-                HASH_SEARCH_STATE *state);
-uchar *hash_next(const HASH *info, const uchar *key, size_t length,
-                 HASH_SEARCH_STATE *state);
-my_bool my_hash_insert(HASH *info,const uchar *data);
-my_bool hash_delete(HASH *hash,uchar *record);
-my_bool hash_update(HASH *hash,uchar *record,uchar *old_key,size_t old_key_length);
-void hash_replace(HASH *hash, HASH_SEARCH_STATE *state, uchar *new_row);
-my_bool hash_check(HASH *hash);			/* Only in debug library */
+uchar *my_hash_element(HASH *hash, ulong idx);
+uchar *my_hash_search(const HASH *info, const uchar *key, size_t length);
+uchar *my_hash_first(const HASH *info, const uchar *key, size_t length,
+                     HASH_SEARCH_STATE *state);
+uchar *my_hash_next(const HASH *info, const uchar *key, size_t length,
+                    HASH_SEARCH_STATE *state);
+my_bool my_hash_insert(HASH *info, const uchar *data);
+my_bool my_hash_delete(HASH *hash, uchar *record);
+my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key,
+                       size_t old_key_length);
+void my_hash_replace(HASH *hash, HASH_SEARCH_STATE *state, uchar *new_row);
+my_bool my_hash_check(HASH *hash); /* Only in debug library */
 
-#define hash_clear(H) bzero((char*) (H),sizeof(*(H)))
-#define hash_inited(H) ((H)->array.buffer != 0)
-#define hash_init_opt(A,B,C,D,E,F,G,H) \
-          (!hash_inited(A) && _hash_init(A,0,B,C,D,E,F,G, H CALLER_INFO))
+#define my_hash_clear(H) bzero((char*) (H), sizeof(*(H)))
+#define my_hash_inited(H) ((H)->array.buffer != 0)
+#define my_hash_init_opt(A,B,C,D,E,F,G,H) \
+          (!my_hash_inited(A) && _my_hash_init(A,0,B,C,D,E,F,G, H CALLER_INFO))
 
 #ifdef	__cplusplus
 }
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 5e63701751b24a6c4146d2b42a76e521944c7f2c..f67ce4db76185c3b7df1373155b5ac0d7360c9ae 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -3601,7 +3601,16 @@ sub run_testcase ($) {
   {
     mtr_timer_stop_all($glob_timers);
     mtr_report("\nServers started, exiting");
-    exit(0);
+    if ($glob_win32_perl)
+    {
+      #ActiveState perl hangs  when using normal exit, use  POSIX::_exit instead
+      use POSIX qw[ _exit ]; 
+      POSIX::_exit(0);
+    }
+    else
+    {
+      exit(0);
+    }
   }
 
   {
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index b8723a87661e83dfe9b853493ad8668fe03118bf..c7997369f4d99b9cde19c0b444b031d9f4b93fba 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -1559,6 +1559,8 @@ SHOW INDEX FROM t1;
 Table	Non_unique	Key_name	Seq_in_index	Column_name	Collation	Cardinality	Sub_part	Packed	Null	Index_type	Comment
 t1	1	c1	1	c1	A	NULL	NULL	NULL	YES	BTREE	
 DROP TABLE t1;
+create user mysqltest_1@'test@test';
+ERROR HY000: Malformed hostname (illegal symbol: '@')
 CREATE TABLE t1 (a INTEGER AUTO_INCREMENT PRIMARY KEY, b INTEGER NOT NULL);
 INSERT IGNORE INTO t1 (b) VALUES (5);
 CREATE TABLE IF NOT EXISTS t2 (a INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY)
diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result
index eff5f117c50bd794fb1b32d79b70ecaf3366493a..83b8217b570aec3d9177ea54c661c7ffc5fdf2e2 100644
--- a/mysql-test/r/information_schema_db.result
+++ b/mysql-test/r/information_schema_db.result
@@ -221,3 +221,24 @@ drop view testdb_1.v1, v2, testdb_1.v3, v4;
 drop database testdb_1;
 drop user testdb_1@localhost;
 drop user testdb_2@localhost;
+create database testdb_1;
+create table testdb_1.t1 (a int);
+create view testdb_1.v1 as select * from testdb_1.t1;
+grant show view on testdb_1.* to mysqltest_1@localhost;
+grant select on testdb_1.v1 to mysqltest_1@localhost;
+select table_schema, table_name, view_definition from information_schema.views
+where table_name='v1';
+table_schema	table_name	view_definition
+testdb_1	v1	select `testdb_1`.`t1`.`a` AS `a` from `testdb_1`.`t1`
+show create view testdb_1.v1;
+View	Create View	character_set_client	collation_connection
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `testdb_1`.`v1` AS select `testdb_1`.`t1`.`a` AS `a` from `testdb_1`.`t1`	latin1	latin1_swedish_ci
+revoke select on testdb_1.v1 from mysqltest_1@localhost;
+select table_schema, table_name, view_definition from information_schema.views
+where table_name='v1';
+table_schema	table_name	view_definition
+testdb_1	v1	
+show create view testdb_1.v1;
+ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 'v1'
+drop user mysqltest_1@localhost;
+drop database testdb_1;
diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test
index 60d98fce49080ab5626f412dd68b13b8df32f36b..2eeca1eea90fdf8b3bfbcf3734710fdc4edb6fb5 100644
--- a/mysql-test/t/create.test
+++ b/mysql-test/t/create.test
@@ -1175,6 +1175,11 @@ CREATE TABLE t1(c1 VARCHAR(33), KEY USING HASH (c1) USING BTREE) ENGINE=MEMORY;
 SHOW INDEX FROM t1;
 DROP TABLE t1;
 
+#
+# Bug#35924 DEFINER should be stored 'quoted' in I_S
+#
+--error ER_UNKNOWN_ERROR
+create user mysqltest_1@'test@test';
 
 #
 # Bug#38821: Assert table->auto_increment_field_not_null failed in open_table()
diff --git a/mysql-test/t/information_schema_db.test b/mysql-test/t/information_schema_db.test
index 666f331c7b95766d132a522d9f56e5b06837c9bf..6353e94fd512f60b4369dbdbc71c71dbb3e658c2 100644
--- a/mysql-test/t/information_schema_db.test
+++ b/mysql-test/t/information_schema_db.test
@@ -82,6 +82,7 @@ drop function func2;
 drop database `inf%`;
 drop procedure mbase.p1;
 drop database mbase;
+disconnect user1;
 
 #
 # Bug#18282 INFORMATION_SCHEMA.TABLES provides inconsistent info about invalid views
@@ -210,3 +211,32 @@ drop view testdb_1.v1, v2, testdb_1.v3, v4;
 drop database testdb_1;
 drop user testdb_1@localhost;
 drop user testdb_2@localhost;
+
+#
+# Bug#22763 Disrepancy between SHOW CREATE VIEW and I_S.VIEWS
+#
+create database testdb_1;
+create table testdb_1.t1 (a int);
+create view testdb_1.v1 as select * from testdb_1.t1;
+
+grant show view on testdb_1.* to mysqltest_1@localhost;
+grant select on testdb_1.v1 to mysqltest_1@localhost;
+
+connect (user1,localhost,mysqltest_1,,test);
+connection user1;
+select table_schema, table_name, view_definition from information_schema.views
+where table_name='v1';
+show create view testdb_1.v1;
+
+connection default;
+revoke select on testdb_1.v1 from mysqltest_1@localhost;
+connection user1;
+select table_schema, table_name, view_definition from information_schema.views
+where table_name='v1';
+--error ER_TABLEACCESS_DENIED_ERROR
+show create view testdb_1.v1;
+
+connection default;
+drop user mysqltest_1@localhost;
+drop database testdb_1;
+disconnect user1;
diff --git a/mysys/hash.c b/mysys/hash.c
index 9166ae6f7882a0a34c63c4bb982c2d4ae1009f91..65a60c9e3413692e24598d6f1f38f575d194351c 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -33,7 +33,7 @@ typedef struct st_hash_info {
   uchar *data;					/* data for current entry */
 } HASH_LINK;
 
-static uint hash_mask(uint hashnr,uint buffmax,uint maxlength);
+static uint my_hash_mask(uint hashnr, uint buffmax, uint maxlength);
 static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink);
 static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key,
                    size_t length);
@@ -46,19 +46,19 @@ static uint calc_hash(const HASH *hash, const uchar *key, size_t length)
 }
 
 my_bool
-_hash_init(HASH *hash,uint growth_size, CHARSET_INFO *charset,
-	   ulong size, size_t key_offset, size_t key_length,
-	   hash_get_key get_key,
-	   void (*free_element)(void*),uint flags CALLER_INFO_PROTO)
+_my_hash_init(HASH *hash, uint growth_size, CHARSET_INFO *charset,
+              ulong size, size_t key_offset, size_t key_length,
+              my_hash_get_key get_key,
+              void (*free_element)(void*), uint flags CALLER_INFO_PROTO)
 {
-  DBUG_ENTER("hash_init");
+  DBUG_ENTER("my_hash_init");
   DBUG_PRINT("enter",("hash: 0x%lx  size: %u", (long) hash, (uint) size));
 
   hash->records=0;
   if (my_init_dynamic_array_ci(&hash->array, sizeof(HASH_LINK), size,
                                growth_size))
   {
-    hash->free=0;				/* Allow call to hash_free */
+    hash->free=0;				/* Allow call to my_hash_free */
     DBUG_RETURN(1);
   }
   hash->key_offset=key_offset;
@@ -76,14 +76,14 @@ _hash_init(HASH *hash,uint growth_size, CHARSET_INFO *charset,
   Call hash->free on all elements in hash.
 
   SYNOPSIS
-    hash_free_elements()
+    my_hash_free_elements()
     hash   hash table
 
   NOTES:
     Sets records to 0
 */
 
-static inline void hash_free_elements(HASH *hash)
+static inline void my_hash_free_elements(HASH *hash)
 {
   if (hash->free)
   {
@@ -100,18 +100,18 @@ static inline void hash_free_elements(HASH *hash)
   Free memory used by hash.
 
   SYNOPSIS
-    hash_free()
+    my_hash_free()
     hash   the hash to delete elements of
 
-  NOTES: Hash can't be reused without calling hash_init again.
+  NOTES: Hash can't be reused without calling my_hash_init again.
 */
 
-void hash_free(HASH *hash)
+void my_hash_free(HASH *hash)
 {
-  DBUG_ENTER("hash_free");
+  DBUG_ENTER("my_hash_free");
   DBUG_PRINT("enter",("hash: 0x%lx", (long) hash));
 
-  hash_free_elements(hash);
+  my_hash_free_elements(hash);
   hash->free= 0;
   delete_dynamic(&hash->array);
   DBUG_VOID_RETURN;
@@ -131,7 +131,7 @@ void my_hash_reset(HASH *hash)
   DBUG_ENTER("my_hash_reset");
   DBUG_PRINT("enter",("hash: 0x%lxd", (long) hash));
 
-  hash_free_elements(hash);
+  my_hash_free_elements(hash);
   reset_dynamic(&hash->array);
   /* Set row pointers so that the hash can be reused at once */
   hash->blength= 1;
@@ -146,8 +146,8 @@ void my_hash_reset(HASH *hash)
 */
 
 static inline char*
-hash_key(const HASH *hash, const uchar *record, size_t *length,
-         my_bool first)
+my_hash_key(const HASH *hash, const uchar *record, size_t *length,
+            my_bool first)
 {
   if (hash->get_key)
     return (char*) (*hash->get_key)(record,length,first);
@@ -157,18 +157,18 @@ hash_key(const HASH *hash, const uchar *record, size_t *length,
 
 	/* Calculate pos according to keys */
 
-static uint hash_mask(uint hashnr,uint buffmax,uint maxlength)
+static uint my_hash_mask(uint hashnr, uint buffmax, uint maxlength)
 {
   if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1));
   return (hashnr & ((buffmax >> 1) -1));
 }
 
-static uint hash_rec_mask(const HASH *hash, HASH_LINK *pos,
-                          uint buffmax, uint maxlength)
+static uint my_hash_rec_mask(const HASH *hash, HASH_LINK *pos,
+                             uint buffmax, uint maxlength)
 {
   size_t length;
-  uchar *key= (uchar*) hash_key(hash,pos->data,&length,0);
-  return hash_mask(calc_hash(hash,key,length),buffmax,maxlength);
+  uchar *key= (uchar*) my_hash_key(hash, pos->data, &length, 0);
+  return my_hash_mask(calc_hash(hash, key, length), buffmax, maxlength);
 }
 
 
@@ -181,15 +181,15 @@ inline
 unsigned int rec_hashnr(HASH *hash,const uchar *record)
 {
   size_t length;
-  uchar *key= (uchar*) hash_key(hash,record,&length,0);
+  uchar *key= (uchar*) my_hash_key(hash, record, &length, 0);
   return calc_hash(hash,key,length);
 }
 
 
-uchar* hash_search(const HASH *hash, const uchar *key, size_t length)
+uchar* my_hash_search(const HASH *hash, const uchar *key, size_t length)
 {
   HASH_SEARCH_STATE state;
-  return hash_first(hash, key, length, &state);
+  return my_hash_first(hash, key, length, &state);
 }
 
 /*
@@ -199,18 +199,18 @@ uchar* hash_search(const HASH *hash, const uchar *key, size_t length)
    Assigns the number of the found record to HASH_SEARCH_STATE state
 */
 
-uchar* hash_first(const HASH *hash, const uchar *key, size_t length,
-                HASH_SEARCH_STATE *current_record)
+uchar* my_hash_first(const HASH *hash, const uchar *key, size_t length,
+                     HASH_SEARCH_STATE *current_record)
 {
   HASH_LINK *pos;
   uint flag,idx;
-  DBUG_ENTER("hash_first");
+  DBUG_ENTER("my_hash_first");
 
   flag=1;
   if (hash->records)
   {
-    idx=hash_mask(calc_hash(hash,key,length ? length : hash->key_length),
-		    hash->blength,hash->records);
+    idx= my_hash_mask(calc_hash(hash, key, length ? length : hash->key_length),
+                      hash->blength, hash->records);
     do
     {
       pos= dynamic_element(&hash->array,idx,HASH_LINK*);
@@ -223,7 +223,7 @@ uchar* hash_first(const HASH *hash, const uchar *key, size_t length,
       if (flag)
       {
 	flag=0;					/* Reset flag */
-	if (hash_rec_mask(hash,pos,hash->blength,hash->records) != idx)
+	if (my_hash_rec_mask(hash, pos, hash->blength, hash->records) != idx)
 	  break;				/* Wrong link */
       }
     }
@@ -234,10 +234,10 @@ uchar* hash_first(const HASH *hash, const uchar *key, size_t length,
 }
 
 	/* Get next record with identical key */
-	/* Can only be called if previous calls was hash_search */
+	/* Can only be called if previous calls was my_hash_search */
 
-uchar* hash_next(const HASH *hash, const uchar *key, size_t length,
-               HASH_SEARCH_STATE *current_record)
+uchar* my_hash_next(const HASH *hash, const uchar *key, size_t length,
+                    HASH_SEARCH_STATE *current_record)
 {
   HASH_LINK *pos;
   uint idx;
@@ -297,7 +297,7 @@ static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key,
                    size_t length)
 {
   size_t rec_keylength;
-  uchar *rec_key= (uchar*) hash_key(hash,pos->data,&rec_keylength,1);
+  uchar *rec_key= (uchar*) my_hash_key(hash, pos->data, &rec_keylength, 1);
   return ((length && length != rec_keylength) ||
 	  my_strnncoll(hash->charset, (uchar*) rec_key, rec_keylength,
 		       (uchar*) key, rec_keylength));
@@ -306,7 +306,7 @@ static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key,
 
 	/* Write a hash-key to the hash-index */
 
-my_bool my_hash_insert(HASH *info,const uchar *record)
+my_bool my_hash_insert(HASH *info, const uchar *record)
 {
   int flag;
   size_t idx;
@@ -321,8 +321,8 @@ my_bool my_hash_insert(HASH *info,const uchar *record)
 
   if (HASH_UNIQUE & info->flags)
   {
-    uchar *key= (uchar*) hash_key(info, record, &idx, 1);
-    if (hash_search(info, key, idx))
+    uchar *key= (uchar*) my_hash_key(info, record, &idx, 1);
+    if (my_hash_search(info, key, idx))
       return(TRUE);				/* Duplicate entry */
   }
 
@@ -341,7 +341,7 @@ my_bool my_hash_insert(HASH *info,const uchar *record)
       pos=data+idx;
       hash_nr=rec_hashnr(info,pos->data);
       if (flag == 0)				/* First loop; Check if ok */
-	if (hash_mask(hash_nr,info->blength,info->records) != first_index)
+	if (my_hash_mask(hash_nr, info->blength, info->records) != first_index)
 	  break;
       if (!(hash_nr & halfbuff))
       {						/* Key will not move */
@@ -413,7 +413,7 @@ my_bool my_hash_insert(HASH *info,const uchar *record)
   }
   /* Check if we are at the empty position */
 
-  idx=hash_mask(rec_hashnr(info,record),info->blength,info->records+1);
+  idx= my_hash_mask(rec_hashnr(info, record), info->blength, info->records + 1);
   pos=data+idx;
   if (pos == empty)
   {
@@ -424,7 +424,7 @@ my_bool my_hash_insert(HASH *info,const uchar *record)
   {
     /* Check if more records in same hash-nr family */
     empty[0]=pos[0];
-    gpos=data+hash_rec_mask(info,pos,info->blength,info->records+1);
+    gpos= data + my_hash_rec_mask(info, pos, info->blength, info->records + 1);
     if (pos == gpos)
     {
       pos->data=(uchar*) record;
@@ -449,18 +449,18 @@ my_bool my_hash_insert(HASH *info,const uchar *record)
 ** if there is a free-function it's called for record if found
 ******************************************************************************/
 
-my_bool hash_delete(HASH *hash,uchar *record)
+my_bool my_hash_delete(HASH *hash, uchar *record)
 {
   uint blength,pos2,pos_hashnr,lastpos_hashnr,idx,empty_index;
   HASH_LINK *data,*lastpos,*gpos,*pos,*pos3,*empty;
-  DBUG_ENTER("hash_delete");
+  DBUG_ENTER("my_hash_delete");
   if (!hash->records)
     DBUG_RETURN(1);
 
   blength=hash->blength;
   data=dynamic_element(&hash->array,0,HASH_LINK*);
   /* Search after record with key */
-  pos=data+ hash_mask(rec_hashnr(hash,record),blength,hash->records);
+  pos= data + my_hash_mask(rec_hashnr(hash, record), blength, hash->records);
   gpos = 0;
 
   while (pos->data != record)
@@ -491,7 +491,7 @@ my_bool hash_delete(HASH *hash,uchar *record)
   /* Move the last key (lastpos) */
   lastpos_hashnr=rec_hashnr(hash,lastpos->data);
   /* pos is where lastpos should be */
-  pos=data+hash_mask(lastpos_hashnr,hash->blength,hash->records);
+  pos= data + my_hash_mask(lastpos_hashnr, hash->blength, hash->records);
   if (pos == empty)			/* Move to empty position. */
   {
     empty[0]=lastpos[0];
@@ -499,7 +499,7 @@ my_bool hash_delete(HASH *hash,uchar *record)
   }
   pos_hashnr=rec_hashnr(hash,pos->data);
   /* pos3 is where the pos should be */
-  pos3= data+hash_mask(pos_hashnr,hash->blength,hash->records);
+  pos3= data + my_hash_mask(pos_hashnr, hash->blength, hash->records);
   if (pos != pos3)
   {					/* pos is on wrong posit */
     empty[0]=pos[0];			/* Save it here */
@@ -507,8 +507,8 @@ my_bool hash_delete(HASH *hash,uchar *record)
     movelink(data,(uint) (pos-data),(uint) (pos3-data),empty_index);
     goto exit;
   }
-  pos2= hash_mask(lastpos_hashnr,blength,hash->records+1);
-  if (pos2 == hash_mask(pos_hashnr,blength,hash->records+1))
+  pos2= my_hash_mask(lastpos_hashnr, blength, hash->records + 1);
+  if (pos2 == my_hash_mask(pos_hashnr, blength, hash->records + 1))
   {					/* Identical key-positions */
     if (pos2 != hash->records)
     {
@@ -536,26 +536,26 @@ exit:
 	  This is much more efficent than using a delete & insert.
 	  */
 
-my_bool hash_update(HASH *hash, uchar *record, uchar *old_key,
-                    size_t old_key_length)
+my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key,
+                       size_t old_key_length)
 {
   uint new_index,new_pos_index,blength,records,empty;
   size_t idx;
   HASH_LINK org_link,*data,*previous,*pos;
-  DBUG_ENTER("hash_update");
+  DBUG_ENTER("my_hash_update");
   
   if (HASH_UNIQUE & hash->flags)
   {
     HASH_SEARCH_STATE state;
-    uchar *found, *new_key= (uchar*) hash_key(hash, record, &idx, 1);
-    if ((found= hash_first(hash, new_key, idx, &state)))
+    uchar *found, *new_key= (uchar*) my_hash_key(hash, record, &idx, 1);
+    if ((found= my_hash_first(hash, new_key, idx, &state)))
     {
       do 
       {
         if (found != record)
           DBUG_RETURN(1);		/* Duplicate entry */
       } 
-      while ((found= hash_next(hash, new_key, idx, &state)));
+      while ((found= my_hash_next(hash, new_key, idx, &state)));
     }
   }
 
@@ -564,11 +564,11 @@ my_bool hash_update(HASH *hash, uchar *record, uchar *old_key,
 
   /* Search after record with key */
 
-  idx=hash_mask(calc_hash(hash, old_key,(old_key_length ?
-					      old_key_length :
-					      hash->key_length)),
-		  blength,records);
-  new_index=hash_mask(rec_hashnr(hash,record),blength,records);
+  idx= my_hash_mask(calc_hash(hash, old_key, (old_key_length ?
+                                              old_key_length :
+                                              hash->key_length)),
+                    blength, records);
+  new_index= my_hash_mask(rec_hashnr(hash, record), blength, records);
   if (idx == new_index)
     DBUG_RETURN(0);			/* Nothing to do (No record check) */
   previous=0;
@@ -618,7 +618,7 @@ my_bool hash_update(HASH *hash, uchar *record, uchar *old_key,
     DBUG_RETURN(0);
   }
   pos=data+new_index;
-  new_pos_index=hash_rec_mask(hash,pos,blength,records);
+  new_pos_index= my_hash_rec_mask(hash, pos, blength, records);
   if (new_index != new_pos_index)
   {					/* Other record in wrong position */
     data[empty] = *pos;
@@ -636,7 +636,7 @@ my_bool hash_update(HASH *hash, uchar *record, uchar *old_key,
 }
 
 
-uchar *hash_element(HASH *hash,ulong idx)
+uchar *my_hash_element(HASH *hash, ulong idx)
 {
   if (idx < hash->records)
     return dynamic_element(&hash->array,idx,HASH_LINK*)->data;
@@ -649,7 +649,8 @@ uchar *hash_element(HASH *hash,ulong idx)
   isn't changed
 */
 
-void hash_replace(HASH *hash, HASH_SEARCH_STATE *current_record, uchar *new_row)
+void my_hash_replace(HASH *hash, HASH_SEARCH_STATE *current_record,
+                     uchar *new_row)
 {
   if (*current_record != NO_RECORD)            /* Safety */
     dynamic_element(&hash->array, *current_record, HASH_LINK*)->data= new_row;
@@ -658,7 +659,7 @@ void hash_replace(HASH *hash, HASH_SEARCH_STATE *current_record, uchar *new_row)
 
 #ifndef DBUG_OFF
 
-my_bool hash_check(HASH *hash)
+my_bool my_hash_check(HASH *hash)
 {
   int error;
   uint i,rec_link,found,max_links,seek,links,idx;
@@ -671,7 +672,7 @@ my_bool hash_check(HASH *hash)
 
   for (i=found=max_links=seek=0 ; i < records ; i++)
   {
-    if (hash_rec_mask(hash,data+i,blength,records) == i)
+    if (my_hash_rec_mask(hash, data + i, blength, records) == i)
     {
       found++; seek++; links=1;
       for (idx=data[i].next ;
@@ -687,11 +688,12 @@ my_bool hash_check(HASH *hash)
 	}
 	hash_info=data+idx;
 	seek+= ++links;
-	if ((rec_link=hash_rec_mask(hash,hash_info,blength,records)) != i)
+	if ((rec_link= my_hash_rec_mask(hash, hash_info,
+                                        blength, records)) != i)
 	{
-	  DBUG_PRINT("error",
-		     ("Record in wrong link at %d: Start %d  Record: 0x%lx  Record-link %d",
-                      idx, i, (long) hash_info->data, rec_link));
+          DBUG_PRINT("error", ("Record in wrong link at %d: Start %d  "
+                               "Record: 0x%lx  Record-link %d",
+                               idx, i, (long) hash_info->data, rec_link));
 	  error=1;
 	}
 	else
diff --git a/sql/handler.cc b/sql/handler.cc
index f26e84bdfdf8e6513a36ac8a79c114df610bfc23..8765a7f86bfffd5a80ae803fae257cf608bdaae4 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -373,6 +373,10 @@ int ha_finalize_handlerton(st_plugin_int *plugin)
   handlerton *hton= (handlerton *)plugin->data;
   DBUG_ENTER("ha_finalize_handlerton");
 
+  /* hton can be NULL here, if ha_initialize_handlerton() failed. */
+  if (!hton)
+    goto end;
+
   switch (hton->state)
   {
   case SHOW_OPTION_NO:
@@ -401,8 +405,16 @@ int ha_finalize_handlerton(st_plugin_int *plugin)
     }
   }
 
+  /*
+    In case a plugin is uninstalled and re-installed later, it should
+    reuse an array slot. Otherwise the number of uninstall/install
+    cycles would be limited.
+  */
+  hton2plugin[hton->slot]= NULL;
+
   my_free((uchar*)hton, MYF(0));
 
+ end:
   DBUG_RETURN(0);
 }
 
@@ -437,6 +449,7 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
   case SHOW_OPTION_YES:
     {
       uint tmp;
+      ulong fslot;
       /* now check the db_type for conflict */
       if (hton->db_type <= DB_TYPE_UNKNOWN ||
           hton->db_type >= DB_TYPE_DEFAULT ||
@@ -461,7 +474,31 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
       tmp= hton->savepoint_offset;
       hton->savepoint_offset= savepoint_alloc_size;
       savepoint_alloc_size+= tmp;
-      hton->slot= total_ha++;
+
+      /*
+        In case a plugin is uninstalled and re-installed later, it should
+        reuse an array slot. Otherwise the number of uninstall/install
+        cycles would be limited. So look for a free slot.
+      */
+      DBUG_PRINT("plugin", ("total_ha: %lu", total_ha));
+      for (fslot= 0; fslot < total_ha; fslot++)
+      {
+        if (!hton2plugin[fslot])
+          break;
+      }
+      if (fslot < total_ha)
+        hton->slot= fslot;
+      else
+      {
+        if (total_ha >= MAX_HA)
+        {
+          sql_print_error("Too many plugins loaded. Limit is %lu. "
+                          "Failed on '%s'", (ulong) MAX_HA, plugin->name.str);
+          goto err;
+        }
+        hton->slot= total_ha++;
+      }
+
       hton2plugin[hton->slot]=plugin;
       if (hton->prepare)
         total_ha_2pc++;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index f2b2806ea600770abe74ae55ca98ea6a418a771d..d11f2838e3a00594226b672010b9cbb85ab27891 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -803,6 +803,7 @@ bool check_string_byte_length(LEX_STRING *str, const char *err_msg,
 bool check_string_char_length(LEX_STRING *str, const char *err_msg,
                               uint max_char_length, CHARSET_INFO *cs,
                               bool no_error);
+bool check_host_name(LEX_STRING *str);
 
 bool parse_sql(THD *thd,
                Parser_state *parser_state,
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 30fef9c7ee70ece4c43ecd7ef3e6cff2f79f8c1d..a710b80b4e0037d3428ad95c95504f9bef83517b 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -7503,6 +7503,39 @@ int test_if_data_home_dir(const char *dir)
 C_MODE_END
 
 
+/**
+  Check that host name string is valid.
+
+  @param[in] str string to be checked
+
+  @return             Operation status
+    @retval  FALSE    host name is ok
+    @retval  TRUE     host name string is longer than max_length or
+                      has invalid symbols
+*/
+
+bool check_host_name(LEX_STRING *str)
+{
+  const char *name= str->str;
+  const char *end= str->str + str->length;
+  if (check_string_byte_length(str, ER(ER_HOSTNAME), HOSTNAME_LENGTH))
+    return TRUE;
+
+  while (name != end)
+  {
+    if (*name == '@')
+    {
+      my_printf_error(ER_UNKNOWN_ERROR, 
+                      "Malformed hostname (illegal symbol: '%c')", MYF(0),
+                      *name);
+      return TRUE;
+    }
+    name++;
+  }
+  return FALSE;
+}
+
+
 extern int MYSQLparse(void *thd); // from sql_yacc.cc
 
 
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index cc465db77206ee16b866da7a5369eb9e2595b526..f715da843c2b883adc8e299afa146342ee2cda5e 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -4236,6 +4236,27 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables,
           !my_strcasecmp(system_charset_info, tables->definer.host.str,
                          sctx->priv_host))
         tables->allowed_show= TRUE;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+      else
+      {
+        if ((thd->col_access & (SHOW_VIEW_ACL|SELECT_ACL)) ==
+            (SHOW_VIEW_ACL|SELECT_ACL))
+          tables->allowed_show= TRUE;
+        else
+        {
+          TABLE_LIST table_list;
+          uint view_access;
+          memset(&table_list, 0, sizeof(table_list));
+          table_list.db= tables->view_db.str;
+          table_list.table_name= tables->view_name.str;
+          table_list.grant.privilege= thd->col_access;
+          view_access= get_table_grant(thd, &table_list);
+          if ((view_access & (SHOW_VIEW_ACL|SELECT_ACL)) ==
+              (SHOW_VIEW_ACL|SELECT_ACL))
+            tables->allowed_show= TRUE;
+        }
+      }
+#endif
     }
     restore_record(table, s->default_values);
     tmp_db_name= &tables->view_db;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 278fe88c3367fb38156577afc6fa4a86f2bf9856..8d9b3a2d4b5081bb3292d056c6cd2e5105d807d8 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -11301,8 +11301,7 @@ user:
             if (check_string_char_length(&$$->user, ER(ER_USERNAME),
                                          USERNAME_CHAR_LENGTH,
                                          system_charset_info, 0) ||
-                check_string_byte_length(&$$->host, ER(ER_HOSTNAME),
-                                         HOSTNAME_LENGTH))
+                check_host_name(&$$->host))
               MYSQL_YYABORT;
           }
         | CURRENT_USER optional_braces