diff --git a/libmariadb b/libmariadb
--- a/libmariadb
+++ b/libmariadb
@@ -1 +1 @@
-Subproject commit 7e53ab369815590ff92913b581d43eb7786f2fe2
+Subproject commit 7e53ab369815590ff92913b581d43eb7786f2fe2-dirty
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 2a9e649..1834d75 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -3957,7 +3957,8 @@ bool Query_compressed_log_event::write()
 */
 Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
 				 ulong query_length, bool using_trans,
-				 bool direct, bool suppress_use, int errcode)
+				 bool direct, bool suppress_use, int errcode,
+         const CHARSET_INFO *query_cs)
 
   :Log_event(thd_arg,
              (thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F :
@@ -4034,8 +4035,16 @@ bool Query_compressed_log_event::write()
   DBUG_ASSERT(thd_arg->variables.collation_connection->number < 256*256);
   DBUG_ASSERT(thd_arg->variables.collation_server->number < 256*256);
   DBUG_ASSERT(thd_arg->variables.character_set_client->mbminlen == 1);
-  int2store(charset, thd_arg->variables.character_set_client->number);
-  int2store(charset+2, thd_arg->variables.collation_connection->number);
+  if (query_cs)
+  {
+    int2store(charset, query_cs->number);
+    int2store(charset+2, query_cs->number);
+  }
+  else
+  {
+    int2store(charset, thd_arg->variables.character_set_client->number);
+    int2store(charset+2, thd_arg->variables.collation_connection->number);
+  }
   int2store(charset+4, thd_arg->variables.collation_server->number);
   if (thd_arg->time_zone_used)
   {
diff --git a/sql/log_event.h b/sql/log_event.h
index 34000a5..ee8d721 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -2086,7 +2086,8 @@ class Query_log_event: public Log_event
 #ifdef MYSQL_SERVER
 
   Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
-                  bool using_trans, bool direct, bool suppress_use, int error);
+                  bool using_trans, bool direct, bool suppress_use, int error,
+                  const CHARSET_INFO *query_cs= NULL);
   const char* get_db() { return db; }
 #ifdef HAVE_REPLICATION
   void pack_info(Protocol* protocol);
diff --git a/sql/sp.cc b/sql/sp.cc
index fcbf4dc..e8014f7 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -1290,7 +1290,8 @@ class Bad_db_error_handler : public Internal_error_handler
                        sp->m_body.str, sp->m_body.length,
                        sp->m_chistics, &(thd->lex->definer->user),
                        &(thd->lex->definer->host),
-                       saved_mode))
+                       saved_mode,
+                       true))
     {
       my_error(ER_OUT_OF_RESOURCES, MYF(0));
       goto done;
@@ -2214,7 +2215,8 @@ int sp_cache_routine(THD *thd, enum stored_procedure_type type, sp_name *name,
               st_sp_chistics *chistics,
               const LEX_STRING *definer_user,
               const LEX_STRING *definer_host,
-              sql_mode_t sql_mode)
+              sql_mode_t sql_mode,
+              bool should_thd_cs)
 {
   sql_mode_t old_sql_mode= thd->variables.sql_mode;
   /* Make some room to begin with */
@@ -2241,6 +2243,16 @@ int sp_cache_routine(THD *thd, enum stored_procedure_type type, sp_name *name,
     buf->append('.');
   }
   append_identifier(thd, buf, name, namelen);
+
+  if (should_thd_cs
+      && !thd->charset_is_system_charset
+      && thd->convert_string(buf, system_charset_info, thd->charset(), TRUE))
+  {
+    sql_print_warning("Failed to convert system_charset_info to %s character "
+                      "when create procedure, string:%s.",
+                      thd->charset()->csname, buf->ptr());
+    return FALSE;
+  }
   buf->append('(');
   buf->append(params, paramslen);
   buf->append(')');
diff --git a/sql/sp.h b/sql/sp.h
index 96d49cf..5037d60 100644
--- a/sql/sp.h
+++ b/sql/sp.h
@@ -229,5 +229,6 @@ bool show_create_sp(THD *thd, String *buf,
               st_sp_chistics *chistics,
               const LEX_STRING *definer_user,
               const LEX_STRING *definer_host,
-	      sql_mode_t sql_mode);
+	      sql_mode_t sql_mode,
+        bool should_thd_cs= FALSE);
 #endif /* _SP_H_ */
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 3f5af29..e0bb248 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2672,7 +2672,7 @@ static bool open_table_entry_fini(THD *thd, TABLE_SHARE *share, TABLE *entry)
         as it does a lot of extra work, that is simply wrong in this case
       */
       Query_log_event qinfo(thd, query.ptr(), query.length(),
-                            FALSE, TRUE, TRUE, 0);
+                            FALSE, TRUE, TRUE, 0, system_charset_info);
       if (mysql_bin_log.write(&qinfo))
         return TRUE;
     }
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 22d6137..2967488 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2327,11 +2327,13 @@ bool THD::copy_with_error(CHARSET_INFO *dstcs, LEX_STRING *dst,
    !0   out of memory
 */
 
-bool THD::convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
+bool THD::convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, bool safe_convert)
 {
-  uint dummy_errors;
+  uint dummy_errors= 0;
   if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors))
     return TRUE;
