List:Commits« Previous MessageNext Message »
From:Konstantin Osipov Date:November 27 2008 6:33pm
Subject:bzr push into mysql-6.0-runtime branch (kostja:2777 to 2778) WL#4264
View as plain text  
 2778 Konstantin Osipov	2008-11-27
      WL#4264, review comments, implement Server_runnable.
modified:
  sql/mysql_priv.h
  sql/protocol.h
  sql/si_objects.cc
  sql/sql_prepare.cc

 2777 Alexander Nozdrin	2008-11-27 [merge]
      Pull from 6.0-runtime
modified:
  mysql-test/r/auto_commit_basic.result
  mysql-test/r/automatic_sp_privileges_basic.result
  mysql-test/r/big_tables_basic.result
  mysql-test/r/engine_condition_pushdown_basic.result
  mysql-test/r/flush_basic.result
  mysql-test/r/foreign_key_checks_basic.result
  mysql-test/r/func_math.result
  mysql-test/r/func_str.result
  mysql-test/r/general_log_basic.result
  mysql-test/r/innodb_checksums_basic.result
  mysql-test/r/innodb_doublewrite_basic.result
  mysql-test/r/innodb_file_per_table_basic.result
  mysql-test/r/innodb_locks_unsafe_for_binlog_basic.result
  mysql-test/r/innodb_rollback_on_timeout_basic.result
  mysql-test/r/innodb_support_xa_basic.result
  mysql-test/r/innodb_table_locks_basic.result
  mysql-test/r/keep_files_on_create_basic.result
  mysql-test/r/local_infile_basic.result
  mysql-test/r/log_bin_trust_function_creators_basic.result
  mysql-test/r/log_queries_not_using_indexes_basic.result
  mysql-test/r/low_priority_updates_basic.result
  mysql-test/r/myisam_use_mmap_basic.result
  mysql-test/r/new_basic.result
  mysql-test/r/old_passwords_basic.result
  mysql-test/r/profiling.result
  mysql-test/r/ps_1general.result
  mysql-test/r/query_cache_wlock_invalidate_basic.result
  mysql-test/r/read_only_basic.result
  mysql-test/r/relay_log_purge_basic.result
  mysql-test/r/rpl_slave_allow_batching_basic.result
  mysql-test/r/rpl_slave_compressed_protocol_basic.result
  mysql-test/r/secure_auth_basic.result
  mysql-test/r/slow_query_log_basic.result
  mysql-test/r/sp-vars.result
  mysql-test/r/sql_auto_is_null_basic.result
  mysql-test/r/sql_big_selects_basic.result
  mysql-test/r/sql_big_tables_basic.result
  mysql-test/r/sql_buffer_result_basic.result
  mysql-test/r/sql_log_bin_basic.result
  mysql-test/r/sql_log_off_basic.result
  mysql-test/r/sql_low_priority_updates_basic.result
  mysql-test/r/sql_notes_basic.result
  mysql-test/r/sql_quote_show_create_basic.result
  mysql-test/r/sql_safe_updates_basic.result
  mysql-test/r/sql_warnings_basic.result
  mysql-test/r/sync_frm_basic.result
  mysql-test/r/timed_mutexes_basic.result
  mysql-test/r/type_varchar.result
  mysql-test/r/unique_checks_basic.result
  mysql-test/suite/falcon/r/falcon_bugs.result
  mysql-test/suite/falcon/t/falcon_bugs.test
  mysql-test/suite/funcs_1/r/falcon_func_view.result
  mysql-test/suite/funcs_1/r/falcon_views.result
  mysql-test/suite/funcs_1/r/innodb_func_view.result
  mysql-test/suite/funcs_1/r/innodb_views.result
  mysql-test/suite/funcs_1/r/memory_func_view.result
  mysql-test/suite/funcs_1/r/memory_views.result
  mysql-test/suite/funcs_1/r/myisam_func_view.result
  mysql-test/suite/funcs_1/r/myisam_views.result
  mysql-test/suite/funcs_1/r/ndb_func_view.result
  mysql-test/suite/funcs_1/r/ndb_views.result
  mysql-test/suite/rpl/t/rpl_switch_stm_row_mixed.test
  mysql-test/t/auto_commit_basic.test
  mysql-test/t/automatic_sp_privileges_basic.test
  mysql-test/t/big_tables_basic.test
  mysql-test/t/engine_condition_pushdown_basic.test
  mysql-test/t/flush_basic.test
  mysql-test/t/foreign_key_checks_basic.test
  mysql-test/t/general_log_basic.test
  mysql-test/t/innodb_checksums_basic.test
  mysql-test/t/innodb_doublewrite_basic.test
  mysql-test/t/innodb_file_per_table_basic.test
  mysql-test/t/innodb_locks_unsafe_for_binlog_basic.test
  mysql-test/t/innodb_rollback_on_timeout_basic.test
  mysql-test/t/innodb_support_xa_basic.test
  mysql-test/t/innodb_table_locks_basic.test
  mysql-test/t/keep_files_on_create_basic.test
  mysql-test/t/local_infile_basic.test
  mysql-test/t/log_bin_trust_function_creators_basic.test
  mysql-test/t/log_queries_not_using_indexes_basic.test
  mysql-test/t/low_priority_updates_basic.test
  mysql-test/t/myisam_use_mmap_basic.test
  mysql-test/t/new_basic.test
  mysql-test/t/old_passwords_basic.test
  mysql-test/t/query_cache_wlock_invalidate_basic.test
  mysql-test/t/read_only_basic.test
  mysql-test/t/relay_log_purge_basic.test
  mysql-test/t/rpl_slave_allow_batching_basic.test
  mysql-test/t/rpl_slave_compressed_protocol_basic.test
  mysql-test/t/secure_auth_basic.test
  mysql-test/t/slow_query_log_basic.test
  mysql-test/t/sp-vars.test
  mysql-test/t/sql_auto_is_null_basic.test
  mysql-test/t/sql_big_selects_basic.test
  mysql-test/t/sql_big_tables_basic.test
  mysql-test/t/sql_buffer_result_basic.test
  mysql-test/t/sql_log_bin_basic.test
  mysql-test/t/sql_log_off_basic.test
  mysql-test/t/sql_low_priority_updates_basic.test
  mysql-test/t/sql_notes_basic.test
  mysql-test/t/sql_quote_show_create_basic.test
  mysql-test/t/sql_safe_updates_basic.test
  mysql-test/t/sql_warnings_basic.test
  mysql-test/t/sync_frm_basic.test
  mysql-test/t/timed_mutexes_basic.test
  mysql-test/t/type_varchar.test
  mysql-test/t/unique_checks_basic.test
  sql/event_scheduler.cc
  sql/events.cc
  sql/field.cc
  sql/sp_head.cc
  sql/sql_acl.cc
  sql/sql_base.cc
  sql/sql_connect.cc
  sql/sql_db.cc
  sql/sql_parse.cc
  sql/sql_plugin.cc
  sql/sql_servers.cc
  sql/sql_udf.cc
  sql/table.cc
  sql/tztime.cc

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2008-11-24 23:00:01 +0000
+++ b/sql/mysql_priv.h	2008-11-27 18:31:59 +0000
@@ -1138,8 +1138,24 @@ pthread_handler_t handle_bootstrap(void 
 int mysql_execute_command(THD *thd);
 
 class Ed_result;
+/**
+  Execute a fragment of server code in an isolated context, so that
+  it doesn't leave any effect on THD. THD must have no open tables.
+  The code must not leave any open tables around.
+  The result of execution (if any) is stored in Ed_result.
+*/
+
+class Server_runnable
+{
+public:
+  virtual bool execute_server_code(THD *thd)= 0;
+  virtual LEX_STRING get_slow_log_info();
+  virtual ~Server_runnable();
+};
 
 bool mysql_execute_direct(THD *thd, LEX_STRING query, Ed_result *result);
+bool mysql_execute_direct(THD *thd, Server_runnable *ed_runnable,
+                          Ed_result *result);
 
 bool do_command(THD *thd);
 bool dispatch_command(enum enum_server_command command, THD *thd,

=== modified file 'sql/protocol.h'
--- a/sql/protocol.h	2008-11-24 23:00:01 +0000
+++ b/sql/protocol.h	2008-11-27 18:31:59 +0000
@@ -266,6 +266,7 @@ private:
   Ed_column -- a class representing a column data in a row. Used with
   Ed_row and Protocol_local.
 */
+
 class Ed_column : public LEX_STRING, public Sql_alloc
 {
 public:

=== modified file 'sql/si_objects.cc'
--- a/sql/si_objects.cc	2008-11-26 13:46:42 +0000
+++ b/sql/si_objects.cc	2008-11-27 18:31:59 +0000
@@ -98,54 +98,52 @@ run_service_interface_sql(THD *thd, cons
 
 struct Table_name_key
 {
-public:
-  static uchar *get_key(const uchar *record,
-                        size_t *key_length,
-                        my_bool not_used __attribute__((unused)));
-
-  static void delete_key(void *data);
-
-public:
-  Table_name_key(const char *db_name_str,
-                 uint db_name_length,
-                 const char *table_name_str,
-                 uint table_name_length)
-  {
-    db_name.copy(db_name_str, db_name_length, system_charset_info);
-    table_name.copy(table_name_str, table_name_length, system_charset_info);
+  LEX_STRING db_name;
+  LEX_STRING table_name;
+  LEX_STRING key;
+  void init_from_mdl_key(const char *key_arg, size_t key_length_arg,
+                         char *key_buff_arg);
+};
 
-    key.length(0);
-    key.append(db_name);
-    key.append(".");
-    key.append(table_name);
-  }
 
-public:
-  String db_name;
-  String table_name;
+void
+Table_name_key::init_from_mdl_key(const char *key_arg, size_t key_length_arg,
+                                  char *key_buff_arg)
+{
+  key.str= key_buff_arg;
+  key.length= key_length_arg - 4; /* Skip MDL object type */
+  memcpy(key.str, key_arg + 4, key.length);
 
-  String key;
-};
+  db_name.str= key.str;
+  db_name.length= strlen(db_name.str);
+  table_name.str= db_name.str + db_name.length + 1; /* Skip \0 */
+  table_name.length= strlen(table_name.str);
+}
 
 ///////////////////////////////////////////////////////////////////////////
+extern "C" {
 
-uchar *Table_name_key::get_key(const uchar *record,
-                               size_t *key_length,
-                               my_bool not_used __attribute__((unused)))
+uchar *
+get_table_name_key(const uchar *record,
+                   size_t *key_length,
+                   my_bool not_used __attribute__((unused)))
 {
-  Table_name_key *tnk= (Table_name_key *) record;
-  *key_length= tnk->key.length();
-  return (uchar *) tnk->key.c_ptr_safe();
+  Table_name_key *table_name_key= (Table_name_key *) record;
+  *key_length= table_name_key->key.length;
+  return (uchar *) table_name_key->key.str;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
-void Table_name_key::delete_key(void *data)
+static void
+free_table_name_key(void *data)
 {
-  Table_name_key *tnk= (Table_name_key *) data;
-  delete tnk;
+  Table_name_key *table_name_key= (Table_name_key *) data;
+  my_free(table_name_key, MYF(0));
 }
 
+} // end of extern "C"
+
 ///////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////
 
@@ -1261,6 +1259,10 @@ public:
 public:
   virtual Obj *next();
 
+  enum enum_base_obj_kind { BASE_TABLE= 0, VIEW };
+
+  virtual enum_base_obj_kind get_base_obj_kind() const= 0;
+
 protected:
   template <typename Iterator>
   static Iterator *create(THD *thd,
@@ -1269,11 +1271,11 @@ protected:
 protected:
   bool init(THD *thd, const String *db_name, const String *view_name);
 
-  virtual bool is_obj_accepted(TABLE_LIST *obj)= 0;
-  virtual Obj *create_obj(const String *db_name, const String *obj_name)= 0;
+  virtual Obj *create_obj(const LEX_STRING *db_name,
+                          const LEX_STRING *obj_name)= 0;
 
 private:
-  HASH *m_table_names;
+  HASH m_table_names;
   uint m_cur_idx;
 };
 
@@ -1297,92 +1299,138 @@ Iterator *View_base_obj_iterator::create
 
 ///////////////////////////////////////////////////////////////////////////
 
-View_base_obj_iterator::View_base_obj_iterator() :
-  m_table_names(NULL),
-  m_cur_idx(0)
+View_base_obj_iterator::View_base_obj_iterator()
+  :m_cur_idx(0)
 {
+  hash_init(&m_table_names, system_charset_info, 16, 0, 0,
+            get_table_name_key, free_table_name_key,
+            MYF(0));
+
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
 View_base_obj_iterator::~View_base_obj_iterator()
 {
-  if (!m_table_names)
-    return;
-
-  hash_free(m_table_names);
-  delete m_table_names;
+  hash_free(&m_table_names);
 }
 
-///////////////////////////////////////////////////////////////////////////
 
-bool View_base_obj_iterator::init(THD *thd,
-                                  const String *db_name,
-                                  const String *view_name)
+/**
+  Find all base tables or views of a view.
+*/
+
+class Find_view_underlying_tables: public Server_runnable
 {
-  /* Ensure that init() will not be run twice. */
-  DBUG_ASSERT(!m_table_names);
+public:
+  Find_view_underlying_tables(const View_base_obj_iterator *base_obj_it,
+                              HASH *table_names,
+                              const String *db_name,
+                              const String *view_name);
 
-  uint not_used; /* Passed to open_tables(). Not used. */
-  THD *my_thd= new THD();
+  bool execute_server_code(THD *thd);
+private:
+  /* Store the resulting unique here */
+  const View_base_obj_iterator *m_base_obj_it;
+  HASH *m_table_names;
+  const String *m_db_name;
+  const String *m_view_name;
+};
 
-  my_thd->security_ctx= thd->security_ctx;
 
-  my_thd->thread_stack= (char*) &my_thd;
-  my_thd->store_globals();
-  lex_start(my_thd);
-
-  TABLE_LIST *tl =
-    sp_add_to_query_tables(my_thd,
-                           my_thd->lex,
-                           ((String *) db_name)->c_ptr_safe(),
-                           ((String *) view_name)->c_ptr_safe(),
-                           TL_READ);
-
-  if (open_tables(my_thd, &tl, &not_used, MYSQL_OPEN_SKIP_TEMPORARY))
-  {
-    close_thread_tables(my_thd);
-    delete my_thd;
-    thd->store_globals();
+Find_view_underlying_tables::
+Find_view_underlying_tables(const View_base_obj_iterator *base_obj_it,
+                            HASH *table_names,
+                            const String *db_name,
+                            const String *view_name)
+  :m_base_obj_it(base_obj_it),
+   m_table_names(table_names),
+   m_db_name(db_name),
+   m_view_name(view_name)
+{
+}
 
-    return TRUE;
-  }
 
-  m_table_names = new HASH();
+bool
+Find_view_underlying_tables::execute_server_code(THD *thd)
+{
+  bool res= TRUE;
+  uint counter_not_used; /* Passed to open_tables(). Not used. */
 
-  hash_init(m_table_names, system_charset_info, 16, 0, 0,
-            Table_name_key::get_key,
-            Table_name_key::delete_key,
-            MYF(0));
+  TABLE_LIST *table_list;
+
+  DBUG_ENTER("Find_view_underlying_tables::execute_server_code");
+
+  table_list= sp_add_to_query_tables(thd, thd->lex,
+                                     ((String *) m_db_name)->c_ptr_safe(),
+                                     ((String *) m_view_name)->c_ptr_safe(),
+                                     TL_READ);
 
-  if (tl->view_tables)
+  if (table_list == NULL)                      /* out of memory, reported */
+    DBUG_RETURN(TRUE);
+
+  if (open_tables(thd, &table_list, &counter_not_used,
+                  MYSQL_OPEN_SKIP_TEMPORARY))
+    goto end;
+
+  if (table_list->view_tables)
   {
-    List_iterator_fast<TABLE_LIST> it(*tl->view_tables);
-    TABLE_LIST *tl2;
+    TABLE_LIST *table;
+    List_iterator_fast<TABLE_LIST> it(*table_list->view_tables);
 
-    while ((tl2 = it++))
+    /*
+      Iterate over immediate underlying tables.
+      The list doesn't include views or tables referenced indirectly,
+      through other views, or stored functions or triggers.
+    */
+    while ((table= it++))
     {
-      Table_name_key *tnk=
-        new Table_name_key(tl2->db, tl2->db_length,
-                           tl2->table_name, tl2->table_name_length);
-
-      if (!is_obj_accepted(tl2) ||
-          hash_search(m_table_names,
-                      (uchar *) tnk->key.c_ptr_safe(),
-                      tnk->key.length()))
-      {
-        delete tnk;
+      Table_name_key *table_name_key;
+      char *key_buff;
+
+      /* If we expect a view, and it's a table, or vice versa, continue */
+      if ((int) m_base_obj_it->get_base_obj_kind() != test(table->view))
         continue;
-      }
 
-      my_hash_insert(m_table_names, (uchar *) tnk);
+      if (! my_multi_malloc(MYF(MY_WME),
+                            &table_name_key, sizeof(*table_name_key),
+                            &key_buff, table->mdl_lock_data->key_length,
+                            NullS))
+        goto end;
+
+      table_name_key->init_from_mdl_key(table->mdl_lock_data->key,
+                                        table->mdl_lock_data->key_length,
+                                        key_buff);
+
+      if (my_hash_insert(m_table_names, (uchar*) table_name_key))
+      {
+        my_free(table_name_key, MYF(0));
+        goto end;
+      }
     }
   }
+  res= FALSE;
+  my_ok(thd);
+
+end:
+  close_thread_tables(thd);
+  DBUG_RETURN(res);
+}
+
+///////////////////////////////////////////////////////////////////////////
 
-  close_thread_tables(my_thd);
-  delete my_thd;
+bool View_base_obj_iterator::init(THD *thd,
+                                  const String *db_name,
+                                  const String *view_name)
+{
+  Find_view_underlying_tables find_tables(this, &m_table_names,
+                                          db_name, view_name);
+  Ed_result ed_result; /* Just to grab OK or ERROR */
+
+  if (mysql_execute_direct(thd, &find_tables, &ed_result))
+    return TRUE;
 
-  thd->store_globals();
+  /* The table list is filled with unique underlying table names. */
 
   return FALSE;
 }
@@ -1391,15 +1439,15 @@ bool View_base_obj_iterator::init(THD *t
 
 Obj *View_base_obj_iterator::next()
 {
-  if (m_cur_idx >= m_table_names->records)
+  if (m_cur_idx >= m_table_names.records)
     return NULL;
 
-  Table_name_key *tnk=
-    (Table_name_key *) hash_element(m_table_names, m_cur_idx);
+  Table_name_key *table_name_key=
+    (Table_name_key *) hash_element(&m_table_names, m_cur_idx);
 
   ++m_cur_idx;
 
-  return create_obj(&tnk->db_name, &tnk->table_name);
+  return create_obj(&table_name_key->db_name, &table_name_key->table_name);
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -1416,12 +1464,12 @@ public:
   }
 
 protected:
-  virtual bool is_obj_accepted(TABLE_LIST *obj)
-  { return !obj->view; }
+  virtual enum_base_obj_kind get_base_obj_kind() const { return BASE_TABLE; }
 
-  virtual Obj *create_obj(const String *db_name, const String *obj_name)
+  virtual Obj *create_obj(const LEX_STRING *db_name,
+                          const LEX_STRING *obj_name)
   {
-    return new Table_obj(db_name->lex_string(), obj_name->lex_string());
+    return new Table_obj(*db_name, *obj_name);
   }
 };
 
@@ -1447,12 +1495,12 @@ public:
   }
 
 protected:
-  virtual bool is_obj_accepted(TABLE_LIST *obj)
-  { return obj->view; }
+  virtual enum_base_obj_kind get_base_obj_kind() const { return VIEW; }
 
-  virtual Obj *create_obj(const String *db_name, const String *obj_name)
+  virtual Obj *create_obj(const LEX_STRING *db_name,
+                          const LEX_STRING *obj_name)
   {
-    return new View_obj(db_name->lex_string(), obj_name->lex_string());
+    return new View_obj(*db_name, *obj_name);
   }
 };
 

=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc	2008-11-24 23:00:01 +0000
+++ b/sql/sql_prepare.cc	2008-11-27 18:31:59 +0000
@@ -162,7 +162,7 @@ public:
   bool execute_loop(String *expanded_query,
                     bool open_cursor,
                     uchar *packet_arg, uchar *packet_end_arg);
-  bool execute_immediate(const char *stmt, uint length);
+  bool execute_server_runnable(Server_runnable *server_runnable);
   /* Destroy this statement */
   void deallocate();
 private:
@@ -184,6 +184,20 @@ private:
 };
 
 
+/**
+*/
+
+class Execute_sql_statement: public Server_runnable
+{
+public:
+  Execute_sql_statement(LEX_STRING sql_text);
+  virtual bool execute_server_code(THD *thd);
+  virtual LEX_STRING get_slow_log_info();
+private:
+  LEX_STRING m_sql_text;
+  LEX_STRING m_slow_log_info;
+};
+
 /******************************************************************************
   Implementation
 ******************************************************************************/
@@ -2764,6 +2778,54 @@ void mysql_stmt_get_longdata(THD *thd, c
 }
 
 
+bool
+mysql_execute_direct(THD *thd, LEX_STRING query, Ed_result *ed_result)
+{
+  Execute_sql_statement execute_sql_statement(query);
+
+  return mysql_execute_direct(thd, &execute_sql_statement, ed_result);
+}
+
+
+/**
+  Execute a fragment of server functionality without an effect on
+  thd, and store results in Ed_result.
+
+  @param thd         Thread handle.
+  @param server_runnable A code fragment to execute.
+  @param ed_result   Result interceptor
+*/
+
+bool
+mysql_execute_direct(THD *thd, Server_runnable *server_runnable,
+                     Ed_result *ed_result)
+{
+  Protocol_local protocol_local(thd, ed_result);
+  Prepared_statement stmt(thd);
+
+  DBUG_ENTER("mysql_execute_direct");
+
+  DBUG_ASSERT(ed_result);
+
+  Protocol *protocol_saved= thd->protocol;
+
+  thd->protocol= &protocol_local;
+
+  ed_result->begin_statement(thd);
+  bool rc= stmt.execute_server_runnable(server_runnable);
+  ed_result->end_statement(thd);
+
+  thd->protocol->end_statement();
+
+  thd->protocol= protocol_saved;
+
+  thd->main_da.reset_diagnostics_area();
+
+  DBUG_RETURN(rc);
+}
+
+
+
 /***************************************************************************
  Select_fetch_protocol_binary
 ****************************************************************************/
@@ -2809,6 +2871,78 @@ Select_fetch_protocol_binary::send_data(
   return rc;
 }
 
+/*******************************************************************
+*
+*******************************************************************/
+
+Server_runnable::~Server_runnable()
+{
+}
+
+
+LEX_STRING
+Server_runnable::get_slow_log_info()
+{
+  return null_lex_str;
+}
+///////////////////////////////////////////////////////////////////////////
+
+Execute_sql_statement::
+Execute_sql_statement(LEX_STRING sql_text)
+  :m_sql_text(sql_text)
+{}
+
+LEX_STRING
+Execute_sql_statement::get_slow_log_info()
+{
+  return m_slow_log_info;
+}
+
+
+/**
+  Parse and execute a statement. Does not prepare the query.
+
+  Allows to execute a statement from within another statement.
+  The main property of the implementation is that it does not
+  affect the environment -- i.e. you  can run many
+  executions without having to cleanup/reset THD in between.
+*/
+
+bool
+Execute_sql_statement::execute_server_code(THD *thd)
+{
+  bool error;
+
+  if (alloc_query(thd, m_sql_text.str, m_sql_text.length))
+    return TRUE;
+
+  m_slow_log_info.str= thd->query;
+  m_slow_log_info.length= thd->query_length;
+
+  Parser_state parser_state(thd, thd->query, thd->query_length);
+
+  parser_state.m_lip.multi_statements= FALSE;
+  lex_start(thd);
+
+  error= parse_sql(thd, &parser_state, NULL) || thd->is_error();
+
+  if (error)
+    goto end;
+
+  thd->lex->set_trg_event_type_for_tables();
+
+  error= mysql_execute_command(thd);
+
+  if (error == 0 && thd->spcont == NULL)
+    general_log_write(thd, COM_STMT_EXECUTE,
+                      thd->query, thd->query_length);
+
+end:
+  lex_end(thd->lex);
+
+  return error;
+}
+
 /***************************************************************************
  Prepared_statement
 ****************************************************************************/
@@ -3258,123 +3392,34 @@ reexecute:
   return error;
 }
 
-/**
-  Execute one SQL statement.
-
-  @param thd    Thread handle.
-  @param query  Query to execute.
-*/
 
 bool
-mysql_execute_direct(THD *thd, LEX_STRING query, Ed_result *result)
-{
-  Protocol_local protocol_local(thd, result);
-
-  DBUG_ENTER("mysql_execute_direct");
-
-  DBUG_ASSERT(result);
-
-  Prepared_statement *stmt= new Prepared_statement(thd);
-
-  if (!stmt)
-    DBUG_RETURN(TRUE);
-
-  Protocol *protocol_saved= thd->protocol;
-
-  thd->protocol= &protocol_local;
-
-  result->begin_statement(thd);
-  bool rc= stmt->execute_immediate(query.str, query.length);
-  result->end_statement(thd);
-
-  thd->protocol->end_statement();
-
-  thd->protocol= protocol_saved;
-
-  delete stmt;
-
-  thd->main_da.reset_diagnostics_area();
-
-  DBUG_RETURN(rc);
-}
-
-
-/**
-  Parse and execute a query string. Does not prepare the query.
-
-  An implementation of "EXECUTE IMMEDIATE" syntax of Dynamic SQL.
-  Allows to execute a statement from within another statement.
-  The main property of the implementation is that it does not
-  affect the environment -- i.e. you  can run many
-  ::execute_immediate() without having to cleanup/reset THD in
-  between.
-*/
-
-bool
-Prepared_statement::execute_immediate(const char *query, uint length)
+Prepared_statement::execute_server_runnable(Server_runnable *server_runnable)
 {
+  LEX_STRING slow_log_stmt;
   Statement stmt_backup;
   bool error;
 
   state= CONVENTIONAL_EXECUTION;
 
-  if (!(lex = new (mem_root) st_lex_local))
+  if (!(lex= new (mem_root) st_lex_local))
     return TRUE;
 
   thd->set_n_backup_statement(this, &stmt_backup);
 
-  if (alloc_query(thd, query, length))
-  {
-    thd->set_statement(&stmt_backup);
-    return TRUE;
-  }
-  /*
-    Expanded query is needed for slow logging, so we want thd->query
-    to point at it even after we restore from backup. This is ok, as
-    expanded query was allocated in thd->mem_root.
-  */
-  stmt_backup.query= thd->query;
-  stmt_backup.query_length= thd->query_length;
-
-  Parser_state parser_state(thd, thd->query, thd->query_length);
-
-  parser_state.m_lip.multi_statements= FALSE;
-  lex_start(thd);
-
-  error= parse_sql(thd, &parser_state, NULL) || thd->is_error();
+  error= server_runnable->execute_server_code(thd);
 
+  cleanup_stmt();
 
-  if (lex->sql_command == SQLCOM_PREPARE ||
-      lex->sql_command == SQLCOM_EXECUTE ||
-      (lex->sql_command == SQLCOM_CHANGE_DB && is_sql_prepare()))
-  {
-    my_error(ER_PS_NO_RECURSION, MYF(0));
-    error= 1;
-  }
-
-  if (error)
-  {
-    thd->set_statement(&stmt_backup);
-    return TRUE;
-  }
-
-  lex->set_trg_event_type_for_tables();
-
-  if (query_cache_send_result_to_client(thd, thd->query,
-                                        thd->query_length) <= 0)
+  slow_log_stmt= server_runnable->get_slow_log_info();
+  if (slow_log_stmt.str)
   {
-    error= mysql_execute_command(thd);
+    stmt_backup.query= slow_log_stmt.str;
+    stmt_backup.query_length= slow_log_stmt.length;
   }
 
-  cleanup_stmt();
-  lex_end(thd->lex);
-
   thd->set_statement(&stmt_backup);
 
-  if (error == 0 && thd->spcont == NULL)
-    general_log_write(thd, COM_STMT_EXECUTE,
-                      thd->query, thd->query_length);
-
   return error;
 }
 

Thread
bzr push into mysql-6.0-runtime branch (kostja:2777 to 2778) WL#4264Konstantin Osipov27 Nov