+  if (safe_convert && dummy_errors)
+    return TRUE;
   /* If convert_buffer >> s copying is more efficient long term */
   if (convert_buffer.alloced_length() >= convert_buffer.length() * 2 ||
       !s->is_alloced())
@@ -6899,7 +6901,7 @@ void THD::issue_unsafe_warnings()
 */
 int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
                       ulong query_len, bool is_trans, bool direct, 
-                      bool suppress_use, int errcode)
+                      bool suppress_use, int errcode, const CHARSET_INFO *query_cs)
 {
   DBUG_ENTER("THD::binlog_query");
   DBUG_PRINT("enter", ("qtype: %s  query: '%-.*s'",
@@ -7014,7 +7016,7 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
       else
       {
         Query_log_event qinfo(this, query_arg, query_len, is_trans, direct,
-          suppress_use, errcode);
+          suppress_use, errcode, query_cs);
         error= mysql_bin_log.write(&qinfo);
       }
 
diff --git a/sql/sql_class.h b/sql/sql_class.h
index e5aaba9..db1fa86 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3164,7 +3164,8 @@ class THD :public Statement,
   int binlog_query(enum_binlog_query_type qtype,
                    char const *query, ulong query_len, bool is_trans,
                    bool direct, bool suppress_use,
-                   int errcode);
+                   int errcode,
+                   const CHARSET_INFO *query_cs= NULL);
 #endif
 
   inline void
@@ -3448,7 +3449,7 @@ class THD :public Statement,
   bool copy_with_error(CHARSET_INFO *dstcs, LEX_STRING *dst,
                        CHARSET_INFO *srccs, const char *src, uint src_length);
 
-  bool convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs);
+  bool convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, bool safe_convert= FALSE);
 
   void add_changed_table(TABLE *table);
   void add_changed_table(const char *key, long key_length);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index a943495..07b51ce 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -4404,7 +4404,8 @@ static TABLE *create_table_from_items(THD *thd,
                               /* is_trans */ TRUE,
                               /* direct */ FALSE,
                               /* suppress_use */ FALSE,
-                              errcode);
+                              errcode,
+                              system_charset_info);
   }
 
   ha_fake_trx_id(thd);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index c112b01..5c5c02a 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1962,7 +1962,8 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
 */
 
 int write_bin_log(THD *thd, bool clear_error,
-                  char const *query, ulong query_length, bool is_trans)
+                  char const *query, ulong query_length, bool is_trans,
+                  const CHARSET_INFO *query_cs)
 {
   int error= 0;
   if (mysql_bin_log.is_open())
@@ -1975,7 +1976,7 @@ int write_bin_log(THD *thd, bool clear_error,
       errcode= query_error_code(thd, TRUE);
     error= thd->binlog_query(THD::STMT_QUERY_TYPE,
                              query, query_length, is_trans, FALSE, FALSE,
-                             errcode);
+                             errcode, query_cs);
     thd_proc_info(thd, 0);
   }
   return error;
@@ -2569,7 +2570,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
                                      built_non_trans_tmp_query.length(),
                                      FALSE, FALSE,
                                      is_drop_tmp_if_exists_added,
-                                     0);
+                                     0,
+                                     system_charset_info);
       }
       if (trans_tmp_table_deleted)
       {
@@ -2584,7 +2586,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
                                      built_trans_tmp_query.length(),
                                      TRUE, FALSE,
                                      is_drop_tmp_if_exists_added,
-                                     0);
+                                     0,
+                                     system_charset_info);
       }
       if (non_tmp_table_deleted)
       {
@@ -2600,7 +2603,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
                                      built_query.ptr(),
                                      built_query.length(),
                                      TRUE, FALSE, FALSE,
-                                     error_code);
+                                     error_code,
+                                     system_charset_info);
       }
     }
   }
@@ -2686,7 +2690,7 @@ bool log_drop_table(THD *thd, const char *db_name, size_t db_name_length,
                                "failed CREATE OR REPLACE */"));
   error= thd->binlog_query(THD::STMT_QUERY_TYPE,
                            query.ptr(), query.length(),
-                           FALSE, FALSE, temporary_table, 0);
+                           FALSE, FALSE, temporary_table, 0, system_charset_info);
   DBUG_RETURN(error);
 }
 
@@ -5606,7 +5610,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
 
           DBUG_ASSERT(result == 0); // show_create_table() always return 0
           do_logging= FALSE;
-          if (write_bin_log(thd, TRUE, query.ptr(), query.length()))
+          if (write_bin_log(thd, TRUE, query.ptr(), query.length(), FALSE, system_charset_info))
           {
             res= 1;
             do_logging= 0;
diff --git a/sql/sql_table.h b/sql/sql_table.h
index 5abb25d..b0ce2d4 100644
--- a/sql/sql_table.h
+++ b/sql/sql_table.h
@@ -260,7 +260,8 @@ CHARSET_INFO* get_sql_field_charset(Create_field *sql_field,
 bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags);
 int write_bin_log(THD *thd, bool clear_error,
                   char const *query, ulong query_length,
-                  bool is_trans= FALSE);
+                  bool is_trans= FALSE,
+                  const CHARSET_INFO *query_cs= NULL);
 bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
                            DDL_LOG_MEMORY_ENTRY **active_entry);
 bool write_execute_ddl_log_entry(uint first_entry,
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index cdb65a7..7b40406 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -682,12 +682,23 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
       buff.append(')');
     }
     buff.append(STRING_WITH_LEN(" AS "));
-    buff.append(views->source.str, views->source.length);
-
-    int errcode= query_error_code(thd, TRUE);
-    if (thd->binlog_query(THD::STMT_QUERY_TYPE,
-                          buff.ptr(), buff.length(), FALSE, FALSE, FALSE, errcode))
+    if (!thd->charset_is_system_charset
+        && thd->convert_string(&buff, system_charset_info, thd->charset(), TRUE))
+    {
+      my_error(ER_INVALID_CHARACTER_STRING, MYF(0),
+               thd->charset()->csname, buff.ptr());
       res= TRUE;
+    }
+    else
+    {
+      buff.append(views->source.str, views->source.length);
+
+      int errcode= query_error_code(thd, TRUE);
+      if (thd->binlog_query(THD::STMT_QUERY_TYPE,
+                            buff.ptr(), buff.length(), FALSE, FALSE, FALSE, errcode))
+        res= TRUE;
+    }
+
   }
 
   if (mode != VIEW_CREATE_NEW)
