List:Commits« Previous MessageNext Message »
From:Konstantin Osipov Date:November 13 2008 7:34pm
Subject:bzr commit into mysql-6.0-runtime branch (kostja:2745)
View as plain text  
#At file:///opt/local/work/mysql-6.0-runtime/

 2745 Konstantin Osipov	2008-11-13
      Commit to be able to patch.
modified:
  libmysql/libmysql.c
  mysql-test/suite/backup/r/backup.result
  mysql-test/suite/backup/r/backup_db_grants.result
  mysql-test/suite/backup/r/backup_errors.result
  mysql-test/suite/backup/r/backup_views.result
  mysql-test/suite/backup/t/backup_db_grants.test
  mysql-test/suite/backup/t/backup_errors.test
  mysql-test/suite/backup/t/backup_views.test
  sql/backup/backup_aux.h
  sql/backup/backup_info.cc
  sql/backup/backup_info.h
  sql/backup/backup_test.cc
  sql/backup/image_info.h
  sql/backup/kernel.cc
  sql/backup/logger.cc
  sql/ddl_blocker.cc
  sql/ddl_blocker.h
  sql/log.cc
  sql/mysql_priv.h
  sql/protocol.cc
  sql/protocol.h
  sql/share/errmsg.txt
  sql/si_objects.cc
  sql/si_objects.h
  sql/sql_class.cc
  sql/sql_error.cc
  sql/sql_error.h
  sql/sql_lex.cc
  sql/sql_lex.h
  sql/sql_parse.cc
  sql/sql_prepare.cc
  sql/sql_yacc.yy

=== modified file 'libmysql/libmysql.c'
--- a/libmysql/libmysql.c	2008-10-22 11:51:28 +0000
+++ b/libmysql/libmysql.c	2008-11-13 19:34:18 +0000
@@ -4863,7 +4863,10 @@ int STDCALL mysql_stmt_next_result(MYSQL
   rc= mysql_next_result(mysql);
 
   if (rc)
+  {
+    set_stmt_errmsg(stmt, &mysql->net);
     DBUG_RETURN(rc);
+  }
 
   stmt->state= MYSQL_STMT_EXECUTE_DONE;
   stmt->bind_result_done= FALSE;

=== modified file 'mysql-test/suite/backup/r/backup.result'
--- a/mysql-test/suite/backup/r/backup.result	2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/r/backup.result	2008-11-13 19:34:18 +0000
@@ -51,10 +51,6 @@ id	#
 command	Daemon
 state	MyISAM backup: holding table locks
 info	MyISAM driver locking thread
-id	#
-command	Query
-state	debug sync point: myisam_locking_thread_added
-info	BACKUP DATABASE db1,db2 TO 'test.ba'
 breakpoints: Sending finish signal to wake BACKUP.
 SET DEBUG_SYNC= 'now SIGNAL finish';
 backup_id

=== modified file 'mysql-test/suite/backup/r/backup_db_grants.result'
--- a/mysql-test/suite/backup/r/backup_db_grants.result	2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/r/backup_db_grants.result	2008-11-13 19:34:18 +0000
@@ -63,10 +63,31 @@ GRANT USAGE ON *.* TO 'bup_user2'@'%'
 SHOW GRANTS FOR 'bup_user3'@'%';
 Grants for bup_user3@%
 GRANT USAGE ON *.* TO 'bup_user3'@'%'
+SHOW GRANTS FOR 'no_user'@'%';
+ERROR 42000: There is no such grant defined for user 'no_user' on host '%'
 Run Restore
 RESTORE FROM 'bup_db_grants.bak';
 backup_id
 #
+Warnings:
+#	1737	The grant 'ALTER ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'ALTER ROUTINE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'CREATE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'CREATE ROUTINE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'CREATE TEMPORARY TABLES ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'CREATE VIEW ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'DELETE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'DROP ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'EVENT ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'EXECUTE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'INDEX ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'INSERT ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'LOCK TABLES ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'REFERENCES ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'SELECT ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'SHOW VIEW ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'TRIGGER ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'UPDATE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
 SHOW TABLES FROM bup_db_grants;
 Tables_in_bup_db_grants
 s1
@@ -99,6 +120,28 @@ Run Restore
 RESTORE FROM 'bup_db_grants.bak';
 backup_id
 #
+Warnings:
+#	1737	The grant 'INSERT ON bup_db_grants.*' for the user 'bup_user2'@'%' was skipped because the user does not exist.
+#	1737	The grant 'INSERT(b) ON bup_db_grants.s1' for the user 'bup_user2'@'%' was skipped because the user does not exist.
+#	1737	The grant 'SELECT(b) ON bup_db_grants.s1' for the user 'bup_user2'@'%' was skipped because the user does not exist.
+#	1737	The grant 'ALTER ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'ALTER ROUTINE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'CREATE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'CREATE ROUTINE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'CREATE TEMPORARY TABLES ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'CREATE VIEW ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'DELETE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'DROP ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'EVENT ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'EXECUTE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'INDEX ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'INSERT ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'LOCK TABLES ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'REFERENCES ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'SELECT ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'SHOW VIEW ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'TRIGGER ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+#	1737	The grant 'UPDATE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
 SHOW TABLES FROM bup_db_grants;
 Tables_in_bup_db_grants
 s1

=== modified file 'mysql-test/suite/backup/r/backup_errors.result'
--- a/mysql-test/suite/backup/r/backup_errors.result	2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/r/backup_errors.result	2008-11-13 19:34:18 +0000
@@ -110,7 +110,7 @@ delete database files so that check_db_d
 si_objects.cc @ DatabaseObj::do_serialize
 SET DEBUG_SYNC='now SIGNAL db_will_fail';
 Database has been deleted, backup will fail
-ERROR 42000: Unknown database 'db1'
+ERROR HY000: Failed to obtain meta-data for database `db1`
 
 Test that backup fails with error if a table used by 
 a trigger cannot be opened

=== modified file 'mysql-test/suite/backup/r/backup_views.result'
--- a/mysql-test/suite/backup/r/backup_views.result	2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/r/backup_views.result	2008-11-13 19:34:18 +0000
@@ -277,10 +277,14 @@ DROP DATABASE bup_db2;
 Restore database.
 restore database with view dependency to other, non-existing db
 RESTORE FROM 'bup_objectview1.bak';
-ERROR HY000: Could not restore view `bup_db1`.`v5`. Please check the view definition for possible missing dependencies.
+backup_id
+#
 DROP DATABASE bup_db1;
+DROP DATABASE bup_db2;
 RESTORE FROM 'bup_objectview2.bak';
-ERROR HY000: Could not restore view `bup_db2`.`student_details`. Please check the view definition for possible missing dependencies.
+backup_id
+#
+DROP DATABASE bup_db1;
 DROP DATABASE bup_db2;
 RESTORE FROM 'bup_objectview.bak';
 backup_id
@@ -581,10 +585,13 @@ ALTER VIEW alter1 AS SELECT 6;
 
 Testing view selecting from altered view
 
+SELECT * FROM alter1;
+6
+6
 SELECT * FROM alter2;
 ERROR HY000: View 'bup_db1.alter2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
 BACKUP DATABASE bup_db1 TO 'bup_alterview.bak';
-ERROR HY000: View 'bup_db1.alter2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+ERROR HY000: Failed to obtain meta-data for view `bup_db1`.`alter2`
 
 *** EXIT Backup of database with altered view
 

=== modified file 'mysql-test/suite/backup/t/backup_db_grants.test'
--- a/mysql-test/suite/backup/t/backup_db_grants.test	2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/t/backup_db_grants.test	2008-11-13 19:34:18 +0000
@@ -60,6 +60,8 @@ FLUSH PRIVILEGES;
 SHOW GRANTS FOR 'bup_user1'@'%';
 SHOW GRANTS FOR bup_user2;
 SHOW GRANTS FOR 'bup_user3'@'%';
+--error ER_NONEXISTING_GRANT
+SHOW GRANTS FOR 'no_user'@'%';
 
 --echo Run Restore
 --replace_column 1 #

=== modified file 'mysql-test/suite/backup/t/backup_errors.test'
--- a/mysql-test/suite/backup/t/backup_errors.test	2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/t/backup_errors.test	2008-11-13 19:34:18 +0000
@@ -251,7 +251,7 @@ SET DEBUG_SYNC='now SIGNAL db_will_fail'
 
 connection con2;
 --echo Database has been deleted, backup will fail
---error ER_BAD_DB_ERROR
+--error ER_BACKUP_GET_META_DB
 reap;
 
 --echo

=== modified file 'mysql-test/suite/backup/t/backup_views.test'
--- a/mysql-test/suite/backup/t/backup_views.test	2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/t/backup_views.test	2008-11-13 19:34:18 +0000
@@ -205,18 +205,20 @@ DROP DATABASE bup_db2;
 
 --echo restore database with view dependency to other, non-existing db
 
---error ER_BACKUP_CANT_RESTORE_VIEW
+replace_column 1 #;
 RESTORE FROM 'bup_objectview1.bak';
 
 # An incomplete bup_db1 was created by the failing restore operation.
 # Remove it before trying restore of bup_db2.
 DROP DATABASE bup_db1;
+DROP DATABASE bup_db2;
 
---error ER_BACKUP_CANT_RESTORE_VIEW
+replace_column 1 #;
 RESTORE FROM 'bup_objectview2.bak';
 
 # An incomplete bup_db2 was created by the failing restore operation.
 # Remove it before reverting to the working backup image
+DROP DATABASE bup_db1;
 DROP DATABASE bup_db2;
 
 replace_column 1 #;
@@ -349,11 +351,13 @@ ALTER VIEW alter1 AS SELECT 6;
 --echo Testing view selecting from altered view
 --echo 
 
+SELECT * FROM alter1;
+
 --error ER_VIEW_INVALID
 SELECT * FROM alter2;
 
 #fails
---error ER_VIEW_INVALID
+--error ER_BACKUP_GET_META_VIEW
 BACKUP DATABASE bup_db1 TO 'bup_alterview.bak';
 
 --echo 

=== modified file 'sql/backup/backup_aux.h'
--- a/sql/backup/backup_aux.h	2008-10-14 12:08:56 +0000
+++ b/sql/backup/backup_aux.h	2008-11-13 19:34:18 +0000
@@ -42,12 +42,6 @@ storage_engine_ref get_se_by_name(const 
 namespace backup {
 
 /**
-  Constants for appending uniqueness to privileges in backup catalog.
-*/
-#define UNIQUE_PRIV_KEY_LEN 9
-#define UNIQUE_PRIV_KEY_FORMAT "%08lu"
-
-/**
   Local version of LEX_STRING structure.
 
   Defines various constructors for convenience.

=== modified file 'sql/backup/backup_info.cc'
--- a/sql/backup/backup_info.cc	2008-10-27 13:06:21 +0000
+++ b/sql/backup/backup_info.cc	2008-11-13 19:34:18 +0000
@@ -532,7 +532,7 @@ backup::Image_info::Db* Backup_info::add
 
   @returns 0 on success, error code otherwise.
  */
-int Backup_info::add_dbs(List< ::LEX_STRING > &dbs)
+int Backup_info::add_dbs(THD *thd, List< ::LEX_STRING > &dbs)
 {
   using namespace obs;
 
@@ -552,7 +552,7 @@ int Backup_info::add_dbs(List< ::LEX_STR
     
     obs::Obj *obj= get_database(&db_name); // reports errors
 
-    if (obj && !check_db_existence(&db_name))
+    if (obj && !check_db_existence(thd, &db_name))
     {    
       if (!unknown_dbs.is_empty()) // we just compose unknown_dbs list
       {
@@ -727,7 +727,7 @@ int Backup_info::add_db_items(Db &db)
 
     // If this table uses a tablespace, add this tablespace to the catalogue.
 
-    obj= get_tablespace_for_table(m_ctx.m_thd, &db.name(), &tbl->name());
+    obj= find_tablespace_for_table(m_ctx.m_thd, &db.name(), &tbl->name());
 
     if (obj)
     {
@@ -1031,8 +1031,7 @@ Backup_info::add_db_object(Db &db, const
   ulong pos= db.obj_count();
 
   DBUG_ASSERT(obj);
-  String *name= (String *)obj->get_name();
-  DBUG_ASSERT(name);
+  DBUG_ASSERT(obj->get_name());
 
   switch (type) {
 
@@ -1052,22 +1051,6 @@ Backup_info::add_db_object(Db &db, const
 
   }
 
-  /*
-    Generate a unique name for the privilege (grant) objects.
-    Note: this name does not alter the mechanics of the
-          grant objects in si_objects.cc
-  */
-  if (type == BSTREAM_IT_PRIVILEGE)
-  {
-    String new_name;
-    char buff[10];
-    sprintf(buff, UNIQUE_PRIV_KEY_FORMAT, pos);
-    new_name.append(*name);
-    new_name.append(" ");
-    new_name.append(buff);
-    name->copy(new_name);
-  }
-
   /* 
     Add new object to the dependency list. If it is a view, add its
     dependencies first.
@@ -1078,11 +1061,11 @@ Backup_info::add_db_object(Db &db, const
 
   // Get a dep. list node for the object.  
 
-  int res= get_dep_node(db.name(), *name, type, n);
+  int res= get_dep_node(db.name(), *obj->get_name(), type, n);
   
   if (res == get_dep_node_res::ERROR)
   {
-    m_ctx.fatal_error(error, db.name().ptr(), name->ptr());
+    m_ctx.fatal_error(error, db.name().ptr(), obj->get_name()->ptr());
     return NULL;
   }
 
@@ -1097,7 +1080,7 @@ Backup_info::add_db_object(Db &db, const
     if (type == BSTREAM_IT_VIEW)
       if (add_view_deps(*obj))
       {
-        m_ctx.fatal_error(error, db.name().ptr(), name->ptr());
+        m_ctx.fatal_error(error, db.name().ptr(), obj->get_name()->ptr());
         return NULL;
       } 
 
@@ -1114,11 +1097,11 @@ Backup_info::add_db_object(Db &db, const
     objects.
    */
 
-  Dbobj *o= Image_info::add_db_object(db, type, *name, pos);
+  Dbobj *o= Image_info::add_db_object(db, type, *obj->get_name(), pos);
  
   if (!o)
   {
-    m_ctx.fatal_error(error, db.name().ptr(), name->ptr());
+    m_ctx.fatal_error(error, db.name().ptr(), obj->get_name()->ptr());
     return NULL;
   }
 
@@ -1134,7 +1117,7 @@ Backup_info::add_db_object(Db &db, const
   n->obj= o;  
 
   DBUG_PRINT("backup",("Added object %s of type %d from database %s (pos=%lu)",
-                       name->ptr(), type, db.name().ptr(), pos));
+                       obj->get_name()->ptr(), type, db.name().ptr(), pos));
   return o;
 }
 

=== modified file 'sql/backup/backup_info.h'
--- a/sql/backup/backup_info.h	2008-10-27 13:06:21 +0000
+++ b/sql/backup/backup_info.h	2008-11-13 19:34:18 +0000
@@ -38,7 +38,7 @@ class Backup_info: public backup::Image_
 
   bool is_valid();
 
-  int add_dbs(List< ::LEX_STRING >&);
+  int add_dbs(THD *thd, List< ::LEX_STRING >&);
   int add_all_dbs();
 
   int close();

=== modified file 'sql/backup/backup_test.cc'
--- a/sql/backup/backup_test.cc	2008-10-17 11:28:25 +0000
+++ b/sql/backup/backup_test.cc	2008-11-13 19:34:18 +0000
@@ -32,7 +32,7 @@ int execute_backup_test_command(THD *thd
 
   {
     String tmp_db_name("qqq", 3, system_charset_info);
-    DBUG_ASSERT(obs::check_db_existence(&tmp_db_name));
+    DBUG_ASSERT(obs::check_db_existence(thd, &tmp_db_name));
   }
 
   /*
@@ -62,7 +62,7 @@ int execute_backup_test_command(THD *thd
       if (is_internal_db_name(db->get_db_name()))
           continue;
 
-      DBUG_ASSERT(!obs::check_db_existence(db->get_db_name()));
+      DBUG_ASSERT(!obs::check_db_existence(thd, db->get_db_name()));
 
       //
       // List tables..
@@ -247,10 +247,7 @@ int execute_backup_test_command(THD *thd
           protocol->prepare_for_resend();
           protocol->store(const_cast<String*>(db->get_name()));
           protocol->store(const_cast<String*>(grant->get_name()));
-          String user;
-          String host;
-          String *user_host= (String *)grant->get_name();
-          check_user_existence(thd, user_host);
+          check_user_existence(thd, grant);
           protocol->store(C_STRING_WITH_LEN("GRANT"),
                           system_charset_info);
           grant->serialize(thd, &serial);

=== modified file 'sql/backup/image_info.h'
--- a/sql/backup/image_info.h	2008-10-15 15:38:28 +0000
+++ b/sql/backup/image_info.h	2008-11-13 19:34:18 +0000
@@ -1065,16 +1065,8 @@ obs::Obj* Image_info::Dbobj::materialize
     m_obj_ptr= obs::materialize_trigger(db_name, name, ver, &sdata);
     break;
   case BSTREAM_IT_PRIVILEGE:
-  {
-    /*
-      Here we undo the uniqueness suffix for grants.
-    */
-    String new_name;
-    new_name.copy(*name);
-    new_name.length(new_name.length() - UNIQUE_PRIV_KEY_LEN);
-    m_obj_ptr= obs::materialize_db_grant(db_name, &new_name, ver, &sdata);
+    m_obj_ptr= obs::materialize_db_grant(db_name, name, ver, &sdata);
     break;
-  }
   default: m_obj_ptr= NULL;
   }
 

=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc	2008-11-06 18:39:27 +0000
+++ b/sql/backup/kernel.cc	2008-11-13 19:34:18 +0000
@@ -185,7 +185,8 @@ execute_backup_command(THD *thd, LEX *le
     else
     {
       context.write_message(log_level::INFO, "Backing up selected databases");
-      res= info->add_dbs(lex->db_list); // backup databases specified by user
+      /* Backup databases specified by user. */
+      res= info->add_dbs(thd, lex->db_list);
     }
 
     info->close(); // close catalogue after filling it with objects to backup
@@ -1905,24 +1906,30 @@ int bcat_create_item(st_bstream_image_he
 
   if (item->type == BSTREAM_IT_TABLESPACE)
   {
-    // if the tablespace exists, there is nothing more to do
-    if (obs::tablespace_exists(thd, sobj))
+    Obj *ts= obs::find_tablespace(thd, sobj->get_name());
+
+    if (ts)
     {
-      DBUG_PRINT("restore",(" skipping tablespace which exists"));
-      return BSTREAM_OK;
-    }
+      /*
+        A tablespace with the same name exists. We have to check if other
+        attributes are the same as they were.
+      */
 
-    /* 
-      If there is a different tablespace with the same name then we can't 
-      re-create the original tablespace used by tables being restored. We report 
-      this and cancel restore process.
-    */ 
+      if (obs::compare_tablespace_attributes(ts, sobj))
+      {
+        /* The tablespace is the same. There is nothing more to do. */
+        DBUG_PRINT("restore",(" skipping tablespace which exists"));
+        return BSTREAM_OK;
+      }
 
-    Obj *ts= obs::is_tablespace(thd, sobj); 
+      /*
+        A tablespace with the same name exists, but it has been changed
+        since backup.  We can't re-create the original tablespace used by
+        tables being restored. We report this and cancel restore process.
+      */
 
-    if (ts)
-    {
-      DBUG_PRINT("restore",(" tablespace has changed on the server - aborting"));
+      DBUG_PRINT("restore",
+                 (" tablespace has changed on the server - aborting"));
       info->m_ctx.fatal_error(ER_BACKUP_TS_CHANGE, desc);
       return BSTREAM_ERROR;
     }
@@ -1943,12 +1950,14 @@ int bcat_create_item(st_bstream_image_he
             error handling work in WL#4384 with possible implementation
             via a related bug report.
     */
-    if (!obs::check_user_existence(thd, sobj->get_name()))
+    if (!obs::check_user_existence(thd, sobj))
     {
-      info->m_ctx.report_error(log_level::WARNING, 
+      info->m_ctx.report_error(log_level::WARNING,
                                ER_BACKUP_GRANT_SKIPPED,
-                               create_stmt);
-      return BSTREAM_OK; 
+                               obs::grant_get_grant_info(sobj)->ptr(),
+                               obs::grant_get_user_name(sobj)->ptr(),
+                               obs::grant_get_host_name(sobj)->ptr());
+      return BSTREAM_OK;
     }
     /*
       We need to check the grant against the database list to ensure the

=== modified file 'sql/backup/logger.cc'
--- a/sql/backup/logger.cc	2008-10-27 13:06:21 +0000
+++ b/sql/backup/logger.cc	2008-11-13 19:34:18 +0000
@@ -52,10 +52,10 @@ int Logger::write_message(log_level::val
        error.msg= sql_strdup(msg);
      }
 
-     sql_print_error(out);
+     sql_print_error("%s", out);
      if (m_push_errors)
        push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-			   error_code, msg);
+			   error_code, "%s", msg);
      DBUG_PRINT("backup_log",("[ERROR] %s", out));
      
      if (m_state == READY || m_state == RUNNING)
@@ -69,15 +69,15 @@ int Logger::write_message(log_level::val
      return 0;
 
    case log_level::WARNING:
-     sql_print_warning(out);
+     sql_print_warning("%s", out);
      if (m_push_errors)
        push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
-                           error_code, msg);
+                           error_code, "%s", msg);
      DBUG_PRINT("backup_log",("[Warning] %s", out));
      return 0;
 
    case log_level::INFO:
-     sql_print_information(out);
+     sql_print_information("%s", out);
      DBUG_PRINT("backup_log",("[Info] %s", out));
      return 0;
 

=== modified file 'sql/ddl_blocker.cc'
--- a/sql/ddl_blocker.cc	2008-08-19 15:35:29 +0000
+++ b/sql/ddl_blocker.cc	2008-11-13 19:34:18 +0000
@@ -44,7 +44,8 @@ void DDL_blocker_class::destroy_DDL_bloc
   m_instance= NULL;
 }
 
-DDL_blocker_class::DDL_blocker_class()
+DDL_blocker_class::DDL_blocker_class() :
+  m_blocker_thd(NULL)
 {
   pthread_mutex_init(&THR_LOCK_DDL_blocker, MY_MUTEX_INIT_FAST);
   pthread_mutex_init(&THR_LOCK_DDL_is_blocked, MY_MUTEX_INIT_FAST);
@@ -64,6 +65,9 @@ DDL_blocker_class::~DDL_blocker_class()
   pthread_cond_destroy(&COND_DDL_blocker);
   pthread_cond_destroy(&COND_process_blocked);
   pthread_cond_destroy(&COND_DDL_blocker_blocked);
+
+  DBUG_ASSERT(!DDL_blocked);
+  DBUG_ASSERT(!m_blocker_thd);
 }
 
 /**
@@ -124,17 +128,33 @@ my_bool DDL_blocker_class::check_DDL_blo
     Check the ddl blocker condition. Rest until ddl blocker is released.
   */
   pthread_mutex_lock(&THR_LOCK_DDL_is_blocked);
-  thd->enter_cond(&COND_DDL_blocker, &THR_LOCK_DDL_is_blocked,
-                  "DDL blocker: DDL is blocked");
-  while (DDL_blocked && !thd->DDL_exception && (ret == 0))
+
+  DBUG_ASSERT(m_blocker_thd && DDL_blocked ||
+              !m_blocker_thd && !DDL_blocked);
+
+  if (m_blocker_thd && m_blocker_thd == thd)
   {
-    if (thd->backup_wait_timeout == 0)
-      ret = -1;
-    else
-      ret= pthread_cond_timedwait(&COND_DDL_blocker, &THR_LOCK_DDL_is_blocked,
-                                  &ddl_timeout);
+    ret= 0;
+    pthread_mutex_unlock(&THR_LOCK_DDL_is_blocked);
   }
-  thd->exit_cond("DDL blocker: DDL is not blocked");
+  else
+  {
+    thd->enter_cond(&COND_DDL_blocker, &THR_LOCK_DDL_is_blocked,
+                    "DDL blocker: DDL is blocked");
+    while (DDL_blocked &&
+           !thd->DDL_exception &&
+           ret == 0 &&
+           thd->killed == THD::NOT_KILLED)
+    {
+      if (thd->backup_wait_timeout == 0)
+        ret = -1;
+      else
+        ret= pthread_cond_timedwait(&COND_DDL_blocker, &THR_LOCK_DDL_is_blocked,
+                                    &ddl_timeout);
+    }
+    thd->exit_cond("DDL blocker: DDL is not blocked");
+  }
+
   if (ret == 0)
   {
     start_DDL();
@@ -171,12 +191,24 @@ my_bool DDL_blocker_class::block_DDL(THD
     Rest until another blocker is done.
   */
   pthread_mutex_lock(&THR_LOCK_DDL_blocker_blocked);
+
+  if (m_blocker_thd && m_blocker_thd == thd)
+  {
+    /* DDL blocker has been already acquired by the given thd. */
+
+    pthread_mutex_unlock(&THR_LOCK_DDL_blocker);
+
+    DEBUG_SYNC(thd, "after_block_ddl");
+    DBUG_RETURN(TRUE);
+  }
+
   thd->enter_cond(&COND_DDL_blocker_blocked, &THR_LOCK_DDL_blocker_blocked,
                   "DDL blocker: Checking block on blocker");
   while (DDL_blocked)
     pthread_cond_wait(&COND_DDL_blocker_blocked,
                       &THR_LOCK_DDL_blocker_blocked);
   DDL_blocked= TRUE;
+  m_blocker_thd= thd;
   thd->exit_cond("DDL blocker: Ok to block DDL");
 
   /*
@@ -203,6 +235,7 @@ void DDL_blocker_class::unblock_DDL()
 {
   pthread_mutex_lock(&THR_LOCK_DDL_blocker);
   DDL_blocked= FALSE;
+  m_blocker_thd= NULL;
   pthread_cond_broadcast(&COND_DDL_blocker);
   pthread_cond_signal(&COND_DDL_blocker_blocked);
   pthread_mutex_unlock(&THR_LOCK_DDL_blocker);

=== modified file 'sql/ddl_blocker.h'
--- a/sql/ddl_blocker.h	2008-06-25 13:39:04 +0000
+++ b/sql/ddl_blocker.h	2008-11-13 19:34:18 +0000
@@ -5,6 +5,8 @@
  */
 #include "mysql_priv.h"
 
+class THD;
+
 /**
    @class DDL_blocker_class
  
@@ -119,4 +121,6 @@ class DDL_blocker_class
     my_bool DDL_blocked;                     ///< Is blocking operation running
     int DDL_blocks;              ///< Number of DDL operations in progress.
     static DDL_blocker_class *m_instance;    ///< instance var for singleton 
+
+    THD *m_blocker_thd;
 };

=== modified file 'sql/log.cc'
--- a/sql/log.cc	2008-11-06 18:39:27 +0000
+++ b/sql/log.cc	2008-11-13 19:34:18 +0000
@@ -917,8 +917,27 @@ bool Log_to_csv_event_handler::
 
   if (history_data->command)
   {
-    if (table->field[ET_OBH_FIELD_COMMAND]->store(history_data->command,
-        strlen(history_data->command), system_charset_info))
+    LEX_STRING cmd;
+    uint str_end_unused;
+
+    if (String::needs_conversion(0, thd->charset(), system_charset_info,
+                                 &str_end_unused))
+    {
+      if (thd->convert_string(&cmd, system_charset_info,
+                              history_data->command,
+                              strlen(history_data->command),
+                              thd->charset()))
+        goto err;
+
+    }
+    else
+    {
+      cmd.str= history_data->command;
+      cmd.length= strlen(cmd.str);
+    }
+
+    if (table->field[ET_OBH_FIELD_COMMAND]->store(cmd.str, cmd.length,
+                                                  system_charset_info))
       goto err;
     table->field[ET_OBH_FIELD_COMMAND]->set_notnull();
   }

=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h	2008-11-06 18:39:27 +0000
+++ b/sql/mysql_priv.h	2008-11-13 19:34:18 +0000
@@ -1136,6 +1136,11 @@ void init_update_queries(void);
 void free_max_user_conn(void);
 pthread_handler_t handle_bootstrap(void *arg);
 int mysql_execute_command(THD *thd);
+
+class Ed_result;
+
+bool mysql_execute_direct(THD *thd, const LEX_STRING *query, Ed_result *result);
+
 bool do_command(THD *thd);
 bool dispatch_command(enum enum_server_command command, THD *thd,
 		      char* packet, uint packet_length);
@@ -2593,6 +2598,11 @@ inline void lex_string_set(LEX_STRING *l
   lex_str->length= strlen(c_str);
 }
 
+inline int lex_string_cmp(const LEX_STRING *s1, const LEX_STRING *s2)
+{
+  return strncmp(s1->str, s2->str, min(s1->length, s2->length));
+}
+
 bool load_charset(MEM_ROOT *mem_root,
                   Field *field,
                   CHARSET_INFO *dflt_cs,

=== modified file 'sql/protocol.cc'
--- a/sql/protocol.cc	2008-10-20 09:16:47 +0000
+++ b/sql/protocol.cc	2008-11-13 19:34:18 +0000
@@ -440,6 +440,8 @@ void net_end_statement(THD *thd)
   if (thd->main_da.is_sent)
     return;
 
+  thd->main_da.is_sent= TRUE;
+
   switch (thd->main_da.status()) {
   case Diagnostics_area::DA_ERROR:
     /* The query failed, send error to log and abort bootstrap. */
@@ -469,7 +471,6 @@ void net_end_statement(THD *thd)
                 0, 0, NULL);
     break;
   }
-  thd->main_da.is_sent= TRUE;
   DBUG_VOID_RETURN;
 }
 
@@ -800,7 +801,6 @@ bool Protocol::store(I_List<i_string>* s
   return store((char*) tmp.ptr(), len,  tmp.charset());
 }
 
-
 /****************************************************************************
   Functions to handle the simple (default) protocol where everything is
   This protocol is the one that is used by default between the MySQL server
@@ -1417,3 +1417,448 @@ bool Protocol_binary::send_out_parameter
 
   return FALSE;
 }
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Ed_result::Ed_result(MEM_ROOT *mem_root) :
+  m_mem_root(mem_root),
+  m_cur_rs(NULL),
+  m_status(Diagnostics_area::DA_EMPTY),
+  m_server_status(0),
+  m_total_warn_count(0),
+  m_affected_rows(0),
+  m_last_insert_id(0),
+  m_sql_errno(0)
+{
+  m_message[0]= 0;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_result::add_result_set(List<Item> *col_metadata)
+{
+  Ed_result_set *rs= Ed_result_set::create(m_mem_root, col_metadata);
+
+  if (!rs)
+    return TRUE;
+
+  m_cur_rs= rs;
+
+  return push_back(rs, m_mem_root) ? TRUE : FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_result::on_end_statement(THD *thd)
+{
+  DBUG_ASSERT(m_status == Diagnostics_area::DA_EMPTY);
+
+  m_status= thd->main_da.status();
+
+  if (m_status == Diagnostics_area::DA_OK)
+  {
+    m_server_status= thd->main_da.server_status();
+    m_total_warn_count= thd->main_da.total_warn_count();
+    m_affected_rows= thd->main_da.affected_rows();
+    m_last_insert_id= thd->main_da.last_insert_id();
+
+    strmake(m_message, thd->main_da.message(), sizeof (m_message) - 1);
+  }
+  else if (m_status == Diagnostics_area::DA_EOF)
+  {
+    m_server_status= thd->main_da.server_status();
+    m_total_warn_count= thd->main_da.total_warn_count();
+  }
+  else if (m_status == Diagnostics_area::DA_ERROR)
+  {
+    m_sql_errno= thd->main_da.sql_errno();
+    strmake(m_message, thd->main_da.message(), sizeof (m_message) - 1);
+  }
+
+  List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+  while (true)
+  {
+    MYSQL_ERROR *err= it++;
+
+    if (!err)
+      break;
+
+    MYSQL_ERROR *err_copy= new (m_mem_root) MYSQL_ERROR(m_mem_root, err);
+
+    if (!err_copy || m_warnings.push_back(err_copy, m_mem_root))
+      return TRUE;
+  }
+
+  return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Ed_result_set *
+Ed_result_set::create(MEM_ROOT *mem_root, List<Item> *col_metadata)
+{
+  Ed_result_set *rs= new (mem_root) Ed_result_set(mem_root);
+
+  if (!rs || rs->init(col_metadata))
+    return NULL;
+
+  return rs;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_result_set::init(List<Item> *col_metadata)
+{
+  m_metadata= Ed_result_set_metadata::create(m_mem_root, col_metadata);
+
+  return m_metadata == NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+Ed_row *Ed_result_set::add_row()
+{
+  Ed_row *row= Ed_row::create(m_mem_root, m_metadata);
+
+  if (!row)
+    return NULL;
+
+  m_cur_row= row;
+
+  return m_data.push_back(row, m_mem_root) ? NULL : row;
+}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Ed_result_set_metadata *
+Ed_result_set_metadata::create(MEM_ROOT *mem_root,
+                               List<Item> *col_metadata)
+{
+  Ed_result_set_metadata *md= new (mem_root) Ed_result_set_metadata();
+
+  if (!md || md->init(mem_root, col_metadata))
+    return NULL;
+
+  return md;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_result_set_metadata::init(MEM_ROOT *mem_root, List<Item> *col_metadata)
+{
+  if (!col_metadata)
+    return FALSE;
+
+  m_metadata= new (mem_root) Send_field[col_metadata->elements];
+
+  if (!m_metadata)
+    return TRUE;
+
+  m_num_columns= col_metadata->elements;
+
+  List_iterator_fast<Item> it(*col_metadata);
+
+  int i= 0;
+  for (Item *column= it++; column; column= it++)
+    column->make_field(&m_metadata[i]);
+
+  return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Ed_row *Ed_row::create(MEM_ROOT *mem_root,
+                       const Ed_result_set_metadata *metadata)
+{
+  DBUG_ASSERT(metadata);
+
+  Ed_row *row= new (mem_root) Ed_row(mem_root, metadata);
+
+  if (!row || row->init())
+    return NULL;
+
+  return row;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_row::init()
+{
+  m_columns= new (m_mem_root) Ed_column[m_metadata->get_num_columns()];
+
+  return m_columns == NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_row::add_null()
+{
+  if (m_cur_column >= m_metadata->get_num_columns())
+    return TRUE;
+
+  ++m_cur_column;
+
+  return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_row::add_column(const void *data_ptr, int data_length)
+{
+  if (m_cur_column >= m_metadata->get_num_columns())
+    return TRUE;
+
+  m_columns[m_cur_column++].set_data(m_mem_root, data_ptr, data_length);
+
+  return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Protocol_local: a protocol for retrieving result sets from the server
+// locally.
+//
+///////////////////////////////////////////////////////////////////////////
+
+void Protocol_local::prepare_for_resend()
+{
+  DBUG_ASSERT(m_result);
+
+  Ed_result_set *rs= m_result->get_cur_result_set();
+
+  DBUG_ASSERT(rs);
+
+  rs->add_row();
+}
+
+bool Protocol_local::write()
+{
+  return FALSE;
+}
+
+bool Protocol_local::store_null()
+{
+  DBUG_ASSERT(m_result);
+
+  Ed_result_set *rs= m_result->get_cur_result_set();
+  Ed_row *row= rs->get_cur_row();
+  DBUG_ASSERT(row);
+
+  return row->add_null();
+}
+
+bool Protocol_local::store_string(const char *str,
+                                  int length,
+                                  CHARSET_INFO *src_cs,
+                                  CHARSET_INFO *dst_cs)
+{
+  DBUG_ASSERT(m_result);
+
+  Ed_result_set *rs= m_result->get_cur_result_set();
+  Ed_row *row= rs->get_cur_row();
+  DBUG_ASSERT(row);
+
+  /* 'dst_cs' is set 0 when client issued SET character_set_results = NULL */
+
+  if (!dst_cs ||
+      my_charset_same(src_cs, dst_cs) ||
+      src_cs == &my_charset_bin ||
+      dst_cs == &my_charset_bin)
+  {
+    return row->add_column(str, length);
+  }
+
+  /* Store with conversion */
+  uint dummy_errors;
+
+  if (convert->copy(str, length, src_cs, dst_cs, &dummy_errors))
+    return TRUE;
+
+  return row->add_column(convert->ptr(), convert->length());
+}
+
+bool Protocol_local::store_tiny(longlong value)
+{
+  Ed_result_set *rs= m_result->get_cur_result_set();
+  const Ed_result_set_metadata *md= rs->get_metadata();
+  Ed_row *row= rs->get_cur_row();
+
+  int cur_col_idx= row->get_cur_column();
+
+  const Send_field *col_md= md->get_column(cur_col_idx);
+
+  char v= (char) value;
+
+  return row->add_column(&v, 1);
+}
+
+bool Protocol_local::store_short(longlong value)
+{
+  Ed_result_set *rs= m_result->get_cur_result_set();
+  const Ed_result_set_metadata *md= rs->get_metadata();
+  Ed_row *row= rs->get_cur_row();
+
+  int cur_col_idx= row->get_cur_column();
+
+  const Send_field *col_md= md->get_column(cur_col_idx);
+
+  int16 v= (int16) value;
+
+  return row->add_column(&v, 2);
+}
+
+bool Protocol_local::store_long(longlong value)
+{
+  Ed_result_set *rs= m_result->get_cur_result_set();
+  const Ed_result_set_metadata *md= rs->get_metadata();
+  Ed_row *row= rs->get_cur_row();
+
+  int cur_col_idx= row->get_cur_column();
+
+  const Send_field *col_md= md->get_column(cur_col_idx);
+
+  int32 v= (int32) value;
+
+  return row->add_column(&v, 4);
+}
+
+bool Protocol_local::store_longlong(longlong value, bool unsigned_flag)
+{
+  Ed_result_set *rs= m_result->get_cur_result_set();
+  const Ed_result_set_metadata *md= rs->get_metadata();
+  Ed_row *row= rs->get_cur_row();
+
+  int cur_col_idx= row->get_cur_column();
+
+  const Send_field *col_md= md->get_column(cur_col_idx);
+
+  int64 v= (int64) value;
+
+  return row->add_column(&v, 8);
+}
+
+bool Protocol_local::store_decimal(const my_decimal *value)
+{
+  Ed_result_set *rs= m_result->get_cur_result_set();
+  const Ed_result_set_metadata *md= rs->get_metadata();
+  Ed_row *row= rs->get_cur_row();
+
+  int cur_col_idx= row->get_cur_column();
+
+  const Send_field *col_md= md->get_column(cur_col_idx);
+
+  char buf[DECIMAL_MAX_STR_LENGTH];
+  String str(buf, sizeof (buf), &my_charset_bin);
+  my_decimal2string(E_DEC_FATAL_ERROR, value, 0, 0, 0, &str);
+
+  return row->add_column(str.ptr(), str.length());
+}
+
+bool Protocol_local::store(const char *str,
+                           size_t length,
+                           CHARSET_INFO *src_cs)
+{
+  CHARSET_INFO *dst_cs= this->thd->variables.character_set_results;
+  return store_string(str, length, src_cs, dst_cs);
+}
+
+bool Protocol_local::store(const char *str,
+                           size_t length,
+                           CHARSET_INFO *src_cs,
+                           CHARSET_INFO *dst_cs)
+{
+  return store_string(str, length, src_cs, dst_cs);
+}
+
+bool Protocol_local::store(MYSQL_TIME *time)
+{
+  Ed_result_set *rs= m_result->get_cur_result_set();
+  const Ed_result_set_metadata *md= rs->get_metadata();
+  Ed_row *row= rs->get_cur_row();
+
+  int cur_col_idx= row->get_cur_column();
+
+  const Send_field *col_md= md->get_column(cur_col_idx);
+
+  return row->add_column(time, sizeof (MYSQL_TIME));
+}
+
+bool Protocol_local::store_date(MYSQL_TIME *time)
+{
+  Ed_result_set *rs= m_result->get_cur_result_set();
+  const Ed_result_set_metadata *md= rs->get_metadata();
+  Ed_row *row= rs->get_cur_row();
+
+  int cur_col_idx= row->get_cur_column();
+
+  const Send_field *col_md= md->get_column(cur_col_idx);
+
+  return row->add_column(time, sizeof (MYSQL_TIME));
+}
+
+bool Protocol_local::store_time(MYSQL_TIME *time)
+{
+  Ed_result_set *rs= m_result->get_cur_result_set();
+  const Ed_result_set_metadata *md= rs->get_metadata();
+  Ed_row *row= rs->get_cur_row();
+
+  int cur_col_idx= row->get_cur_column();
+
+  const Send_field *col_md= md->get_column(cur_col_idx);
+
+  return row->add_column(time, sizeof (MYSQL_TIME));
+}
+
+bool Protocol_local::store(float value, uint32 decimals, String *buffer)
+{
+  Ed_result_set *rs= m_result->get_cur_result_set();
+  const Ed_result_set_metadata *md= rs->get_metadata();
+  Ed_row *row= rs->get_cur_row();
+
+  int cur_col_idx= row->get_cur_column();
+
+  const Send_field *col_md= md->get_column(cur_col_idx);
+
+  return row->add_column(&value, sizeof (float));
+}
+
+bool Protocol_local::store(double value, uint32 decimals, String *buffer)
+{
+  Ed_result_set *rs= m_result->get_cur_result_set();
+  const Ed_result_set_metadata *md= rs->get_metadata();
+  Ed_row *row= rs->get_cur_row();
+
+  int cur_col_idx= row->get_cur_column();
+
+  const Send_field *col_md= md->get_column(cur_col_idx);
+
+  return row->add_column(&value, sizeof (double));
+}
+
+bool Protocol_local::store(Field *field)
+{
+  if (field->is_null())
+    return store_null();
+  return field->send_binary(this);
+}
+
+bool Protocol_local::send_result_set_metadata(List<Item> *columns, uint)
+{
+  DBUG_ASSERT(m_result);
+
+  return m_result->add_result_set(columns);
+}
+
+bool Protocol_local::send_out_parameters(List<Item_param> *sp_params)
+{
+  return FALSE;
+}
+
+#ifdef EMBEDDED_LIBRARY
+void Protocol_local::remove_last_row()
+{ }
+#endif

=== modified file 'sql/protocol.h'
--- a/sql/protocol.h	2008-08-07 17:52:43 +0000
+++ b/sql/protocol.h	2008-11-13 19:34:18 +0000
@@ -114,6 +114,8 @@ public:
     */
   };
   virtual enum enum_protocol_type type()= 0;
+
+  virtual bool on_end_statement() { return FALSE; }
 };
 
 
@@ -191,3 +193,286 @@ uchar *net_store_data(uchar *to,const uc
 uchar *net_store_data(uchar *to,int32 from);
 uchar *net_store_data(uchar *to,longlong from);
 
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Protocol_void: an implementation of Protocol, which just trashes results.
+*/
+
+class Protocol_void :public Protocol
+{
+public:
+  inline Protocol_void(THD *thd)
+    : Protocol(thd)
+  { }
+
+public:
+  virtual inline void prepare_for_resend() { }
+  virtual inline bool write() { return FALSE; }
+  virtual inline bool store_null() { return FALSE; }
+  virtual inline bool store_tiny(longlong) { return FALSE; }
+  virtual inline bool store_short(longlong) { return FALSE; }
+  virtual inline bool store_long(longlong) { return FALSE; }
+  virtual inline bool store_longlong(longlong, bool) { return FALSE; }
+  virtual inline bool store_decimal(const my_decimal *) { return FALSE; }
+  virtual inline bool store(const char *, size_t, CHARSET_INFO *)
+  { return FALSE; }
+  virtual inline bool store(const char *, size_t,
+                            CHARSET_INFO *, CHARSET_INFO *)
+  { return FALSE; }
+  virtual inline bool store(MYSQL_TIME *) { return FALSE; }
+  virtual inline bool store_date(MYSQL_TIME *) { return FALSE; }
+  virtual inline bool store_time(MYSQL_TIME *) { return FALSE; }
+  virtual inline bool store(float, uint32, String *) { return FALSE; }
+  virtual inline bool store(double, uint32, String *) { return FALSE; }
+  virtual inline bool store(Field *) { return FALSE; }
+
+  virtual inline bool send_result_set_metadata(List<Item> *, uint)
+  { return FALSE; }
+  virtual inline bool send_out_parameters(List<Item_param> *) { return FALSE; }
+#ifdef EMBEDDED_LIBRARY
+  void remove_last_row() { }
+#endif
+  virtual enum enum_protocol_type type() { return PROTOCOL_TEXT; /* FIXME */ };
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  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:
+  inline Ed_column()
+  {
+    str= NULL;
+    length= 0;
+  }
+
+  inline void set_data(MEM_ROOT *mem_root, const void *p_str, int p_length)
+  {
+    str= (char *) memdup_root(mem_root, p_str, p_length);
+    length= p_length;
+  }
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Ed_result_set_metadata -- a class representing result set metadata. Used
+  with Ed_result_set and Protocol_local.
+*/
+
+class Ed_result_set_metadata : public Sql_alloc
+{
+public:
+  static Ed_result_set_metadata *create(MEM_ROOT *mem_root,
+                                        List<Item> *col_metadata);
+
+public:
+  inline int get_num_columns() const { return m_num_columns; }
+
+  inline const Send_field *get_column(int idx) const
+  { return &m_metadata[idx]; }
+
+private:
+  inline Ed_result_set_metadata() :
+    m_num_columns(0),
+    m_metadata(NULL)
+  { }
+
+private:
+  bool init(MEM_ROOT *mem_root, List<Item> *col_metadata);
+
+private:
+  int m_num_columns;
+  Send_field *m_metadata;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Ed_row -- a class representing a row in a result set. Used with
+  Ed_result_set and Protocol_local.
+*/
+class Ed_row : public Sql_alloc
+{
+public:
+  static Ed_row *create(MEM_ROOT *mem_root,
+                        const Ed_result_set_metadata *metadata);
+
+public:
+  bool add_null();
+  bool add_column(const void *data_ptr, int data_length);
+
+public:
+  inline const Ed_result_set_metadata *get_metadata() const
+  { return m_metadata; }
+
+  inline const Ed_column *get_column(int idx) const
+  { return &m_columns[idx]; }
+
+  inline const Ed_column *operator [](int idx) const
+  { return get_column(idx); }
+
+  inline int get_cur_column() const { return m_cur_column; }
+
+private:
+  inline Ed_row(MEM_ROOT *mem_root,
+                const Ed_result_set_metadata *metadata) :
+    m_mem_root(mem_root),
+    m_metadata(metadata),
+    m_cur_column(0)
+  { }
+
+  bool init();
+
+private:
+  MEM_ROOT *m_mem_root;
+  const Ed_result_set_metadata *m_metadata;
+  Ed_column *m_columns;
+  int m_cur_column;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Ed_result_set -- a class representing one result set. Used with Ed_result
+  and Protocol_local.
+*/
+class Ed_result_set : public Sql_alloc
+{
+public:
+  static Ed_result_set *create(MEM_ROOT *mem_root,
+                               List<Item> *col_metadata);
+
+private:
+  inline Ed_result_set(MEM_ROOT *mem_root) :
+    m_mem_root(mem_root),
+    m_metadata(NULL),
+    m_cur_row(NULL)
+  { }
+
+private:
+  bool init(List<Item> *col_metadata);
+
+public:
+  inline const Ed_result_set_metadata *get_metadata() const
+  { return m_metadata; }
+
+  inline List<Ed_row> *data()      { return &m_data;      }
+  inline Ed_row *get_cur_row()     { return m_cur_row;    }
+
+  Ed_row *add_row();
+
+private:
+  MEM_ROOT *m_mem_root;
+
+  Ed_result_set_metadata *m_metadata;
+  List<Ed_row> m_data;
+
+  Ed_row *m_cur_row;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/*
+  Ed_result -- a class representing results for an SQL statement execution.
+  Used with Protocol_local.
+*/
+class Ed_result : public List<Ed_result_set>
+{
+public:
+  Ed_result(MEM_ROOT *mem_root);
+
+  inline ~Ed_result()
+  { }
+
+public:
+  inline Ed_result_set *get_cur_result_set() { return m_cur_rs; }
+
+  bool add_result_set(List<Item> *col_metadata);
+
+public:
+  bool on_end_statement(THD *thd);
+
+public:
+  inline uint get_status() const { return m_status; }
+  inline uint get_server_status() const { return m_server_status; }
+  inline uint get_total_warn_count() const { return m_total_warn_count; }
+  inline ha_rows get_affected_rows() const { return m_affected_rows; }
+  inline ulonglong get_last_insert_id() const { return m_last_insert_id; }
+  inline uint get_sql_errno() const { return m_sql_errno; }
+  inline const char *get_message() const { return m_message; }
+  inline List<MYSQL_ERROR> *get_warnings() { return &m_warnings; }
+
+private:
+  MEM_ROOT *m_mem_root;
+  Ed_result_set *m_cur_rs;
+
+private:
+  /*
+    NOTE: this section will be refactored / eliminated when warning
+    support in THD is refactored.
+  */
+  uint m_status;
+  uint m_server_status;
+  uint m_total_warn_count;
+  ha_rows m_affected_rows;
+  ulonglong m_last_insert_id;
+  uint m_sql_errno;
+  char m_message[MYSQL_ERRMSG_SIZE];
+  List<MYSQL_ERROR> m_warnings;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+  Protocol_local: a protocol for retrieving result sets from the server
+  locally.
+*/
+class Protocol_local :public Protocol
+{
+public:
+  inline Protocol_local(THD *thd, Ed_result *result)
+    : Protocol(thd),
+      m_result(result)
+  { }
+
+public:
+  virtual void prepare_for_resend();
+  virtual bool write();
+  virtual bool store_null();
+  virtual bool store_tiny(longlong from);
+  virtual bool store_short(longlong from);
+  virtual bool store_long(longlong from);
+  virtual bool store_longlong(longlong from, bool unsigned_flag);
+  virtual bool store_decimal(const my_decimal *);
+  virtual bool store(const char *from, size_t length, CHARSET_INFO *cs);
+  virtual bool store(const char *from, size_t length,
+                     CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
+  virtual bool store(MYSQL_TIME *time);
+  virtual bool store_date(MYSQL_TIME *time);
+  virtual bool store_time(MYSQL_TIME *time);
+  virtual bool store(float value, uint32 decimals, String *buffer);
+  virtual bool store(double value, uint32 decimals, String *buffer);
+  virtual bool store(Field *field);
+
+  virtual bool send_result_set_metadata(List<Item> *list, uint flags);
+  virtual bool send_out_parameters(List<Item_param> *sp_params);
+#ifdef EMBEDDED_LIBRARY
+  void remove_last_row();
+#endif
+  virtual enum enum_protocol_type type() { return PROTOCOL_TEXT; /* FIXME */ };
+  virtual bool on_end_statement() { return m_result->on_end_statement(thd); };
+
+private:
+  bool store_string(const char *str, int length,
+                    CHARSET_INFO *src_cs, CHARSET_INFO *dst_cs);
+
+private:
+  Ed_result *m_result;
+};
+

=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt	2008-11-07 17:07:58 +0000
+++ b/sql/share/errmsg.txt	2008-11-13 19:34:18 +0000
@@ -6397,7 +6397,7 @@ ER_BACKUP_GET_META_PRIV
 ER_BACKUP_CANT_RESTORE_PRIV
         eng "Could not execute grant '%-.64s'."
 ER_BACKUP_GRANT_SKIPPED
-        eng "The grant '%-.64s' was skipped because the user does not exist."
+        eng "The grant '%-.64s' for the user '%-.64s'@'%-.64s' was skipped because the user does not exist."
 ER_BACKUP_GRANT_WRONG_DB
         eng "The grant '%-.64s' failed. Database not included in the backup image."
 ER_BACKUP_LOGPATHS

=== modified file 'sql/si_objects.cc'
--- a/sql/si_objects.cc	2008-10-27 13:06:21 +0000
+++ b/sql/si_objects.cc	2008-11-13 19:34:18 +0000
@@ -26,333 +26,105 @@
 #include "sp.h"
 #include "sp_head.h" // for sp_add_to_query_tables().
 
-TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list); // defined in sql_show.cc
-
 DDL_blocker_class *DDL_blocker= NULL;
 
+#define QUERY_BUFFER_SIZE 4096
+
 ///////////////////////////////////////////////////////////////////////////
 
 namespace {
 
-// Helper methods
-
-/**
-  Execute the SQL string passed.
-
-  This is a private helper function to the implementation.
-*/
-int silent_exec(THD *thd, String *query)
-{
-  Vio *save_vio= thd->net.vio;
-
-  DBUG_PRINT("si_objects",("executing %s",query->c_ptr()));
-
-  /*
-    Note: the change net.vio idea taken from execute_init_command in
-    sql_parse.cc
-   */
-  thd->net.vio= 0;
-
-  thd->query=         query->c_ptr();
-  thd->query_length=  query->length();
-
-  thd->set_time();
-  pthread_mutex_lock(&::LOCK_thread_count);
-  thd->query_id= ::next_query_id();
-  pthread_mutex_unlock(&::LOCK_thread_count);
-
-  /*
-    @todo The following is a work around for online backup and the DDL blocker.
-          It should be removed when the generalized solution is in place.
-          This is needed to ensure the restore (which uses DDL) is not blocked
-          when the DDL blocker is engaged.
-  */
-  thd->DDL_exception= TRUE;
-
-  /*
-    Note: This is a copy and paste from the code in sql_parse.cc.
-          See "case COM_QUERY:".
-  */
-  const char *found_semicolon= thd->query;
-  char *packet_end= thd->query + thd->query_length;
-  mysql_parse(thd, thd->query, thd->query_length, &found_semicolon);
-  while (!thd->killed && found_semicolon && !thd->is_error())
-  {
-    char *next_packet= (char*) found_semicolon;
-    /*
-      Multiple queries exits, execute them individually
-    */
-    close_thread_tables(thd);
-    ulong length= (ulong)(packet_end - next_packet);
-
-    /* Remove garbage at start of query */
-    while (my_isspace(thd->charset(), *next_packet) && length > 0)
-    {
-      next_packet++;
-      length--;
-    }
-    pthread_mutex_lock(&LOCK_thread_count);
-    thd->query_length= length;
-    thd->query= next_packet;
-    thd->query_id= next_query_id();
-    thd->set_time(); /* Reset the query start time. */
-    /* TODO: set thd->lex->sql_command to SQLCOM_END here */
-    pthread_mutex_unlock(&LOCK_thread_count);
-    mysql_parse(thd, next_packet, length, & found_semicolon);
-  }
-
-  close_thread_tables(thd);
+///////////////////////////////////////////////////////////////////////////
+//
+// Type identifiers in INFORMATION_SCHEMA.
+//
+///////////////////////////////////////////////////////////////////////////
 
-  thd->net.vio= save_vio;
+const LEX_STRING IS_TYPE_TABLE= { C_STRING_WITH_LEN("BASE TABLE") };
+const LEX_STRING IS_TYPE_VIEW=  { C_STRING_WITH_LEN("VIEW") };
 
-  if (thd->is_error())
-  {
-    DBUG_PRINT("restore",
-              ("error executing query %s!", thd->query));
-    DBUG_PRINT("restore",("last error (%d): %s",thd->net.last_errno
-                                               ,thd->net.last_error));
-    return thd->net.last_errno ? (int)thd->net.last_errno : -1;
-  }
-
-  return 0;
-}
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
 
-/*
-  This method gets the create statement for a procedure or function.
-*/
-bool serialize_routine(THD *thd,
-                     int type,
-                      String db_name,
-                      String r_name,
-                      String *string)
+void log_warnings(Ed_result *result)
 {
-  int ret= 0;
-  sp_head *sp;
-  sp_name *routine_name;
-  LEX_STRING sql_mode;
-  DBUG_ENTER("serialize_routine");
-  DBUG_PRINT("serialize_routine", ("name: %s@%s", db_name.c_ptr(),
-             r_name.c_ptr()));
-
-  DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE || type == TYPE_ENUM_FUNCTION);
-  sp_cache **cache = type == TYPE_ENUM_PROCEDURE ?
-                     &thd->sp_proc_cache : &thd->sp_func_cache;
-  LEX_STRING db;
-  db.str= db_name.c_ptr();
-  db.length= db_name.length();
-  LEX_STRING name;
-  name.str= r_name.c_ptr();
-  name.length= r_name.length();
-  routine_name= new sp_name(db, name, true);
-  routine_name->init_qname(thd);
-  if (type == TYPE_ENUM_PROCEDURE)
-    thd->variables.max_sp_recursion_depth++;
-  if ((sp= sp_find_routine(thd, type, routine_name, cache, FALSE)))
-  {
-    sys_var_thd_sql_mode::symbolic_mode_representation(thd,
-      sp->m_sql_mode, &sql_mode);
-    Stored_program_creation_ctx *sp_ctx= sp->get_creation_ctx();
+  List_iterator_fast<MYSQL_ERROR> it(*result->get_warnings());
 
-    /*
-      Prepend sql_mode command.
-    */
-    string->append("SET SQL_MODE = '");
-    string->append(sql_mode.str);
-    string->append("'; ");
-
-    /*
-      append character set client charset information
-    */
-    string->append("SET CHARACTER_SET_CLIENT = '");
-    string->append(sp_ctx->get_client_cs()->csname);
-    string->append("'; ");
-
-    /*
-      append collation_connection information
-    */
-    string->append("SET COLLATION_CONNECTION = '");
-    string->append(sp_ctx->get_connection_cl()->name);
-    string->append("'; ");
-
-    /*
-      append collation_connection information
-    */
-    string->append("SET COLLATION_DATABASE = '");
-    string->append(sp_ctx->get_db_cl()->name);
-    string->append("'; ");
-
-    string->append(sp->m_defstr.str);
-  }
-  else
+  while (true)
   {
-    string->length(0);
-    ret= TRUE;
-  }
-  if (type == TYPE_ENUM_PROCEDURE)
-    thd->variables.max_sp_recursion_depth--;
-  DBUG_RETURN(ret);
-}
-
-/*
-  This method calls silent_exec() while saving the context
-  information before the call and restoring after the call.
-
-  If save_timezone, it also saves and restores the timezone.
-*/
-bool execute_with_ctx(THD *thd, String *query, bool save_timezone)
-{
-  bool ret= false;
-  ulong orig_sql_mode;
-  CHARSET_INFO *orig_char_set_client;
-  CHARSET_INFO *orig_coll_conn;
-  CHARSET_INFO *orig_coll_db;
-  Time_zone *tm_zone;
-  DBUG_ENTER("Obj::execute_with_ctx()");
-
-  /*
-    Preserve SQL_MODE, CHARACTER_SET_CLIENT, COLLATION_CONNECTION,
-    and COLLATION_DATABASE.
-  */
-  orig_sql_mode= thd->variables.sql_mode;
-  orig_char_set_client= thd->variables.character_set_client;
-  orig_coll_conn= thd->variables.collation_connection;
-  orig_coll_db= thd->variables.collation_database;
-
-  /*
-    Preserve timezone.
-  */
-  if (save_timezone)
-    tm_zone= thd->variables.time_zone;
-
-  ret= silent_exec(thd, query);
-
-  /*
-    Restore SQL_MODE, CHARACTER_SET_CLIENT, COLLATION_CONNECTION,
-    and COLLATION_DATABASE.
-  */
-  thd->variables.sql_mode= orig_sql_mode;
-  thd->variables.character_set_client= orig_char_set_client;
-  thd->variables.collation_connection= orig_coll_conn;
-  thd->variables.collation_database= orig_coll_db;
-
-  /*
-    Restore timezone.
-  */
-  if (save_timezone)
-    thd->variables.time_zone= tm_zone;
+    MYSQL_ERROR *err= it++;
 
-  DBUG_RETURN(ret);
-}
-
-/*
-  Drops an object.
+    if (!err)
+      break;
 
-  obj_name is the name of the object e.g., DATABASE, PROCEDURE, etc.
-  name1 is the db name  (blank for database objects)
-  name2 is the name of the object
-*/
-bool drop_object(THD *thd, const char *obj_name, String *name1, String *name2)
-{
-  DBUG_ENTER("Obj::drop_object()");
-  String cmd;
-  cmd.length(0);
-  cmd.append("DROP ");
-  cmd.append(obj_name);
-  cmd.append(" IF EXISTS ");
-  if (name1 && (name1->length() > 0))
-  {
-    append_identifier(thd, &cmd, name1->c_ptr(), name1->length());
-    cmd.append(".");
+    sql_print_information("SQL warning: code: %u; level: %d; msg: %s",
+                          (unsigned int) err->code,
+                          (int) err->level,
+                          (const char *) err->msg);
   }
-  append_identifier(thd, &cmd, name2->c_ptr(), name2->length());
-  DBUG_RETURN(silent_exec(thd, &cmd));
 }
 
-/**
-  Open given table in @c INFORMATION_SCHEMA database.
-
-  This is a private helper function to the implementation.
-
-  @param[in] thd  Thread context
-  @param[in] st   Schema table enum
-  @param[in] db_list List of databases for select condition
-
-  @note: The select condition is designed to form a WHERE clause based on
-  the database/schema column of the information_schema views. Most views have
-  a database/schema column but for those that do not, you must ignore the
-  selection condition by passing db_list = NULL.
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
 
-  @retval TABLE* The schema table
-*/
-TABLE* open_schema_table(THD *thd, ST_SCHEMA_TABLE *st, List<LEX_STRING> *db_list)
+bool run_query(THD *thd, const LEX_STRING *query, Ed_result *result)
 {
-  TABLE *t;
-  TABLE_LIST arg;
-  my_bitmap_map *old_map;
-
-  bzero( &arg, sizeof(TABLE_LIST) );
+  DBUG_ENTER("run_query()");
+  DBUG_PRINT("run_query",
+             ("query: %.*s",
+              (int) query->length, (const char *) query->str));
 
-  // set context for create_schema_table call
-  arg.schema_table= st;
-  arg.alias=        NULL;
-  arg.select_lex=   NULL;
+  ulong sql_mode_saved= thd->variables.sql_mode;
+  CHARSET_INFO *client_cs_saved= thd->variables.character_set_client;
+  CHARSET_INFO *results_cs_saved= thd->variables.character_set_results;
+  CHARSET_INFO *connection_cl_saved= thd->variables.collation_connection;
 
-  t= create_schema_table(thd,&arg); // Note: callers must free t.
-
-  if( !t ) return NULL; // error!
+  thd->variables.sql_mode= 0;
 
   /*
-   Temporarily set thd->lex->wild to NULL to keep st->fill_table
-   happy.
+    Temporary tables should be ignored while looking for table structures.
+    Backup wants to backup ordinary tables, not temporary ones.
   */
-  ::String *wild= thd->lex->wild;
-  ::enum_sql_command command= thd->lex->sql_command;
-
-  thd->lex->wild = NULL;
-  thd->lex->sql_command = enum_sql_command(0);
+  TABLE *tmp_tables_saved= thd->temporary_tables;
+  thd->temporary_tables= NULL;
 
-  // context for fill_table
-  arg.table= t;
-
-  old_map= tmp_use_all_columns(t, t->read_set);
+  /* A query is in UTF8 (internal character set). */
+  thd->variables.character_set_client= system_charset_info;
 
   /*
-    Create a selection condition only if db_list is defined.
+    Ed_results should be fetched without any conversion (in the original
+    character set) in order to preserve object definition query intact.
   */
-  if (db_list)
-    st->fill_table(thd, &arg, obs::create_db_select_condition(thd, t, db_list));
-  else
-    st->fill_table(thd, &arg, NULL);
+  thd->variables.character_set_results= &my_charset_bin;
+  thd->variables.collation_connection= system_charset_info;
+  thd->update_charset();
 
-  tmp_restore_column_map(t->read_set, old_map);
+  bool rc= mysql_execute_direct(thd, query, result);
 
-  // undo changes to thd->lex
-  thd->lex->wild= wild;
-  thd->lex->sql_command= command;
+  thd->variables.sql_mode= sql_mode_saved;
+  thd->variables.collation_connection= connection_cl_saved;
+  thd->variables.character_set_results= results_cs_saved;
+  thd->variables.character_set_client= client_cs_saved;
+  thd->update_charset();
 
-  return t;
-}
+  thd->temporary_tables= tmp_tables_saved;
 
-/*
-  Prepend the USE DB <obj> command.
-*/
-void prepend_db(THD *thd, String *serialization, String *db_name)
-{
-  DBUG_ENTER("Obj::prepend_db()");
-  /*
-    prepend "USE db" statement
-  */
-  serialization->length(0);
-  serialization->append("USE ");
-  append_identifier(thd, serialization, db_name->c_ptr(), db_name->length());
-  serialization->append("; ");
-  DBUG_VOID_RETURN;
+  DBUG_RETURN(rc);
 }
 
 ///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
 
 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,
@@ -367,1270 +139,1235 @@ struct Table_name_key
     key.append(table_name);
   }
 
+public:
   String db_name;
   String table_name;
 
   String key;
 };
 
-uchar *
-get_table_name_key(const uchar *record,
-                   size_t *key_length,
-                   my_bool not_used __attribute__((unused)))
+///////////////////////////////////////////////////////////////////////////
+
+uchar *Table_name_key::get_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();
 }
 
-void delete_table_name_key(void *data)
+///////////////////////////////////////////////////////////////////////////
+
+void Table_name_key::delete_key(void *data)
 {
   Table_name_key *tnk= (Table_name_key *) data;
   delete tnk;
 }
 
-}
-
+///////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////
 
-namespace obs {
-
-/**
-  Build a where clause for list of databases.
-
-  This method is used to help improve the efficiency of queries against
-  information schema tables. It builds a condition tree of the form
-  db_col IN ('a','b','c') where a,b,c are database names.
-
-  @param[in] thd      Thread context.
-  @param[in] t        The table to operate on.
-  @param[in] db_list  The list of databases in form List<LEX_STRING>
-
-  @returns NULL if no databases in list or pointer to COND tree.
-*/
-COND *create_db_select_condition(THD *thd,
-                                 TABLE *t,
-                                 List<LEX_STRING> *db_list)
-{
-  List<Item> in_db_list;
-  List_iterator< ::LEX_STRING> it(*db_list);
-  ::LEX_STRING *db;
-  DBUG_ENTER("Obj::create_select_condition()");
+class Fmt
+{
+public:
+  Fmt(const char *format, ...);
 
-  /*
-    If no list of databases, just return NULL
-  */
-  if (!db_list->elements)
-    DBUG_RETURN(NULL);
+public:
+  const char *str() const { return m_buffer; }
+  int length() const { return m_length; }
 
-  /*
-    Build an inclusion list in the form of 'a', 'b', etc.
-  */
-  while ((db= it++))
-  {
-    Item *db_name= new Item_string(db->str, db->length, system_charset_info);
-    db_name->fix_fields(thd, &db_name);
-    db_name->next= NULL;
-    in_db_list.push_front(db_name);
-  }
+private:
+  char m_buffer[QUERY_BUFFER_SIZE];
+  int m_length;
+};
 
-  /*
-    Build the compared field "table_schema" and link to temp table field.
-  */
-  Item *db_field= new Item_field(thd, thd->lex->current_context(), t->field[1]);
-  in_db_list.push_front(db_field);
+///////////////////////////////////////////////////////////////////////////
 
-  /*
-    Build the in function item comparison and add list of databases.
-  */
-  Item_func_in *in_cond = new Item_func_in(in_db_list);
-  in_cond->fix_fields(thd, (Item **)&in_cond);
-  in_cond->fix_length_and_dec();
+Fmt::Fmt(const char *format, ...)
+{
+  va_list args;
 
-  DBUG_RETURN(in_cond);
+  va_start(args, format);
+  m_length= my_vsnprintf(m_buffer, sizeof (m_buffer), format, args);
+  va_end(args);
 }
 
 ///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: object impl classes.
-//
-
 ///////////////////////////////////////////////////////////////////////////
 
-/**
-   @class DatabaseObj
-
-   This class provides an abstraction to a database object for creation and
-   capture of the creation data.
-*/
-class DatabaseObj : public Obj
+class Out_stream
 {
 public:
-  DatabaseObj(const String *db_name);
+  Out_stream(String *serialization) :
+    m_serialization(serialization)
+  { }
 
 public:
-  virtual bool materialize(uint serialization_version,
-                           const String *serialization);
-
-  const String* get_name()
-  { return &m_db_name; }
-
-  const String *get_db_name()
-  {
-    return &m_db_name;
-  }
-
-private:
-  // These attributes are to be used only for serialization.
-  String m_db_name;
-
-  bool drop(THD *thd);
-  virtual bool do_serialize(THD *thd, String *serialization);
-  virtual bool do_execute(THD *thd);
+  Out_stream &operator <<(const char *query);
+  Out_stream &operator <<(const LEX_STRING *query);
+  Out_stream &operator <<(const String &query);
+  Out_stream &operator <<(const Fmt &query);
 
 private:
-  // These attributes are to be used only for materialization.
-  String m_create_stmt;
+  String *m_serialization;
 };
 
 ///////////////////////////////////////////////////////////////////////////
 
-/**
-   @class TableObj
-
-   This class provides an abstraction to a table object for creation and
-   capture of the creation data.
-*/
-class TableObj : public Obj
+Out_stream &Out_stream::operator <<(const char *query)
 {
-public:
-  TableObj(const String *db_name,
-           const String *table_name,
-           bool table_is_view);
+  LEX_STRING str= { (char *) query, strlen(query) };
+  return Out_stream::operator <<(&str);
+}
 
-public:
-  virtual bool materialize(uint serialization_version,
-                           const String *serialization);
+///////////////////////////////////////////////////////////////////////////
 
-  const String* get_name()
-  { return &m_table_name; }
+Out_stream &Out_stream::operator <<(const LEX_STRING *query)
+{
+  char chunk_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING chunk;
 
-  const String *get_db_name()
-  {
-    return &m_db_name;
-  }
+  chunk.str= chunk_buffer;
+  chunk.length= my_snprintf(chunk_buffer, QUERY_BUFFER_SIZE,
+    "%d %.*s\n",
+    (int) query->length,
+    (int) query->length,
+    (const char *) query->str);
 
-private:
-  // These attributes are to be used only for serialization.
-  String m_db_name;
-  String m_table_name;
-  bool m_table_is_view;
+  m_serialization->append(chunk.str, chunk.length);
 
-  bool drop(THD *thd);
-  virtual bool do_serialize(THD *thd, String *serialization);
-  virtual bool do_execute(THD *thd);
+  return *this;
+}
 
-private:
-  // These attributes are to be used only for materialization.
-  String m_create_stmt;
+///////////////////////////////////////////////////////////////////////////
 
-private:
-  bool serialize_table(THD *thd, String *serialization);
-  bool serialize_view(THD *thd, String *serialization);
-};
+Out_stream &Out_stream::operator <<(const String &query)
+{
+  LEX_STRING str= { (char *) query.ptr(), query.length() };
+  return Out_stream::operator <<(&str);
+}
 
 ///////////////////////////////////////////////////////////////////////////
 
-/**
-  @class TriggerObj
+Out_stream &Out_stream::operator <<(const Fmt &query)
+{
+  LEX_STRING str= { (char *) query.str(), query.length() };
+  return Out_stream::operator <<(&str);
+}
 
-  This class provides an abstraction to a trigger object for creation and
-  capture of the creation data.
-*/
-class TriggerObj : public Obj
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+class In_stream
 {
 public:
-  TriggerObj(const String *db_name,
-             const String *trigger_name);
+  In_stream(uint serialization_version,
+            const String *serialization) :
+    m_serialization_version(serialization_version),
+    m_serialization(serialization),
+    m_read_ptr(m_serialization->ptr()),
+    m_end_ptr(m_serialization->ptr() + m_serialization->length())
+  { }
 
 public:
-  virtual bool materialize(uint serialization_version,
-                           const String *serialization);
-
-  const String* get_name()
-  { return &m_trigger_name; }
-
-  const String *get_db_name()
-  {
-    return &m_db_name;
-  }
-
-private:
-  // These attributes are to be used only for serialization.
-  String m_db_name;
-  String m_trigger_name;
-
-  bool drop(THD *thd);
-  virtual bool do_serialize(THD *thd, String *serialization);
-  virtual bool do_execute(THD *thd);
+  uint serialization_version() const { return m_serialization_version; }
+public:
+  bool next(LEX_STRING *chunk);
 
 private:
-  // These attributes are to be used only for materialization.
-  String m_create_stmt;
+  uint m_serialization_version;
+  const String *m_serialization;
+  const char *m_read_ptr;
+  const char *m_end_ptr;
 };
 
 ///////////////////////////////////////////////////////////////////////////
 
-/**
-  @class StoredProcObj
-
-  This class provides an abstraction to a stored procedure object for creation
-  and capture of the creation data.
-*/
-class StoredProcObj : public Obj
+bool In_stream::next(LEX_STRING *chunk)
 {
-public:
-  StoredProcObj(const String *db_name,
-                const String *stored_proc_name);
-
-public:
-  virtual bool materialize(uint serialization_version,
-                           const String *serialization);
+  if (m_read_ptr >= m_end_ptr)
+    return TRUE;
 
-  const String* get_name()
-  { return &m_stored_proc_name; }
+  const char *delimiter_ptr=
+    my_strchr(system_charset_info, m_read_ptr, m_end_ptr, ' ');
 
-  const String *get_db_name()
+  if (!delimiter_ptr)
   {
-    return &m_db_name;
+    m_read_ptr= m_end_ptr;
+    return TRUE;
   }
 
-private:
-  // These attributes are to be used only for serialization.
-  String m_db_name;
-  String m_stored_proc_name;
+  char buffer[STRING_BUFFER_USUAL_SIZE];
+  int n= delimiter_ptr - m_read_ptr;
 
-  bool drop(THD *thd);
-  virtual bool do_serialize(THD *thd, String *serialization);
-  virtual bool do_execute(THD *thd);
+  memcpy(buffer, m_read_ptr, n);
+  buffer[n]= 0;
 
-private:
-  // These attributes are to be used only for materialization.
-  String m_create_stmt;
-};
+  chunk->str= (char *) delimiter_ptr + 1;
+  chunk->length= atoi(buffer);
 
+  m_read_ptr+= n /* chunk length */
+               + 1 /* delimiter (a space) */
+               + chunk->length /* chunk */
+               + 1; /* chunk delimiter (\n) */
+
+  return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////
 
-/**
-  @class StoredFuncObj
+#define STR(x) x.length(), x.ptr()
+#define LXS(x) x->length, x->str
 
-  This class provides an abstraction to a stored function object for creation
-  and capture of the creation data.
-*/
-class StoredFuncObj : public Obj
+///////////////////////////////////////////////////////////////////////////
+
+}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+namespace obs {
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+class Abstract_obj : public Obj
 {
 public:
-  StoredFuncObj(const String *db_name,
-                const String *stored_func_name);
+  virtual bool serialize(THD *thd, String *serialization);
 
-public:
+  virtual bool execute(THD *thd);
+
+protected:
   virtual bool materialize(uint serialization_version,
                            const String *serialization);
 
-  const String* get_name()
-  { return &m_stored_func_name; }
+  virtual bool do_materialize(In_stream *is);
 
-  const String *get_db_name()
-  {
-    return &m_db_name;
-  }
+  /**
+    Primitive implementing @c serialize() method.
+  */
+  virtual bool do_serialize(THD *thd, Out_stream &os) = 0;
 
-private:
-  // These attributes are to be used only for serialization.
-  String m_db_name;
-  String m_stored_func_name;
+protected:
+  MEM_ROOT m_mem_root; /* This mem-root is for keeping stmt list. */
+  List<String> m_stmt_lst;
 
-  bool drop(THD *thd);
-  virtual bool do_serialize(THD *thd, String *serialization);
-  virtual bool do_execute(THD *thd);
+protected:
+  Abstract_obj();
+  virtual ~Abstract_obj();
 
 private:
-  // These attributes are to be used only for materialization.
-  String m_create_stmt;
+  Abstract_obj(const Abstract_obj &);
+  Abstract_obj &operator =(const Abstract_obj &);
 };
 
 ///////////////////////////////////////////////////////////////////////////
-#ifdef HAVE_EVENT_SCHEDULER
-/**
-  @class EventObj
 
-  This class provides an abstraction to a event object for creation and capture
-  of the creation data.
-*/
-class EventObj : public Obj
+Abstract_obj::Abstract_obj()
 {
-public:
-  EventObj(const String *db_name,
-           const String *event_name);
+  init_sql_alloc(&m_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
+}
 
-public:
-  virtual bool materialize(uint serialization_version,
-                           const String *serialization);
+///////////////////////////////////////////////////////////////////////////
 
-  const String* get_name()
-  { return &m_event_name; }
+Abstract_obj::~Abstract_obj()
+{
+  free_root(&m_mem_root, MYF(0));
+}
 
-  const String *get_db_name()
-  {
-    return &m_db_name;
-  }
+///////////////////////////////////////////////////////////////////////////
 
-private:
-  // These attributes are to be used only for serialization.
-  String m_db_name;
-  String m_event_name;
+/**
+  Serialize object state into a buffer. The buffer actually should be a
+  binary buffer. String class is used here just because we don't have
+  convenient primitive for binary buffers.
 
-  bool drop(THD *thd);
-  virtual bool do_serialize(THD *thd, String *serialization);
-  virtual bool do_execute(THD *thd);
+  Serialization format is opaque to the client, i.e. the client should
+  not make any assumptions about the format or the content of the
+  returned buffer.
 
-private:
-  // These attributes are to be used only for materialization.
-  String m_create_stmt;
-};
-#endif  // HAVE_EVENT_SCHEDULER
+  Serialization format can be changed in the future versions. However,
+  the server must be able to materialize objects coded in any previous
+  formats.
 
-/**
-   @class TablespaceObj
+  @param[in] thd              Server thread context.
+  @param[in] serialization Buffer to serialize the object
 
-   This class provides an abstraction to a user object for creation and
-   capture of the creation data.
+  @return error status.
+    @retval FALSE on success.
+    @retval TRUE on error.
+
+  @note The real work is done inside @c do_serialize() primitive which should be
+  defied in derived classes. This method prepares appropriate context and calls
+  the primitive.
 */
-class TablespaceObj : public Obj
+
+bool Abstract_obj::serialize(THD *thd, String *serialization)
 {
-public:
-  TablespaceObj(const String *ts_name);
+  ulong saved_sql_mode= thd->variables.sql_mode;
+  thd->variables.sql_mode= 0;
 
-public:
-  virtual bool do_serialize(THD *thd, String *serialization);
+  Out_stream os(serialization);
 
-  virtual bool materialize(uint serialization_version,
-                           const String *serialization);
+  bool ret= do_serialize(thd, os);
 
-  virtual bool do_execute(THD *thd);
+  thd->variables.sql_mode= saved_sql_mode;
 
-  const String *describe();
+  return ret;
+}
 
-  const String *build_serialization();
+///////////////////////////////////////////////////////////////////////////
 
+/**
+  Create the object in the database.
+
+  @param[in] thd              Server thread context.
+
+  @return error status.
+    @retval FALSE on success.
+    @retval TRUE on error.
+*/
+
+bool Abstract_obj::execute(THD *thd)
+{
   /*
-    The get_db_name primitive is not used for tablespaces.
+    Save and update session sql_mode.
+
+    Although backup queries can reset it by itself, we should be able to
+    run at least "set" statement. Backup queries are generated using
+    sql_mode == 0, so we also should use it. If a query needs another
+    sql_mode (stored rountines), it will reset it once more.
   */
-  const String *get_db_name() { return 0; }
 
-  const String* get_name()
-  { return &m_ts_name; }
+  ulong saved_sql_mode= thd->variables.sql_mode;
+  thd->variables.sql_mode= 0;
 
-  const String* get_datafile()
-  { return &m_datafile; }
+  /*
+    NOTE: other session variables are not preserved, so backup query must
+    take care to clean up the environment after itself.
+  */
 
-  const String* get_comments()
-  { return &m_comments; }
+  bool rc;
+  List_iterator_fast<String> it(m_stmt_lst);
+  while (true)
+  {
+    String *stmt= it++;
 
-  const String* get_engine()
-  { return &m_engine; }
+    if (!stmt)
+      break;
 
-  void set_datafile(const String *df)
-  { m_datafile.copy(*df); }
+    LEX_STRING query= { (char *) stmt->ptr(), stmt->length() };
 
-  void set_comments(const String *c)
-  { m_comments.copy(*c); }
+    rc= mysql_execute_direct(thd, &query, NULL);
 
-  void set_engine(const String *engine)
-  { m_engine.copy(*engine); }
+    /* Ignore warnings from materialization for now. */
 
-private:
-  // These attributes are to be used only for serialization.
-  String m_ts_name;
-  String m_datafile;
-  String m_comments;
-  String m_engine;
+    if (rc)
+      break;
+  }
 
-  // Drop is not supported by this object.
-  bool drop(THD *thd)
-  { return 0; }
+  thd->variables.sql_mode= saved_sql_mode;
 
-private:
-  // These attributes are to be used only for materialization.
-  String m_create_stmt;
-};
+  return rc == TRUE;
+}
 
-/**
-   @class DbGrantObj
+///////////////////////////////////////////////////////////////////////////
 
-   This class provides an abstraction to database-level grants.
-   This class will permit the recording and replaying of these
-   grants.
-*/
-class DbGrantObj : public Obj
+bool Abstract_obj::materialize(uint serialization_version,
+                               const String *serialization)
 {
-public:
-  DbGrantObj(const String *grantee,
-             const String *db_name,
-             const String *priv_type);
+  m_stmt_lst.delete_elements();
 
-public:
-  virtual bool materialize(uint serialization_version,
-                           const String *serialization);
+  In_stream is(serialization_version, serialization);
 
-  const String* get_name()
-  {
-    return &m_name;
-  }
+  return do_materialize(&is);
+}
 
-  const String *get_db_name()
-  {
-    return &m_db_name;
-  }
+///////////////////////////////////////////////////////////////////////////
 
-  const String *get_priv_type()
+bool Abstract_obj::do_materialize(In_stream *is)
+{
+  while (true)
   {
-    return &m_priv_type;
-  }
+    LEX_STRING stmt;
 
-protected:
-  // These attributes are to be used only for serialization.
-  String m_db_name;   ///< corresponds with TABLE_SCHEMA in IS tables.
-  String m_name;      ///< name used to list in catalog.
-  String m_grantee;   ///< corresponds with GRANTEE in IS tables.
-  String m_priv_type; ///< corresponds with PRIVILEGE_TYPE in IS tables.
+    if (is->next(&stmt))
+      break;
 
-  bool drop(THD *thd) { return 0; };  // Drop not supported.
-  virtual bool do_execute(THD *thd);
+    String *s= new (&m_mem_root) String();
 
-private:
-  virtual bool do_serialize(THD *thd, String *serialization);
-  // These attributes are to be used only for materialization.
-  String m_grant_stmt;
-};
+    if (!s ||
+        s->copy(stmt.str, stmt.length, system_charset_info) ||
+        m_stmt_lst.push_back(s))
+      return TRUE;
+  }
+
+  return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
 
 /**
-   @class TblGrantObj
+   @class Database_obj
 
-   This class provides an abstraction to table-level and routine-level grants.
-   This class will permit the recording and replaying of these
-   grants.
+   This class provides an abstraction to a database object for creation and
+   capture of the creation data.
 */
-class TblGrantObj : public DbGrantObj
+
+class Database_obj : public Abstract_obj
 {
 public:
-  TblGrantObj(const String *grantee,
-              const String *db_name,
-              const String *table_name,
-              const String *priv_type);
+  Database_obj(const char *db_name_str, int db_name_length);
 
 public:
+  virtual inline const String *get_name() const    { return &m_db_name; }
+  virtual inline const String *get_db_name() const { return &m_db_name; }
 
-  const String *get_table_name()
-  {
-    return &m_table_name;
-  }
+private:
+  /* These attributes are to be used only for serialization. */
+  String m_db_name;
 
-protected:
-  // These attributes are to be used only for serialization.
-  String m_table_name; ///< corresponds with TABLE_NAME in IS tables.
+  virtual bool do_serialize(THD *thd, Out_stream &os);
+};
 
+///////////////////////////////////////////////////////////////////////////
+
+/**
+   @class Table_obj
+
+   This class provides an abstraction to a table object for creation and
+   capture of the creation data.
+*/
+
+class Table_obj : public Abstract_obj
+{
+public:
+  Table_obj(const char *db_name_str, int db_name_length,
+           const char *table_name_str, int table_name_length);
+
+public:
+  virtual inline const String *get_name() const    { return &m_table_name; }
+  virtual inline const String *get_db_name() const { return &m_db_name; }
 
 private:
-  virtual bool do_serialize(THD *thd, String *serialization);
+  /* These attributes are to be used only for serialization. */
+  String m_db_name;
+  String m_table_name;
 
-  // These attributes are to be used only for materialization.
-  String m_grant_stmt;
+  virtual bool do_serialize(THD *thd, Out_stream &os);
 };
 
+///////////////////////////////////////////////////////////////////////////
+
 /**
-   @class ColGrantObj
+   @class View_obj
 
-   This class provides an abstraction to column-level grants.
-   This class will permit the recording and replaying of these
-   grants.
+   This class provides an abstraction to a view object for creation and
+   capture of the creation data.
 */
-class ColGrantObj : public TblGrantObj
+
+class View_obj : public Abstract_obj
 {
 public:
-  ColGrantObj(const String *grantee,
-              const String *db_name,
-              const String *table_name,
-              const String *col_name,
-              const String *priv_type);
+  View_obj(const char *db_name_str, int db_name_length,
+           const char *view_name_str, int view_name_length);
 
 public:
-
-  const String *get_col_name()
-  {
-    return &m_col_name;
-  }
-
-protected:
-  // These attributes are to be used only for serialization.
-  String m_col_name; ///< corresponds with COLUMN_NAME in IS tables.
+  virtual inline const String *get_name() const    { return &m_view_name; }
+  virtual inline const String *get_db_name() const { return &m_db_name; }
 
 private:
-  virtual bool do_serialize(THD *thd, String *serialization);
+  /* These attributes are to be used only for serialization. */
+  String m_db_name;
+  String m_view_name;
 
-  // These attributes are to be used only for materialization.
-  String m_grant_stmt;
+  virtual bool do_serialize(THD *thd, Out_stream &os);
 };
 
 ///////////////////////////////////////////////////////////////////////////
 
-//
-// Implementation: iterator impl classes.
-//
+/**
+  @class Trigger_obj
 
-///////////////////////////////////////////////////////////////////////////
+  This class provides an abstraction to a trigger object for creation and
+  capture of the creation data.
+*/
 
-class InformationSchemaIterator : public Obj_iterator
+class Trigger_obj : public Abstract_obj
 {
 public:
-  static bool prepare_is_table(
-    THD *thd,
-    TABLE **is_table,
-    handler **ha,
-    my_bitmap_map **orig_columns,
-    enum_schema_tables is_table_idx,
-    List<LEX_STRING> db_list);
-
-public:
-  InformationSchemaIterator(THD *thd,
-                            TABLE *is_table,
-                            handler *ha,
-                            my_bitmap_map *orig_columns)
-    :
-      m_thd(thd),
-      m_is_table(is_table),
-      m_ha(ha),
-      m_orig_columns(orig_columns)
-  { }
-
-  virtual ~InformationSchemaIterator();
+  Trigger_obj(const char *db_name_str, int db_name_length,
+             const char *trigger_name_str, int trigger_name_length);
 
 public:
-  virtual Obj *next();
-
-protected:
-  virtual Obj *create_obj(TABLE *t) = 0;
-  THD *m_thd;
+  virtual inline const String *get_name() const    { return &m_trigger_name; }
+  virtual inline const String *get_db_name() const { return &m_db_name; }
 
 private:
-  TABLE *m_is_table;
-  handler *m_ha;
-  my_bitmap_map *m_orig_columns;
+  /* These attributes are to be used only for serialization. */
+  String m_db_name;
+  String m_trigger_name;
 
+  virtual bool do_serialize(THD *thd, Out_stream &os);
 };
 
 ///////////////////////////////////////////////////////////////////////////
 
-class ObjIteratorDummyImpl : Obj_iterator
+/**
+  @class Stored_proc_obj
+
+  This class provides an abstraction to a stored procedure object for creation
+  and capture of the creation data.
+*/
+
+class Stored_proc_obj : public Abstract_obj
 {
 public:
-  ObjIteratorDummyImpl() { return; }
-  virtual ~ObjIteratorDummyImpl() { return; }
-  virtual Obj *next() { return NULL; }
+  Stored_proc_obj(const char *db_name_str, int db_name_length,
+                const char *sp_name_str, int sp_name_length);
 
-protected:
-  virtual Obj *create_obj(TABLE *t) { return NULL; }
+public:
+  virtual inline const String *get_name() const    { return &m_sp_name; }
+  virtual inline const String *get_db_name() const { return &m_db_name; }
 
+private:
+  /* These attributes are to be used only for serialization. */
+  String m_db_name;
+  String m_sp_name;
+
+  virtual bool do_serialize(THD *thd, Out_stream &os);
 };
 
 ///////////////////////////////////////////////////////////////////////////
-class DatabaseIterator : public InformationSchemaIterator
+
+/**
+  @class Stored_func_obj
+
+  This class provides an abstraction to a stored function object for creation
+  and capture of the creation data.
+*/
+
+class Stored_func_obj : public Abstract_obj
 {
 public:
-  DatabaseIterator(THD *thd,
-                   TABLE *is_table,
-                   handler *ha,
-                   my_bitmap_map *orig_columns) :
-    InformationSchemaIterator(thd, is_table, ha, orig_columns)
-  { }
+  Stored_func_obj(const char *db_name_str, int db_name_length,
+                const char *sf_name_str, int sf_name_length);
 
-protected:
-  virtual DatabaseObj *create_obj(TABLE *t);
+public:
+  virtual inline const String *get_name() const    { return &m_sf_name; }
+  virtual inline const String *get_db_name() const { return &m_db_name; }
+
+private:
+  /* These attributes are to be used only for serialization. */
+  String m_db_name;
+  String m_sf_name;
+
+  virtual bool do_serialize(THD *thd, Out_stream &os);
 };
 
 ///////////////////////////////////////////////////////////////////////////
 
-class DbTablesIterator : public InformationSchemaIterator
-{
-public:
-  DbTablesIterator(THD *thd,
-                   const String *db_name,
-                   TABLE *is_table,
-                   handler *ha,
-                   my_bitmap_map *orig_columns) :
-    InformationSchemaIterator(thd, is_table, ha, orig_columns)
-  {
-    m_db_name.copy(*db_name);
-  }
+#ifdef HAVE_EVENT_SCHEDULER
 
-protected:
-  virtual TableObj *create_obj(TABLE *t);
+/**
+  @class Event_obj
 
-  virtual bool is_type_accepted(const String *type) const;
+  This class provides an abstraction to a event object for creation and capture
+  of the creation data.
+*/
 
-  virtual bool is_engine_accepted(const String *engine) const;
+class Event_obj : public Abstract_obj
+{
+public:
+  Event_obj(const char *db_name_str, int db_name_length,
+           const char *event_name_str, int event_name_length);
 
-  virtual TableObj *create_table_obj(const String *db_name,
-                                     const String *table_name) const;
+public:
+  virtual inline const String *get_name() const    { return &m_event_name; }
+  virtual inline const String *get_db_name() const { return &m_db_name; }
 
 private:
+  /* These attributes are to be used only for serialization. */
   String m_db_name;
+  String m_event_name;
+
+  virtual bool do_serialize(THD *thd, Out_stream &os);
 };
 
+#endif // HAVE_EVENT_SCHEDULER
+
 ///////////////////////////////////////////////////////////////////////////
 
-class DbViewsIterator : public DbTablesIterator
+/**
+  @class Tablespace_obj
+
+  This class provides an abstraction to a user object for creation and
+  capture of the creation data.
+*/
+
+class Tablespace_obj : public Abstract_obj
 {
 public:
-  DbViewsIterator(THD *thd,
-                  const String *db_name,
-                  TABLE *is_tables,
-                  handler *ha,
-                  my_bitmap_map *orig_columns)
-    : DbTablesIterator(thd, db_name, is_tables, ha, orig_columns)
-  { }
+  Tablespace_obj(const char *ts_name_str, int ts_name_length,
+                 const char *comment_str, int comment_length,
+                 const char *data_file_name_str, int data_file_name_length,
+                 const char *engine_str, int engine_length);
+
+  Tablespace_obj(const char *ts_name_str, int ts_name_length);
+
+public:
+  virtual inline const String *get_name() const    { return &m_ts_name; }
+  virtual inline const String *get_db_name() const { return NULL; }
+
+  const String *get_description();
 
 protected:
-  virtual bool is_type_accepted(const String *type) const;
+  virtual bool do_serialize(THD *thd, Out_stream &os);
 
-  virtual bool is_engine_accepted(const String *engine) const
-  {
-    return true;
-  }
+  virtual bool materialize(uint serialization_version,
+                           const String *serialization);
 
-  virtual TableObj *create_table_obj(const String *db_name,
-                                     const String *table_name) const;
+private:
+  /* These attributes are to be used only for serialization. */
+  String m_ts_name;
+  String m_comment;
+  String m_data_file_name;
+  String m_engine;
+
+private:
+  String m_description;
 };
 
 ///////////////////////////////////////////////////////////////////////////
 
-class DbTriggerIterator : public InformationSchemaIterator
+/**
+  @class Grant_obj
+
+  This class provides an abstraction to grants. This class will permit the
+  recording and replaying of these grants.
+*/
+
+class Grant_obj : public Abstract_obj
 {
 public:
-  DbTriggerIterator(THD *thd,
-                    const String *db_name,
-                    TABLE *is_table,
-                    handler *ha,
-                    my_bitmap_map *orig_columns) :
-    InformationSchemaIterator(thd, is_table, ha, orig_columns)
-  {
-    m_db_name.copy(*db_name);
-  }
+  static void generate_unique_id(const String *user_name,
+                                 const String *host_name,
+                                 String *id);
+
+public:
+  Grant_obj(const char *id_str, int id_length);
+
+  Grant_obj(const char *user_name_str, int user_name_length,
+            const char *host_name_str, int host_name_length,
+            const char *priv_type_str, int priv_type_length,
+            const char *db_name_str, int db_name_length,
+            const char *table_name_str, int table_name_length,
+            const char *column_name_str, int column_name_length);
+
+public:
+  virtual bool do_materialize(In_stream *is);
+
+public:
+  virtual inline const String *get_name() const    { return &m_id; }
+  virtual inline const String *get_db_name() const { return &m_id; }
+
+  inline const String *get_user_name() const { return &m_user_name; }
+  inline const String *get_host_name() const { return &m_host_name; }
+  inline const String *get_grant_info() const { return &m_grant_info; }
 
 protected:
-  virtual TriggerObj *create_obj(TABLE *t);
+  /* These attributes are to be used only for serialization. */
+  String m_id;      ///< identify grant object (grantee is not unique).
+  String m_user_name;
+  String m_host_name;
+  String m_grant_info;
 
 private:
-  String m_db_name;
+  virtual bool do_serialize(THD *thd, Out_stream &os);
 };
 
 ///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
 
-class DbStoredProcIterator : public InformationSchemaIterator
+template <typename T>
+T *create_row_set_iterator(THD *thd, const LEX_STRING *query)
 {
-public:
-  DbStoredProcIterator(THD *thd,
-                       const String *db_name,
-                       TABLE *is_table,
-                       handler *ha,
-                       my_bitmap_map *orig_columns) :
-    InformationSchemaIterator(thd, is_table, ha, orig_columns)
+  Ed_result result(thd->mem_root);
+
+  if (run_query(thd, query, &result) ||
+      result.get_warnings()->elements > 0)
   {
-    m_db_name.copy(*db_name);
+    /* Should be no warnings. */
+    log_warnings(&result);
+    return NULL;
   }
 
-protected:
-  virtual Obj *create_obj(TABLE *t);
+  DBUG_ASSERT(result.elements == 1);
 
-  virtual bool check_type(const String *sr_type) const;
+  Ed_result_set *rs= result.get_cur_result_set();
 
-  virtual Obj *create_sr_object(const String *db_name,
-                                const String *sr_name);
+  DBUG_ASSERT(rs);
 
-private:
-  String m_db_name;
-};
+  T *it= new T(rs);
 
-class DbGrantIterator : public InformationSchemaIterator
-{
-public:
-  DbGrantIterator(THD *thd,
-                 const String *db_name,
-                 TABLE *is_table,
-                 handler *ha,
-                 my_bitmap_map *orig_columns) :
-    InformationSchemaIterator(thd, is_table, ha, orig_columns)
-  {
-    m_db_name.copy(*db_name);
-  }
+  return it ? it : NULL;
+}
 
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+class Ed_result_set_iterator : public Obj_iterator
+{
 protected:
-  virtual DbGrantObj *create_obj(TABLE *t);
+  inline Ed_result_set_iterator(Ed_result_set *rs);
 
-private:
-  String m_db_name;
+protected:
+  Ed_result_set *m_rs;
+  List_iterator_fast<Ed_row> m_row_it;
 };
 
-class TblGrantIterator : public InformationSchemaIterator
-{
-public:
-  TblGrantIterator(THD *thd,
-                  const String *db_name,
-                  TABLE *is_table,
-                  handler *ha,
-                  my_bitmap_map *orig_columns) :
-    InformationSchemaIterator(thd, is_table, ha, orig_columns)
-  {
-    m_db_name.copy(*db_name);
-  }
+///////////////////////////////////////////////////////////////////////////
 
-protected:
-  virtual TblGrantObj *create_obj(TABLE *t);
+inline Ed_result_set_iterator::Ed_result_set_iterator(Ed_result_set *rs)
+  : m_rs(rs),
+    m_row_it(*rs->data())
+{ }
 
-private:
-  String m_db_name;
-};
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
 
-class ColGrantIterator : public InformationSchemaIterator
+class Database_iterator : public Ed_result_set_iterator
 {
 public:
-  ColGrantIterator(THD *thd,
-                  const String *db_name,
-                  TABLE *is_table,
-                  handler *ha,
-                  my_bitmap_map *orig_columns) :
-    InformationSchemaIterator(thd, is_table, ha, orig_columns)
-  {
-    m_db_name.copy(*db_name);
-  }
+  static Database_iterator *create(THD *thd);
 
-protected:
-  virtual ColGrantObj *create_obj(TABLE *t);
+public:
+  inline Database_iterator(Ed_result_set *rs)
+    :Ed_result_set_iterator(rs)
+  { }
 
-private:
-  String m_db_name;
+public:
+  virtual Obj *next();
 };
 
-
 ///////////////////////////////////////////////////////////////////////////
 
-class DbStoredFuncIterator : public DbStoredProcIterator
+Database_iterator *Database_iterator::create(THD *thd)
 {
-public:
-  DbStoredFuncIterator(THD *thd,
-                       const String *db_name,
-                       TABLE *is_table,
-                       handler *ha,
-                       my_bitmap_map *orig_columns) :
-    DbStoredProcIterator(thd, db_name, is_table, ha, orig_columns)
-  { }
+  LEX_STRING query= { C_STRING_WITH_LEN(
+    "SELECT schema_name "
+    "FROM INFORMATION_SCHEMA.SCHEMATA "
+    "WHERE LCASE(schema_name) != 'mysql' AND "
+          "LCASE(schema_name) != 'information_schema'") };
 
-protected:
-  virtual bool check_type(const String *sr_type) const;
+  return create_row_set_iterator<Database_iterator>(thd, &query);
+}
 
-  virtual Obj *create_sr_object(const String *db_name,
-                                const String *sr_name);
-};
+///////////////////////////////////////////////////////////////////////////
+
+template
+Database_iterator *
+create_row_set_iterator<Database_iterator>(THD *thd, const LEX_STRING *query);
 
 ///////////////////////////////////////////////////////////////////////////
-#ifdef HAVE_EVENT_SCHEDULER
-class DbEventIterator : public InformationSchemaIterator
+
+Obj *Database_iterator::next()
 {
-public:
-  DbEventIterator(THD *thd,
-                  const String *db_name,
-                  TABLE *is_table,
-                  handler *ha,
-                  my_bitmap_map *orig_columns) :
-    InformationSchemaIterator(thd, is_table, ha, orig_columns)
-  {
-    m_db_name.copy(*db_name);
-  }
+  Ed_row *row= m_row_it++;
 
-protected:
-  virtual EventObj *create_obj(TABLE *t);
+  if (!row)
+    return NULL;
 
-private:
-  String m_db_name;
-};
-#endif
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 1);
+  const Ed_column *db_name= row->get_column(0);
 
+  Database_obj *db= new Database_obj(db_name->str, db_name->length);
+
+  return db ? db : NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////
 
-class ViewBaseObjectsIterator : public Obj_iterator
+class Db_tables_iterator : public Ed_result_set_iterator
 {
 public:
-  enum IteratorType
-  {
-    GET_BASE_TABLES,
-    GET_BASE_VIEWS
-  };
+  static Db_tables_iterator *create(THD *thd, const String *db_name);
 
 public:
-  virtual ~ViewBaseObjectsIterator();
+  inline Db_tables_iterator(Ed_result_set *rs)
+    :Ed_result_set_iterator(rs)
+  { }
 
 public:
-  virtual TableObj *next();
+  virtual Obj *next();
+};
 
-private:
-  static ViewBaseObjectsIterator *create(THD *thd,
-                                         const String *db_name,
-                                         const String *view_name,
-                                         IteratorType iterator_type );
+///////////////////////////////////////////////////////////////////////////
 
-private:
-  ViewBaseObjectsIterator(HASH *table_names);
+Db_tables_iterator *Db_tables_iterator::create(THD *thd, const String *db_name)
+{
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
 
-private:
-  HASH *m_table_names;
-  uint m_cur_idx;
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SELECT '%.*s', table_name "
+    "FROM INFORMATION_SCHEMA.TABLES "
+    "WHERE table_schema = '%.*s' AND table_type = '%.*s'",
+    (int) db_name->length(),
+    (const char *) db_name->ptr(),
+    (int) db_name->length(),
+    (const char *) db_name->ptr(),
+    (int) IS_TYPE_TABLE.length,
+    (const char *) IS_TYPE_TABLE.str);
 
-private:
-  friend Obj_iterator *get_view_base_tables(THD *,
-                                            const String *,
-                                            const String *);
-
-  friend Obj_iterator *get_view_base_views(THD *,
-                                           const String *,
-                                           const String *);
-};
+  return create_row_set_iterator<Db_tables_iterator>(thd, &query);
+}
 
 ///////////////////////////////////////////////////////////////////////////
 
-//
-// Implementation: InformationSchemaIterator class.
-//
+template
+Db_tables_iterator *
+create_row_set_iterator<Db_tables_iterator>(THD *thd, const LEX_STRING *query);
 
 ///////////////////////////////////////////////////////////////////////////
 
-bool InformationSchemaIterator::prepare_is_table(
-  THD *thd,
-  TABLE **is_table,
-  handler **ha,
-  my_bitmap_map **orig_columns,
-  enum_schema_tables is_table_idx,
-  List<LEX_STRING> db_list)
+Obj *Db_tables_iterator::next()
 {
-  ST_SCHEMA_TABLE *st= get_schema_table(is_table_idx);
-  if (!(*is_table= open_schema_table(thd, st, &db_list)))
-    return TRUE;
+  Ed_row *row= m_row_it++;
 
-  *ha= (*is_table)->file;
+  if (!row)
+    return NULL;
 
-  if (!*ha)
-  {
-    free_tmp_table(thd, *is_table);
-    return TRUE;
-  }
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
 
-  *orig_columns=
-    dbug_tmp_use_all_columns(*is_table, (*is_table)->read_set);
+  const Ed_column *db_name= row->get_column(0);
+  const Ed_column *table_name= row->get_column(1);
 
-  if ((*ha)->ha_rnd_init(TRUE))
-  {
-    dbug_tmp_restore_column_map((*is_table)->read_set, *orig_columns);
-    free_tmp_table(thd, *is_table);
-    return TRUE;
-  }
+  Table_obj *table= new Table_obj(db_name->str, db_name->length,
+                                table_name->str, table_name->length);
 
-  return FALSE;
+  return table ? table : NULL;
 }
 
-InformationSchemaIterator::~InformationSchemaIterator()
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+class Db_views_iterator : public Ed_result_set_iterator
 {
-  m_ha->ha_rnd_end();
+public:
+  static Db_views_iterator *create(THD *thd, const String *db_name);
 
-  dbug_tmp_restore_column_map(m_is_table->read_set, m_orig_columns);
-  free_tmp_table(m_thd, m_is_table);
-}
+public:
+  inline Db_views_iterator(Ed_result_set *rs)
+    :Ed_result_set_iterator(rs)
+  { }
+
+public:
+  virtual Obj *next();
+};
+
+///////////////////////////////////////////////////////////////////////////
 
-Obj *InformationSchemaIterator::next()
+Db_views_iterator *Db_views_iterator::create(THD *thd, const String *db_name)
 {
-  while (true)
-  {
-    if (m_ha->rnd_next(m_is_table->record[0]))
-      return NULL;
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
 
-    Obj *obj= create_obj(m_is_table);
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SELECT '%.*s', table_name "
+    "FROM INFORMATION_SCHEMA.TABLES "
+    "WHERE table_schema = '%.*s' AND table_type = '%.*s'",
+    (int) db_name->length(),
+    (const char *) db_name->ptr(),
+    (int) db_name->length(),
+    (const char *) db_name->ptr(),
+    (int) IS_TYPE_VIEW.length,
+    (const char *) IS_TYPE_VIEW.str);
 
-    if (obj)
-      return obj;
-  }
+  return create_row_set_iterator<Db_views_iterator>(thd, &query);
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
-//
-// Implementation: DatabaseIterator class.
-//
+template
+Db_views_iterator *
+create_row_set_iterator<Db_views_iterator>(THD *thd, const LEX_STRING *query);
 
 ///////////////////////////////////////////////////////////////////////////
 
-DatabaseObj* DatabaseIterator::create_obj(TABLE *t)
+Obj *Db_views_iterator::next()
 {
-  String name;
+  Ed_row *row= m_row_it++;
+
+  if (!row)
+    return NULL;
+
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
 
-  t->field[1]->val_str(&name);
+  const Ed_column *db_name= row->get_column(0);
+  const Ed_column *view_name= row->get_column(1);
 
-  DBUG_PRINT("DatabaseIterator::next", (" Found database %s", name.ptr()));
+  View_obj *view= new View_obj(db_name->str, db_name->length,
+                             view_name->str, view_name->length);
 
-  return new DatabaseObj(&name);
+  return view ? view : NULL;
 }
 
 ///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
 
-//
-// Implementation: DbTablesIterator class.
-//
+class Db_trigger_iterator : public Ed_result_set_iterator
+{
+public:
+  static Db_trigger_iterator *create(THD *thd, const String *db_name);
+
+public:
+  inline Db_trigger_iterator(Ed_result_set *rs)
+    :Ed_result_set_iterator(rs)
+  { }
+
+public:
+  virtual Obj *next();
+};
 
 ///////////////////////////////////////////////////////////////////////////
 
-TableObj* DbTablesIterator::create_obj(TABLE *t)
+Db_trigger_iterator *Db_trigger_iterator::create(THD *thd, const String *db_name)
 {
-  String table_name;
-  String db_name;
-  String type;
-  String engine;
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
 
-  t->field[1]->val_str(&db_name);
-  t->field[2]->val_str(&table_name);
-  t->field[3]->val_str(&type);
-  t->field[4]->val_str(&engine);
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SELECT '%.*s', trigger_name "
+    "FROM INFORMATION_SCHEMA.TRIGGERS "
+    "WHERE trigger_schema = '%.*s'",
+    (int) db_name->length(),
+    (const char *) db_name->ptr(),
+    (int) db_name->length(),
+    (const char *) db_name->ptr());
 
-  // Skip tables not from the given database.
+  return create_row_set_iterator<Db_trigger_iterator>(thd, &query);
+}
 
-  if (db_name != m_db_name)
-    return NULL;
+///////////////////////////////////////////////////////////////////////////
 
-  // Skip tables/views depending on enumerate_views flag.
+template
+Db_trigger_iterator *
+create_row_set_iterator<Db_trigger_iterator>(THD *thd, const LEX_STRING *query);
 
-  if (!is_type_accepted(&type))
-    return NULL;
+///////////////////////////////////////////////////////////////////////////
 
-  // TODO: actually, Backup Kernel needs to know also tables with
-  // invalid/empty engines. It is required so that Backup Kernel can throw
-  // a warning to the user.
+Obj *Db_trigger_iterator::next()
+{
+  Ed_row *row= m_row_it++;
 
-  if (!is_engine_accepted(&engine))
+  if (!row)
     return NULL;
 
-  DBUG_PRINT("DbTablesIterator::next", (" Found table %s.%s",
-                                        db_name.ptr(), table_name.ptr()));
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
 
-  return create_table_obj(&db_name, &table_name);
-}
+  const Ed_column *db_name= row->get_column(0);
+  const Ed_column *trigger_name= row->get_column(1);
 
-bool DbTablesIterator::is_type_accepted(const String *type) const
-{
-  return my_strcasecmp(system_charset_info,
-                       ((String *) type)->c_ptr_safe(), "BASE TABLE") == 0;
-}
+  Trigger_obj *trigger= new Trigger_obj(db_name->str, db_name->length,
+                                      trigger_name->str, trigger_name->length);
 
-bool DbTablesIterator::is_engine_accepted(const String *engine) const
-{
-  return engine->length() > 0;
+  return trigger ? trigger : NULL;
 }
 
-TableObj *DbTablesIterator::create_table_obj(const String *db_name,
-                                             const String *table_name) const
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+class Db_stored_proc_iterator : public Ed_result_set_iterator
 {
-  return new TableObj(db_name, table_name, false);
-}
+public:
+  static Db_stored_proc_iterator *create(THD *thd, const String *db_name);
 
-///////////////////////////////////////////////////////////////////////////
+public:
+  inline Db_stored_proc_iterator(Ed_result_set *rs)
+    :Ed_result_set_iterator(rs)
+  { }
 
-//
-// Implementation: DbViewsIterator class.
-//
+public:
+  virtual Obj *next();
+};
 
 ///////////////////////////////////////////////////////////////////////////
 
-bool DbViewsIterator::is_type_accepted(const String *type) const
+Db_stored_proc_iterator *
+Db_stored_proc_iterator::create(THD *thd, const String *db_name)
 {
-  return my_strcasecmp(system_charset_info,
-                       ((String *) type)->c_ptr_safe(), "VIEW") == 0;
-}
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
 
-TableObj *DbViewsIterator::create_table_obj(const String *db_name,
-                                            const String *table_name) const
-{
-  return new TableObj(db_name, table_name, true);
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SELECT '%.*s', routine_name "
+    "FROM INFORMATION_SCHEMA.ROUTINES "
+    "WHERE routine_schema = '%.*s' AND routine_type = 'PROCEDURE'",
+    (int) db_name->length(),
+    (const char *) db_name->ptr(),
+    (int) db_name->length(),
+    (const char *) db_name->ptr());
+
+  return create_row_set_iterator<Db_stored_proc_iterator>(thd, &query);
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
-//
-// Implementation: DbTriggerIterator class.
-//
+template
+Db_stored_proc_iterator *
+create_row_set_iterator<Db_stored_proc_iterator>(THD *thd,
+                                                 const LEX_STRING *query);
 
 ///////////////////////////////////////////////////////////////////////////
 
-TriggerObj *DbTriggerIterator::create_obj(TABLE *t)
+Obj *Db_stored_proc_iterator::next()
 {
-  String db_name;
-  String trigger_name;
+  Ed_row *row= m_row_it++;
+
+  if (!row)
+    return NULL;
 
-  t->field[1]->val_str(&db_name);
-  t->field[2]->val_str(&trigger_name);
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
 
-  // Skip triggers not from the given database.
+  const Ed_column *db_name= row->get_column(0);
+  const Ed_column *routine_name= row->get_column(1);
 
-  if (db_name != m_db_name)
-    return NULL;
+  Stored_proc_obj *sp= new Stored_proc_obj(db_name->str, db_name->length,
+                                       routine_name->str, routine_name->length);
 
-  return new TriggerObj(&db_name, &trigger_name);
+  return sp ? sp : NULL;
 }
 
 ///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: DbStoredProcIterator class.
-//
-
 ///////////////////////////////////////////////////////////////////////////
 
-Obj *DbStoredProcIterator::create_obj(TABLE *t)
+class Db_stored_func_iterator : public Ed_result_set_iterator
 {
-  String db_name;
-  String sr_name;
-  String sr_type;
-
-  t->field[2]->val_str(&db_name);
-  t->field[3]->val_str(&sr_name);
-  t->field[4]->val_str(&sr_type);
-
-  // Skip stored procedure not from the given database.
+public:
+  static Db_stored_func_iterator *create(THD *thd, const String *db_name);
 
-  if (db_name != m_db_name)
-    return NULL;
+public:
+  inline Db_stored_func_iterator(Ed_result_set *rs)
+    :Ed_result_set_iterator(rs)
+  { }
 
-  if (!check_type(&sr_type))
-    return NULL;
+public:
+  virtual Obj *next();
+};
 
-  return create_sr_object(&db_name, &sr_name);
-}
+///////////////////////////////////////////////////////////////////////////
 
-bool DbStoredProcIterator::check_type(const String *sr_type) const
+Db_stored_func_iterator *
+Db_stored_func_iterator::create(THD *thd, const String *db_name)
 {
-  return
-    my_strcasecmp(system_charset_info,
-                  ((String *) sr_type)->c_ptr_safe(),
-                  "PROCEDURE") == 0;
-}
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
 
-Obj *DbStoredProcIterator::create_sr_object(const String *db_name,
-                                            const String *sr_name)
-{
-  return new StoredProcObj(db_name, sr_name);
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SELECT '%.*s', routine_name "
+    "FROM INFORMATION_SCHEMA.ROUTINES "
+    "WHERE routine_schema = '%.*s' AND routine_type = 'FUNCTION'",
+    (int) db_name->length(),
+    (const char *) db_name->ptr(),
+    (int) db_name->length(),
+    (const char *) db_name->ptr());
+
+  return create_row_set_iterator<Db_stored_func_iterator>(thd, &query);
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
-//
-// Implementation: DbStoredFuncIterator class.
-//
+template
+Db_stored_func_iterator *
+create_row_set_iterator<Db_stored_func_iterator>(THD *thd,
+                                                 const LEX_STRING *query);
 
 ///////////////////////////////////////////////////////////////////////////
 
-bool DbStoredFuncIterator::check_type(const String *sr_type) const
+Obj *Db_stored_func_iterator::next()
 {
-  return
-    my_strcasecmp(system_charset_info,
-                  ((String *) sr_type)->c_ptr_safe(),
-                  "FUNCTION") == 0;
-}
+  Ed_row *row= m_row_it++;
 
-Obj *DbStoredFuncIterator::create_sr_object(const String *db_name,
-                                            const String *sr_name)
-{
-  return new StoredFuncObj(db_name, sr_name);
+  if (!row)
+    return NULL;
+
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
+
+  const Ed_column *db_name= row->get_column(0);
+  const Ed_column *routine_name= row->get_column(1);
+
+  Stored_func_obj *sf= new Stored_func_obj(db_name->str, db_name->length,
+                                       routine_name->str, routine_name->length);
+
+  return sf ? sf : NULL;
 }
 
-#ifdef HAVE_EVENT_SCHEDULER
+///////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////
 
-//
-// Implementation: DbEventIterator class.
-//
+class Db_event_iterator : public Ed_result_set_iterator
+{
+public:
+  static Db_event_iterator *create(THD *thd, const String *db_name);
+
+public:
+  inline Db_event_iterator(Ed_result_set *rs)
+    :Ed_result_set_iterator(rs)
+  { }
+
+public:
+  virtual Obj *next();
+};
 
 ///////////////////////////////////////////////////////////////////////////
-EventObj *DbEventIterator::create_obj(TABLE *t)
+
+Db_event_iterator *
+Db_event_iterator::create(THD *thd, const String *db_name)
 {
-  String db_name;
-  String event_name;
+#ifdef HAVE_EVENT_SCHEDULER
 
-  t->field[1]->val_str(&db_name);
-  t->field[2]->val_str(&event_name);
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
 
-  // Skip event not from the given database.
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SELECT '%.*s', event_name "
+    "FROM INFORMATION_SCHEMA.EVENTS "
+    "WHERE event_schema = '%.*s'",
+    (int) db_name->length(),
+    (const char *) db_name->ptr(),
+    (int) db_name->length(),
+    (const char *) db_name->ptr());
 
-  if (db_name != m_db_name)
-    return NULL;
+  return create_row_set_iterator<Db_event_iterator>(thd, &query);
+
+#else
+
+  return NULL;
 
-  return new EventObj(&db_name, &event_name);
-}
 #endif
+}
 
 ///////////////////////////////////////////////////////////////////////////
 
-//
-// Implementation: DbGrantIterator class.
-//
+#ifdef HAVE_EVENT_SCHEDULER
+template
+Db_event_iterator *
+create_row_set_iterator<Db_event_iterator>(THD *thd, const LEX_STRING *query);
+#endif
 
 ///////////////////////////////////////////////////////////////////////////
 
-DbGrantObj* DbGrantIterator::create_obj(TABLE *t)
+Obj *Db_event_iterator::next()
 {
-  String grantee;   // corresponds with GRANTEE
-  String db_name;   // corresponds with TABLE_SCHEMA
-  String priv_type; // corresponds with PRIVILEGE_TYPE
-
-  t->field[0]->val_str(&grantee);
-  t->field[2]->val_str(&db_name);
-  t->field[3]->val_str(&priv_type);
-
-  /*
-    The fill method for SCHEMA_PRIVILEGES does not use the COND portion
-    of the generic fill() method. Thus, we have to do the restriction here.
+#ifdef HAVE_EVENT_SCHEDULER
 
-    Ensure the only rows sent back from iterator are the ones that match the
-    database specified.
-  */
-  if (db_name == m_db_name)
-  {
-    DBUG_PRINT("DbGrantIterator::create", (" Found grant %s %s %s",
-     db_name.ptr(), grantee.ptr(), priv_type.ptr()));
+  Ed_row *row= m_row_it++;
 
-    /*
-      Include grants for only users that exist at time of backup.
-    */
-    if (check_user_existence(m_thd, &grantee))
-      return new DbGrantObj(&grantee, &db_name, &priv_type);
-    else
-      return NULL;
-  }
-  else
+  if (!row)
     return NULL;
-}
 
-///////////////////////////////////////////////////////////////////////////
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
 
-//
-// Implementation: TblGrantIterator class.
-//
+  const Ed_column *db_name= row->get_column(0);
+  const Ed_column *event_name= row->get_column(1);
 
-///////////////////////////////////////////////////////////////////////////
+  Event_obj *event= new Event_obj(db_name->str, db_name->length,
+                                  event_name->str, event_name->length);
 
-TblGrantObj* TblGrantIterator::create_obj(TABLE *t)
-{
-  String grantee;   // corresponds with GRANTEE
-  String db_name;   // corresponds with TABLE_SCHEMA
-  String tbl_name;  // corresponds with TABLE_NAME
-  String priv_type; // corresponds with PRIVILEGE_TYPE
-
-  t->field[0]->val_str(&grantee);
-  t->field[2]->val_str(&db_name);
-  t->field[3]->val_str(&tbl_name);
-  t->field[4]->val_str(&priv_type);
+  return event ? event : NULL;
 
-  /*
-    The fill method for TABLE_PRIVILEGES does not use the COND portion
-    of the generic fill() method. Thus, we have to do the restriction here.
+#else
 
-    Ensure the only rows sent back from iterator are the ones that match the
-    database specified.
-  */
-  if (db_name == m_db_name)
-  {
-    DBUG_PRINT("TblGrantIterator::create", (" Found grant %s %s %s %s",
-     db_name.ptr(), grantee.ptr(), tbl_name.ptr(), priv_type.ptr()));
+  return NULL;
 
-    /*
-      Include grants for only users that exist at time of backup.
-    */
-    if (check_user_existence(m_thd, &grantee))
-      return new TblGrantObj(&grantee, &db_name, &tbl_name, &priv_type);
-    else
-      return NULL;
-  }
-  else
-    return NULL;
+#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
 
-//
-// Implementation: ColGrantIterator class.
-//
+class View_base_obj_iterator : public Obj_iterator
+{
+public:
+  View_base_obj_iterator();
+  virtual ~View_base_obj_iterator();
+
+public:
+  virtual Obj *next();
+
+protected:
+  template <typename T>
+  static T *create(THD *thd, const String *db_name, const String *view_name);
+
+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;
+
+private:
+  HASH *m_table_names;
+  uint m_cur_idx;
+};
 
 ///////////////////////////////////////////////////////////////////////////
 
-ColGrantObj* ColGrantIterator::create_obj(TABLE *t)
+template <typename T>
+T *View_base_obj_iterator::create(THD *thd,
+                                  const String *db_name,
+                                  const String *view_name)
 {
-  String grantee;   // corresponds with GRANTEE
-  String db_name;   // corresponds with TABLE_SCHEMA
-  String tbl_name;  // corresponds with TABLE_NAME
-  String col_name;  // corresponds with COLUMN_NAME
-  String priv_type; // corresponds with PRIVILEGE_TYPE
-
-  t->field[0]->val_str(&grantee);
-  t->field[2]->val_str(&db_name);
-  t->field[3]->val_str(&tbl_name);
-  t->field[4]->val_str(&col_name);
-  t->field[5]->val_str(&priv_type);
+  T *it= new T();
 
-  /*
-    The fill method for COLUMN_PRIVILEGES does not use the COND portion
-    of the generic fill() method. Thus, we have to do the restriction here.
-
-    Ensure the only rows sent back from iterator are the ones that match the
-    database specified.
-  */
-  if (db_name == m_db_name)
+  if (it->init(thd, db_name, view_name))
   {
-    DBUG_PRINT("ColGrantIterator::create", (" Found grant %s %s %s %s %s",
-     db_name.ptr(), grantee.ptr(), tbl_name.ptr(), col_name.ptr(),
-     priv_type.ptr()));
-
-    /*
-      Include grants for only users that exist at time of backup.
-    */
-    if (check_user_existence(m_thd, &grantee))
-      return new ColGrantObj(&grantee, &db_name, &tbl_name,
-                             &col_name, &priv_type);
-    else
-      return NULL;
-  }
-  else
+    delete it;
     return NULL;
+  }
+
+  return it;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+View_base_obj_iterator::View_base_obj_iterator() :
+  m_table_names(NULL),
+  m_cur_idx(0)
+{
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
-//
-// Implementation: ViewBaseObjectsIterator class.
-//
+View_base_obj_iterator::~View_base_obj_iterator()
+{
+  if (!m_table_names)
+    return;
+
+  hash_free(m_table_names);
+  delete m_table_names;
+}
 
 ///////////////////////////////////////////////////////////////////////////
 
-ViewBaseObjectsIterator *
-ViewBaseObjectsIterator::create(THD *thd,
-                               const String *db_name,
-                               const String *view_name,
-                               IteratorType iterator_type)
+bool View_base_obj_iterator::init(THD *thd,
+                                  const String *db_name,
+                                  const String *view_name)
 {
-  uint table_count; // Passed to open_tables(). Not used.
+  DBUG_ASSERT(!m_table_names);
+
+  uint not_used; /* Passed to open_tables(). Not used. */
   THD *my_thd= new THD();
 
   my_thd->security_ctx= thd->security_ctx;
@@ -1646,20 +1383,20 @@ ViewBaseObjectsIterator::create(THD *thd
                            ((String *) view_name)->c_ptr_safe(),
                            TL_READ);
 
-  if (open_tables(my_thd, &tl, &table_count, 0))
+  if (open_tables(my_thd, &tl, &not_used, MYSQL_OPEN_SKIP_TEMPORARY))
   {
     close_thread_tables(my_thd);
     delete my_thd;
     thd->store_globals();
 
-    return NULL;
+    return TRUE;
   }
 
-  HASH *table_names = new HASH();
+  m_table_names = new HASH();
 
-  hash_init(table_names, system_charset_info, 16, 0, 0,
-            get_table_name_key,
-            delete_table_name_key,
+  hash_init(m_table_names, system_charset_info, 16, 0, 0,
+            Table_name_key::get_key,
+            Table_name_key::delete_key,
             MYF(0));
 
   if (tl->view_tables)
@@ -1673,23 +1410,16 @@ ViewBaseObjectsIterator::create(THD *thd
         new Table_name_key(tl2->db, tl2->db_length,
                            tl2->table_name, tl2->table_name_length);
 
-      if (iterator_type == GET_BASE_TABLES && tl2->view ||
-          iterator_type == GET_BASE_VIEWS && !tl2->view)
+      if (!is_obj_accepted(tl2) ||
+          hash_search(m_table_names,
+                      (uchar *) tnk->key.c_ptr_safe(),
+                      tnk->key.length()))
       {
         delete tnk;
         continue;
       }
 
-      if (!hash_search(table_names,
-                       (uchar *) tnk->key.c_ptr_safe(),
-                       tnk->key.length()))
-      {
-        my_hash_insert(table_names, (uchar *) tnk);
-      }
-      else
-      {
-        delete tnk;
-      }
+      my_hash_insert(m_table_names, (uchar *) tnk);
     }
   }
 
@@ -1698,22 +1428,12 @@ ViewBaseObjectsIterator::create(THD *thd
 
   thd->store_globals();
 
-  return new ViewBaseObjectsIterator(table_names);
-}
-
-ViewBaseObjectsIterator::ViewBaseObjectsIterator(HASH *table_names) :
-  m_table_names(table_names),
-  m_cur_idx(0)
-{
+  return FALSE;
 }
 
-ViewBaseObjectsIterator::~ViewBaseObjectsIterator()
-{
-  hash_free(m_table_names);
-  delete m_table_names;
-}
+///////////////////////////////////////////////////////////////////////////
 
-TableObj *ViewBaseObjectsIterator::next()
+Obj *View_base_obj_iterator::next()
 {
   if (m_cur_idx >= m_table_names->records)
     return NULL;
@@ -1723,223 +1443,189 @@ TableObj *ViewBaseObjectsIterator::next(
 
   ++m_cur_idx;
 
-  return new TableObj(&tnk->db_name, &tnk->table_name, false);
+  return create_obj(&tnk->db_name, &tnk->table_name);
 }
 
 ///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: enumeration functions.
-//
-
 ///////////////////////////////////////////////////////////////////////////
 
-Obj_iterator *get_databases(THD *thd)
+class View_base_table_iterator : public View_base_obj_iterator
 {
-  TABLE *is_table;
-  handler *ha;
-  my_bitmap_map *orig_columns;
-
-  if (InformationSchemaIterator::prepare_is_table(
-      thd, &is_table, &ha, &orig_columns, SCH_SCHEMATA,
-      thd->lex->db_list))
-    return NULL;
-
-  return new DatabaseIterator(thd, is_table, ha, orig_columns);
-}
+public:
+  static View_base_obj_iterator *
+  create(THD *thd, const String *db_name, const String *view_name)
+  {
+    return View_base_obj_iterator::create<View_base_table_iterator>
+      (thd, db_name, view_name);
+  }
 
-template <typename Iterator>
-Iterator *create_is_iterator(THD *thd,
-                             enum_schema_tables is_table_idx,
-                             const String *db_name)
-{
-  TABLE *is_table;
-  handler *ha;
-  my_bitmap_map *orig_columns;
-
-  LEX_STRING dbname;
-  String db;
-  db.copy(*db_name);
-  thd->make_lex_string(&dbname, db.c_ptr(), db.length(), FALSE);
-  List<LEX_STRING> db_list;
-  db_list.push_back(&dbname);
-
-  if (InformationSchemaIterator::prepare_is_table(
-      thd, &is_table, &ha, &orig_columns, is_table_idx,
-      db_list))
-    return NULL;
+protected:
+  virtual bool is_obj_accepted(TABLE_LIST *obj)
+  { return !obj->view; }
 
-  return new Iterator(thd, db_name, is_table, ha, orig_columns);
-}
+  virtual Obj *create_obj(const String *db_name, const String *obj_name)
+  {
+    return new Table_obj(db_name->ptr(), db_name->length(),
+                         obj_name->ptr(), obj_name->length());
+  }
+};
 
-template
-DbTablesIterator *
-create_is_iterator<DbTablesIterator>(THD *, enum_schema_tables, const String *);
+///////////////////////////////////////////////////////////////////////////
 
 template
-DbViewsIterator *
-create_is_iterator<DbViewsIterator>(THD *, enum_schema_tables, const String *);
+View_base_table_iterator *
+View_base_obj_iterator::create<View_base_table_iterator>(
+  THD *thd, const String *db_name, const String *view_name);
 
-template
-DbTriggerIterator *
-create_is_iterator<DbTriggerIterator>(THD *, enum_schema_tables, const String *);
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
 
-template
-DbStoredProcIterator *
-create_is_iterator<DbStoredProcIterator>(THD *, enum_schema_tables, const String *);
+class View_base_view_iterator : public View_base_obj_iterator
+{
+public:
+  static View_base_obj_iterator *
+  create(THD *thd, const String *db_name, const String *view_name)
+  {
+    return View_base_obj_iterator::create<View_base_view_iterator>
+      (thd, db_name, view_name);
+  }
 
-template
-DbStoredFuncIterator *
-create_is_iterator<DbStoredFuncIterator>(THD *, enum_schema_tables, const String *);
+protected:
+  virtual bool is_obj_accepted(TABLE_LIST *obj)
+  { return obj->view; }
 
-#ifdef HAVE_EVENT_SCHEDULER
-template
-DbEventIterator *
-create_is_iterator<DbEventIterator>(THD *, enum_schema_tables, const String *);
-#endif
+  virtual Obj *create_obj(const String *db_name, const String *obj_name)
+  {
+    return new View_obj(db_name->ptr(), db_name->length(),
+                        obj_name->ptr(), obj_name->length());
+  }
+};
 
-template
-DbGrantIterator *
-create_is_iterator<DbGrantIterator>(THD *, enum_schema_tables, const String *);
+///////////////////////////////////////////////////////////////////////////
 
 template
-TblGrantIterator *
-create_is_iterator<TblGrantIterator>(THD *, enum_schema_tables, const String *);
+View_base_view_iterator *
+View_base_obj_iterator::create<View_base_view_iterator>(
+  THD *thd, const String *db_name, const String *view_name);
 
-template
-ColGrantIterator *
-create_is_iterator<ColGrantIterator>(THD *, enum_schema_tables, const String *);
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
 
-Obj_iterator *get_db_tables(THD *thd, const String *db_name)
+class Grant_iterator : public Ed_result_set_iterator
 {
-  return create_is_iterator<DbTablesIterator>(thd, SCH_TABLES, db_name);
-}
+public:
+  static Grant_iterator *create(THD *thd, const String *db_name);
 
-Obj_iterator *get_db_views(THD *thd, const String *db_name)
-{
-  return create_is_iterator<DbViewsIterator>(thd, SCH_TABLES, db_name);
-}
+public:
+  inline Grant_iterator(Ed_result_set *rs)
+    :Ed_result_set_iterator(rs)
+  { }
 
-Obj_iterator *get_db_triggers(THD *thd, const String *db_name)
-{
-  return create_is_iterator<DbTriggerIterator>(thd, SCH_TRIGGERS, db_name);
-}
+public:
+  virtual Obj *next();
+};
 
-Obj_iterator *get_db_stored_procedures(THD *thd, const String *db_name)
-{
-  return create_is_iterator<DbStoredProcIterator>(thd, SCH_PROCEDURES, db_name);
-}
+///////////////////////////////////////////////////////////////////////////
 
-Obj_iterator *get_db_stored_functions(THD *thd, const String *db_name)
+Grant_iterator *
+Grant_iterator::create(THD *thd, const String *db_name)
 {
-  return create_is_iterator<DbStoredFuncIterator>(thd, SCH_PROCEDURES, db_name);
-}
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
 
-Obj_iterator *get_db_events(THD *thd, const String *db_name)
-{
-#ifdef HAVE_EVENT_SCHEDULER
-  return create_is_iterator<DbEventIterator>(thd, SCH_EVENTS, db_name);
-#else
-  return (Obj_iterator *)new ObjIteratorDummyImpl;
-#endif
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "(SELECT user AS c1, "
+            "host AS c2, "
+            "privilege_type AS c3, "
+            "table_schema AS c4, "
+            "NULL AS c5, "
+            "NULL AS c6 "
+    "FROM INFORMATION_SCHEMA.SCHEMA_PRIVILEGES, mysql.user "
+    "WHERE table_schema = '%.*s' AND "
+          "grantee = CONCAT(\"'\", user, \"'@'\", host, \"'\")) "
+    "UNION "
+    "(SELECT user, host, privilege_type, table_schema, table_name, NULL "
+    "FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES, mysql.user "
+    "WHERE table_schema = '%.*s' AND "
+          "grantee = CONCAT(\"'\", user, \"'@'\", host, \"'\")) "
+    "UNION "
+    "(SELECT user, host, privilege_type, table_schema, table_name, column_name "
+    "FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES, mysql.user "
+    "WHERE table_schema = '%.*s' AND "
+          "grantee = CONCAT(\"'\", user, \"'@'\", host, \"'\")) "
+    "ORDER BY c1 ASC, c2 ASC, c3 ASC, c4 ASC, c5 ASC, c6 ASC",
+    (int) db_name->length(),
+    (const char *) db_name->ptr(),
+    (int) db_name->length(),
+    (const char *) db_name->ptr(),
+    (int) db_name->length(),
+    (const char *) db_name->ptr());
+
+  return create_row_set_iterator<Grant_iterator>(thd, &query);
 }
 
-/**
-  GrantObjIterator constructor
+///////////////////////////////////////////////////////////////////////////
 
-  This constructor initializes iterators for the grants supported.
-  These include database-, table- and routine-, and column-level grants.
-  The iterators return all of the grants for the database specified.
-*/
-GrantObjIterator::GrantObjIterator(THD *thd, const String *db_name)
-: Obj_iterator()
-{
-  db_grants= create_is_iterator<DbGrantIterator>(thd,
-                                                 SCH_SCHEMA_PRIVILEGES,
-                                                 db_name);
-  tbl_grants= create_is_iterator<TblGrantIterator>(thd,
-                                                 SCH_TABLE_PRIVILEGES,
-                                                 db_name);
-  col_grants= create_is_iterator<ColGrantIterator>(thd,
-                                                 SCH_COLUMN_PRIVILEGES,
-                                                 db_name);
-}
-
-Obj *GrantObjIterator::next()
-{
-  Obj *obj= 0;
-  obj= db_grants->next();
-  if (!obj)
-    obj= tbl_grants->next();
-  if (!obj)
-    obj= col_grants->next();
-  return obj;
-}
+Obj *Grant_iterator::next()
+{
+  Ed_row *row= m_row_it++;
 
-/**
-  Creates a high-level iterator that iterates over database-, table-,
-  routine-, and column-level privileges which shall permit a single
-  iterator from the si_objects to retrieve all of the privileges for
-  a given database.
+  if (!row)
+    return NULL;
 
-  @param[IN] thd      Current THD object
-  @param[IN] db_name  Name of database to get grants
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 6);
 
-  @Note The client is responsible for destroying the returned iterator.
+  const Ed_column *user_name= row->get_column(0);
+  const Ed_column *host_name= row->get_column(1);
+  const Ed_column *privilege_type= row->get_column(2);
+  const Ed_column *db_name= row->get_column(3);
+  const Ed_column *tbl_name= row->get_column(4);
+  const Ed_column *col_name= row->get_column(5);
+
+  LEX_STRING table_name= { C_STRING_WITH_LEN("") };
+  LEX_STRING column_name= { C_STRING_WITH_LEN("") };
+
+  if (tbl_name)
+    table_name= *tbl_name;
+
+  if (col_name)
+    column_name= *col_name;
+
+  Grant_obj *grant= new Grant_obj(user_name->str, user_name->length,
+                                  host_name->str, host_name->length,
+                                  privilege_type->str, privilege_type->length,
+                                  db_name->str, db_name->length,
+                                  table_name.str, table_name.length,
+                                  column_name.str, column_name.length);
 
-  @return a pointer to an iterator object.
-    @retval NULL in case of error.
-*/
-Obj_iterator *get_all_db_grants(THD *thd, const String *db_name)
-{
-  return new GrantObjIterator(thd, db_name);
+  return grant ? grant : NULL;
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
-//
-// Implementation: dependency functions.
-//
+template
+Grant_iterator *
+create_row_set_iterator<Grant_iterator>(THD *thd, const LEX_STRING *query);
 
 ///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
 
-Obj_iterator* get_view_base_tables(THD *thd,
-                                   const String *db_name,
-                                   const String *view_name)
-{
-  return ViewBaseObjectsIterator::create(
-    thd, db_name, view_name, ViewBaseObjectsIterator::GET_BASE_TABLES);
-}
-
-Obj_iterator* get_view_base_views(THD *thd,
-                                  const String *db_name,
-                                  const String *view_name)
+Database_obj::Database_obj(const char *db_name_str, int db_name_length)
 {
-  return ViewBaseObjectsIterator::create(
-    thd, db_name, view_name, ViewBaseObjectsIterator::GET_BASE_VIEWS);
+  m_db_name.copy(db_name_str, db_name_length, system_charset_info);
 }
 
 ///////////////////////////////////////////////////////////////////////////
 
-//
-// Implementation: DatabaseObj class.
-//
-
-///////////////////////////////////////////////////////////////////////////
-
-DatabaseObj::DatabaseObj(const String *db_name)
-{
-  m_db_name.copy(*db_name); // copy name string to newly allocated memory
-}
-
 /**
   Serialize the object.
 
   This method produces the data necessary for materializing the object
   on restore (creates object).
 
-  @param[in]  thd            Thread context.
-  @param[out] serialization  The data needed to recreate this object.
+  @param[in]  thd Thread context.
+  @param[out] os  Output stream.
 
   @note this method will return an error if the db_name is either
         mysql or information_schema as these are not objects that
@@ -1949,315 +1635,435 @@ DatabaseObj::DatabaseObj(const String *d
    @retval FALSE on success
    @retval TRUE on error
 */
-bool DatabaseObj::do_serialize(THD *thd, String *serialization)
+
+bool Database_obj::do_serialize(THD *thd, Out_stream &os)
 {
-  HA_CREATE_INFO create;
-  DBUG_ENTER("DatabaseObj::serialize()");
-  DBUG_PRINT("DatabaseObj::serialize", ("name: %s", m_db_name.c_ptr()));
+  DBUG_ENTER("Database_obj::serialize()");
+  DBUG_PRINT("Database_obj::serialize",
+             ("name: %.*s",
+              m_db_name.length(), m_db_name.ptr()));
 
   if (is_internal_db_name(&m_db_name))
   {
-    DBUG_PRINT("backup",(" Skipping internal database %s", m_db_name.c_ptr()));
+    DBUG_PRINT("backup",
+               (" Skipping internal database %.*s",
+                m_db_name.length(), m_db_name.ptr()));
+
     DBUG_RETURN(TRUE);
   }
-  create.default_table_charset= system_charset_info;
 
-  if (check_db_dir_existence(m_db_name.c_ptr()))
+  /* Run 'SHOW CREATE' query. */
+
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
+
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SHOW CREATE DATABASE `%.*s`",
+    (int) m_db_name.length(),
+    (const char *) m_db_name.ptr());
+
+  Ed_result result(thd->mem_root);
+
+  if (run_query(thd, &query, &result) ||
+      result.get_warnings()->elements > 0)
   {
-    my_error(ER_BAD_DB_ERROR, MYF(0), m_db_name.c_ptr());
+    /*
+      There should be no warnings. A warning means that serialization has
+      failed.
+    */
+    log_warnings(&result);
     DBUG_RETURN(TRUE);
   }
 
-  load_db_opt_by_name(thd, m_db_name.c_ptr(), &create);
+  /* Generate serialization. */
 
-  serialization->append(STRING_WITH_LEN("CREATE DATABASE "));
-  append_identifier(thd, serialization, m_db_name.c_ptr(), m_db_name.length());
+  DBUG_ASSERT(result.elements == 1);
 
-  if (create.default_table_charset)
-  {
-    serialization->append(STRING_WITH_LEN(" DEFAULT CHARACTER SET "));
-    serialization->append(create.default_table_charset->csname);
-    if (!(create.default_table_charset->state & MY_CS_PRIMARY))
-    {
-      serialization->append(STRING_WITH_LEN(" COLLATE "));
-      serialization->append(create.default_table_charset->name);
-    }
-  }
-  DBUG_RETURN(FALSE);
-}
+  Ed_result_set *rs= result.get_cur_result_set();
 
-/**
-  Materialize the serialization string.
+  DBUG_ASSERT(rs);
 
-  This method saves serialization string into a member variable.
+  if (rs->data()->elements == 0)
+    DBUG_RETURN(TRUE);
 
-  @param[in]  serialization_version   version number of this interface
-  @param[in]  serialization           the string from serialize()
+  DBUG_ASSERT(rs->data()->elements == 1);
+
+  List_iterator_fast<Ed_row> row_it(*rs->data());
+  Ed_row *row= row_it++;
+
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
+
+  const Ed_column *create_stmt= row->get_column(1);
+
+  os <<
+    "SET @saved_cs_client = @@character_set_client" <<
+    "SET character_set_client = utf8" <<
+    Fmt("DROP DATABASE IF EXISTS `%.*s`", STR(m_db_name)) <<
+    create_stmt <<
+    "SET character_set_client = @saved_cs_client";
 
-  @todo take serialization_version into account
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-  */
-bool DatabaseObj::materialize(uint serialization_version,
-                             const String *serialization)
-{
-  DBUG_ENTER("DatabaseObj::materialize()");
-  m_create_stmt.copy(*serialization);
   DBUG_RETURN(FALSE);
 }
 
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Table_obj::Table_obj(const char *db_name_str, int db_name_length,
+                   const char *table_name_str, int table_name_length)
+{
+  m_db_name.copy(db_name_str, db_name_length, system_charset_info);
+  m_table_name.copy(table_name_str, table_name_length, system_charset_info);
+}
+
+///////////////////////////////////////////////////////////////////////////
+
 /**
-  Create the object.
+  Serialize the object.
 
-  This method uses serialization string in a query and executes it.
+  This method produces the data necessary for materializing the object
+  on restore (creates object).
 
-  @param[in]  thd  Thread context.
+  @param[in]  thd Thread context.
+  @param[out] os  Output stream.
 
   @returns Error status.
     @retval FALSE on success
     @retval TRUE on error
 */
-bool DatabaseObj::do_execute(THD *thd)
+
+bool Table_obj::do_serialize(THD *thd, Out_stream &os)
 {
-  DBUG_ENTER("DatabaseObj::execute()");
-  drop(thd);
-  DBUG_RETURN(silent_exec(thd, &m_create_stmt));
-}
+  DBUG_ENTER("Table_obj::serialize()");
+  DBUG_PRINT("Table_obj::serialize",
+             ("name: %.*s.%.*s",
+              m_db_name.length(), m_db_name.ptr(),
+              m_table_name.length(), m_table_name.ptr()));
 
-/**
-  Drop the object.
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
 
-  This method calls the silent_exec method to execute the query.
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SHOW CREATE TABLE `%.*s`.`%.*s`",
+    (int) m_db_name.length(),
+    (const char *) m_db_name.ptr(),
+    (int) m_table_name.length(),
+    (const char *) m_table_name.ptr());
 
-  @note This uses "IF EXISTS" and does not return error if
-        object does not exist.
+  Ed_result result(thd->mem_root);
 
-        @param[in]  thd            Thread context.
-  @param[out] serialization  the data needed to recreate this object
+  if (run_query(thd, &query, &result) ||
+      result.get_warnings()->elements > 0)
+  {
+    /*
+      There should be no warnings. A warning means that serialization has
+      failed.
+    */
+    log_warnings(&result);
+    DBUG_RETURN(TRUE);
+  }
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool DatabaseObj::drop(THD *thd)
-{
-  DBUG_ENTER("DatabaseObj::drop()");
-  DBUG_RETURN(drop_object(thd,
-                          (char *) "DATABASE",
-                          0,
-                          &m_db_name));
-}
+  DBUG_ASSERT(result.elements == 1);
 
-///////////////////////////////////////////////////////////////////////////
+  Ed_result_set *rs= result.get_cur_result_set();
 
-//
-// Implementation: TableObj class.
-//
+  DBUG_ASSERT(rs);
 
-///////////////////////////////////////////////////////////////////////////
+  if (rs->data()->elements == 0)
+    DBUG_RETURN(TRUE);
 
-TableObj::TableObj(const String *db_name,
-                   const String *table_name,
-                   bool table_is_view) :
-  m_table_is_view(table_is_view)
-{
-  m_db_name.copy(*db_name);
-  m_table_name.copy(*table_name);
-}
+  DBUG_ASSERT(rs->data()->elements == 1);
 
-bool TableObj::serialize_table(THD *thd, String *serialization)
-{
-  return 0;
+  List_iterator_fast<Ed_row> row_it(*rs->data());
+  Ed_row *row= row_it++;
+
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
+
+  const Ed_column *create_stmt= row->get_column(1);
+
+  os <<
+    "SET @saved_cs_client = @@character_set_client" <<
+    "SET character_set_client = utf8" <<
+    Fmt("USE `%.*s`", STR(m_db_name)) <<
+    create_stmt <<
+    "SET character_set_client = @saved_cs_client";
+
+  DBUG_RETURN(FALSE);
 }
 
-bool TableObj::serialize_view(THD *thd, String *serialization)
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+View_obj::View_obj(const char *db_name_str, int db_name_length,
+                 const char *view_name_str, int view_name_length)
 {
-  return 0;
+  m_db_name.copy(db_name_str, db_name_length, system_charset_info);
+  m_view_name.copy(view_name_str, view_name_length, system_charset_info);
 }
 
-/**
-  Serialize the object.
+///////////////////////////////////////////////////////////////////////////
 
-  This method produces the data necessary for materializing the object
-  on restore (creates object).
+static bool
+get_view_create_stmt(THD *thd,
+                     View_obj *view,
+                     const LEX_STRING **create_stmt,
+                     const LEX_STRING **client_cs_name,
+                     const LEX_STRING **connection_cl_name)
+{
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
 
-  @param[in]  thd            Thread context.
-  @param[out] serialization  The data needed to recreate this object.
+  /* Get a create statement for a view. */
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool TableObj::do_serialize(THD *thd, String *serialization)
-{
-  bool ret= 0;
-  LEX_STRING tname, dbname;
-  DBUG_ENTER("TableObj::serialize()");
-  DBUG_PRINT("TableObj::serialize", ("name: %s@%s", m_db_name.c_ptr(),
-             m_table_name.c_ptr()));
-
-  prepend_db(thd, serialization, &m_db_name);
-  tname.str= m_table_name.c_ptr();
-  tname.length= m_table_name.length();
-  dbname.str= m_db_name.c_ptr();
-  dbname.length= m_db_name.length();
-  Table_ident *name_id= new Table_ident(tname);
-  name_id->db= dbname;
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SHOW CREATE VIEW `%.*s`.`%.*s`",
+    (int) view->get_db_name()->length(),
+    (const char *) view->get_db_name()->ptr(),
+    (int) view->get_name()->length(),
+    (const char *) view->get_name()->ptr());
 
-  /*
-    Add the view to the table list and set the thd to look at views only.
-    Note: derived from sql_yacc.yy.
-  */
-  thd->lex->select_lex.add_table_to_list(thd, name_id, NULL, 0);
-  TABLE_LIST *table_list= (TABLE_LIST*)thd->lex->select_lex.table_list.first;
-  thd->lex->sql_command = SQLCOM_SHOW_CREATE;
+  Ed_result result(thd->mem_root);
 
-  /*
-    Setup view specific variables and settings
-  */
-  if (m_table_is_view)
+  if (run_query(thd, &query, &result) ||
+      result.get_warnings()->elements > 0)
   {
-    thd->lex->only_view= 1;
-    thd->lex->view_prepare_mode= TRUE; // use prepare mode
-    table_list->skip_temporary= 1;     // skip temporary tables
+    /*
+      There should be no warnings. A warning means that serialization has
+      failed.
+    */
+    log_warnings(&result);
+    return TRUE;
   }
 
-  /*
-    Open the view and its base tables or views
-  */
-  if (open_normal_and_derived_tables(thd, table_list, 0)) {
-    close_thread_tables(thd);
-    thd->lex->select_lex.table_list.empty();
-    DBUG_RETURN(TRUE);
-  }
+  DBUG_ASSERT(result.elements == 1);
 
-  /*
-    Setup view specific variables and settings
-  */
-  if (m_table_is_view)
+  Ed_result_set *rs= result.get_cur_result_set();
+
+  DBUG_ASSERT(rs);
+
+  if (rs->data()->elements == 0)
+    return TRUE;
+
+  DBUG_ASSERT(rs->data()->elements == 1);
+
+  List_iterator_fast<Ed_row> row_it(*rs->data());
+  Ed_row *row= row_it++;
+
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 4);
+
+  *create_stmt= row->get_column(1);
+  *client_cs_name= row->get_column(2);
+  *connection_cl_name= row->get_column(3);
+
+  return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+static bool
+dump_base_object_stubs(THD *thd,
+                       Obj_iterator *base_object_it,
+                       Out_stream &os)
+{
+  char base_obj_stmt_buf[QUERY_BUFFER_SIZE];
+  String base_obj_stmt(base_obj_stmt_buf,
+                        sizeof (base_obj_stmt_buf),
+                        system_charset_info);
+
+  while (true)
   {
-    View_creation_ctx *creation_ctx= table_list->view_creation_ctx;
+    Obj *base_obj= base_object_it->next();
 
-    /*
-      append character set client charset information
-    */
-    serialization->append("SET CHARACTER_SET_CLIENT = '");
-    serialization->append(creation_ctx->get_client_cs()->csname);
-    serialization->append("'; ");
+    if (!base_obj)
+      break;
+
+    /* Dump header of base obj stub. */
+
+    os <<
+      Fmt("CREATE DATABASE IF NOT EXISTS `%.*s`",
+          (int) base_obj->get_db_name()->length(),
+          (const char *) base_obj->get_db_name()->ptr());
+
+    base_obj_stmt.length(0);
+    base_obj_stmt.append(C_STRING_WITH_LEN("CREATE TABLE IF NOT EXISTS `"));
+    base_obj_stmt.append(*base_obj->get_db_name());
+    base_obj_stmt.append(C_STRING_WITH_LEN("`.`"));
+    base_obj_stmt.append(*base_obj->get_name());
+    base_obj_stmt.append(C_STRING_WITH_LEN("`("));
+
+    /* Get base obj structure. */
+
+    char query_buffer[QUERY_BUFFER_SIZE];
+    LEX_STRING query;
+
+    query.str= query_buffer;
+    query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+      "SHOW COLUMNS FROM `%.*s`.`%.*s`",
+      (int) base_obj->get_db_name()->length(),
+      (const char *) base_obj->get_db_name()->ptr(),
+      (int) base_obj->get_name()->length(),
+      (const char *) base_obj->get_name()->ptr());
+
+    Ed_result result(thd->mem_root);
+
+    if (run_query(thd, &query, &result) ||
+        result.get_warnings()->elements > 0)
+    {
+      /*
+        There should be no warnings. A warning means that serialization has
+        failed.
+      */
+      log_warnings(&result);
+      delete base_obj;
+      return TRUE;
+    }
+
+    DBUG_ASSERT(result.elements == 1);
+
+    Ed_result_set *rs= result.get_cur_result_set();
+    DBUG_ASSERT(rs);
+
+    /* Dump structure of base obj stub. */
+
+    List_iterator_fast<Ed_row> row_it(*rs->data());
+    bool first_column= TRUE;
+
+    while (true)
+    {
+      Ed_row *row= row_it++;
+
+      if (!row)
+        break;
+
+      DBUG_ASSERT(row->get_metadata()->get_num_columns() == 6);
+
+      const LEX_STRING *col_name= row->get_column(0);
+      const LEX_STRING *col_type= row->get_column(1);
+
+      if (first_column)
+        first_column= FALSE;
+      else
+        base_obj_stmt.append(C_STRING_WITH_LEN(", "));
+
+      base_obj_stmt.append(C_STRING_WITH_LEN("`"));
+      base_obj_stmt.append(col_name->str, col_name->length);
+      base_obj_stmt.append(C_STRING_WITH_LEN("` "));
+      base_obj_stmt.append(col_type->str, col_type->length);
+    }
 
-    /*
-      append collation_connection information
-    */
-    serialization->append("SET COLLATION_CONNECTION = '");
-    serialization->append(creation_ctx->get_connection_cl()->name);
-    serialization->append("'; ");
+    base_obj_stmt.append(C_STRING_WITH_LEN(") ENGINE = MyISAM"));
 
-    table_list->view_db= dbname;
-    serialization->set_charset(creation_ctx->get_client_cs());
+    os << base_obj_stmt;
+
+    delete base_obj;
   }
 
-  /*
-    Get the create statement and close up shop.
-  */
-  ret= m_table_is_view ?
-    view_store_create_info(thd, table_list, serialization) :
-    store_create_info(thd, table_list, serialization, NULL,
-                      /* show_database */ TRUE);
-  close_thread_tables(thd);
-  serialization->set_charset(system_charset_info);
-  thd->lex->select_lex.table_list.empty();
-  DBUG_RETURN(FALSE);
+  return FALSE;
 }
 
-/**
-  Materialize the serialization string.
+///////////////////////////////////////////////////////////////////////////
 
-  This method saves serialization string into a member variable.
+/**
+  Serialize the object.
 
-  @param[in]  serialization_version   version number of this interface
-  @param[in]  serialization           the string from serialize()
+  This method produces the data necessary for materializing the object
+  on restore (creates object).
 
-  @todo take serialization_version into account
+  @param[in]  thd Thread context.
+  @param[out] os  Output stream.
 
   @returns Error status.
     @retval FALSE on success
     @retval TRUE on error
-  */
-bool TableObj::materialize(uint serialization_version,
-                           const String *serialization)
+*/
+bool View_obj::do_serialize(THD *thd, Out_stream &os)
 {
-  DBUG_ENTER("TableObj::materialize()");
-  m_create_stmt.copy(*serialization);
-  DBUG_RETURN(FALSE);
-}
+  DBUG_ENTER("View_obj::serialize()");
+  DBUG_PRINT("View_obj::serialize",
+             ("name: %.*s.%.*s",
+              m_db_name.length(), m_db_name.ptr(),
+              m_view_name.length(), m_view_name.ptr()));
 
-/**
-  Create the object represented by TableObj in the database.
+  const LEX_STRING *create_stmt;
+  const LEX_STRING *client_cs_name;
+  const LEX_STRING *connection_cl_name;
 
-  This method uses serialization string in a query and executes it.
+  if (get_view_create_stmt(thd, this, &create_stmt,
+                           &client_cs_name, &connection_cl_name))
+  {
+    DBUG_RETURN(TRUE);
+  }
 
-  @param[in]  thd  Thread context.
+  /* Dump the header. */
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool TableObj::do_execute(THD *thd)
-{
-  DBUG_ENTER("TableObj::execute()");
-  drop(thd);
-  DBUG_RETURN(silent_exec(thd, &m_create_stmt));
-}
+  os <<
+    "SET @saved_cs_client = @@character_set_client" <<
+    "SET @saved_col_connection = @@collation_connection" <<
+    "SET character_set_client = utf8";
 
-/**
-  Drop the object.
+  /* Get view dependencies. */
+
+  {
+    Obj_iterator *base_table_it=
+      get_view_base_tables(thd, &m_db_name, &m_view_name);
+
+    if (!base_table_it ||
+        dump_base_object_stubs(thd, base_table_it, os))
+    {
+      DBUG_RETURN(TRUE);
+    }
 
-  This method calls the silent_exec method to execute the query.
+    delete base_table_it;
+  }
 
-  @note This uses "IF EXISTS" and does not return error if
-        object does not exist.
+  {
+    Obj_iterator *base_view_it=
+      get_view_base_views(thd, &m_db_name, &m_view_name);
 
-  @param[in]  thd            Thread context.
-  @param[out] serialization  The data needed to recreate this object.
+    if (!base_view_it ||
+        dump_base_object_stubs(thd, base_view_it, os))
+    {
+      DBUG_RETURN(TRUE);
+    }
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool TableObj::drop(THD *thd)
-{
-  DBUG_ENTER("TableObj::drop()");
-  DBUG_RETURN(drop_object(thd,
-                          (char *) "TABLE",
-                          &m_db_name,
-                          &m_table_name));
+    delete base_view_it;
+  }
+
+  os <<
+    Fmt("USE `%.*s`", STR(m_db_name)) <<
+    Fmt("SET character_set_client = %.*s", LXS(client_cs_name)) <<
+    Fmt("SET collation_connection = %.*s", LXS(connection_cl_name)) <<
+    create_stmt <<
+    "SET character_set_client = @saved_cs_client" <<
+    "SET collation_connection = @saved_col_connection";
+
+  DBUG_RETURN(FALSE);
 }
 
 ///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: TriggerObj class.
-//
 ///////////////////////////////////////////////////////////////////////////
 
-TriggerObj::TriggerObj(const String *db_name,
-                             const String *trigger_name)
+Trigger_obj::Trigger_obj(const char *db_name_str, int db_name_length,
+                       const char *trigger_name_str, int trigger_name_length)
 {
-  // copy strings to newly allocated memory
-  m_db_name.copy(*db_name);
-  m_trigger_name.copy(*trigger_name);
+  m_db_name.copy(db_name_str, db_name_length, system_charset_info);
+  m_trigger_name.copy(trigger_name_str, trigger_name_length,
+                      system_charset_info);
 }
 
+///////////////////////////////////////////////////////////////////////////
+
 /**
   Serialize the object.
 
   This method produces the data necessary for materializing the object
   on restore (creates object).
 
-  @param[in]  thd            Thread handler.
-  @param[out] serialization  The data needed to recreate this object.
+  @param[in]  thd Thread handler.
+  @param[out] os  Output stream.
 
   @note this method will return an error if the db_name is either
         mysql or information_schema as these are not objects that
@@ -2267,190 +2073,101 @@ TriggerObj::TriggerObj(const String *db_
     @retval FALSE on success
     @retval TRUE on error
 */
-bool TriggerObj::do_serialize(THD *thd, String *serialization)
-{
-  bool ret= false;
-  uint num_tables;
-  sp_name *trig_name;
-  LEX_STRING trg_name;
-  ulonglong trg_sql_mode;
-  LEX_STRING trg_sql_mode_str;
-  LEX_STRING trg_sql_original_stmt;
-  LEX_STRING trg_client_cs_name;
-  LEX_STRING trg_connection_cl_name;
-  LEX_STRING trg_db_cl_name;
-  CHARSET_INFO *trg_client_cs;
-  DBUG_ENTER("TriggerObj::serialize()");
-
-  DBUG_PRINT("TriggerObj::serialize", ("name: %s in %s",
-             m_trigger_name.c_ptr(), m_db_name.c_ptr()));
-
-  prepend_db(thd, serialization, &m_db_name);
-  LEX_STRING db;
-  db.str= m_db_name.c_ptr();
-  db.length= m_db_name.length();
-  LEX_STRING t_name;
-  t_name.str= m_trigger_name.c_ptr();
-  t_name.length= m_trigger_name.length();
-  trig_name= new sp_name(db, t_name, true);
-  trig_name->init_qname(thd);
-  TABLE_LIST *lst= get_trigger_table(thd, trig_name);
-  if (!lst)
-    DBUG_RETURN(FALSE);
 
-  alloc_mdl_locks(lst, thd->mem_root);
+bool Trigger_obj::do_serialize(THD *thd, Out_stream &os)
+{
+  DBUG_ENTER("Trigger_obj::do_serialize()");
+  DBUG_PRINT("Trigger_obj::do_serialize",
+             ("name: %.*s.%.*s",
+              m_db_name.length(), m_db_name.ptr(),
+              m_trigger_name.length(), m_trigger_name.ptr()));
 
   DBUG_EXECUTE_IF("backup_fail_add_trigger", DBUG_RETURN(TRUE););
-  if (open_tables(thd, &lst, &num_tables, 0))
-    DBUG_RETURN(TRUE);
-
-  DBUG_ASSERT(num_tables == 1);
-  Table_triggers_list *triggers= lst->table->triggers;
-  if (!triggers)
-    DBUG_RETURN(FALSE);
-
-  int trigger_idx= triggers->find_trigger_by_name(&trig_name->m_name);
-  if (trigger_idx < 0)
-    DBUG_RETURN(FALSE);
-
-  triggers->get_trigger_info(thd,
-                             trigger_idx,
-                             &trg_name,
-                             &trg_sql_mode,
-                             &trg_sql_original_stmt,
-                             &trg_client_cs_name,
-                             &trg_connection_cl_name,
-                             &trg_db_cl_name);
-  sys_var_thd_sql_mode::symbolic_mode_representation(thd,
-                                                     trg_sql_mode,
-                                                     &trg_sql_mode_str);
-
-  /*
-    prepend SQL Mode
-  */
-  serialization->append("SET SQL_MODE = '");
-  serialization->append(trg_sql_mode_str.str);
-  serialization->append("'; ");
-
-  /*
-    append character set client charset information
-  */
-  serialization->append("SET CHARACTER_SET_CLIENT = '");
-  serialization->append(trg_client_cs_name.str);
-  serialization->append("'; ");
-
-  /*
-    append collation_connection information
-  */
-  serialization->append("SET COLLATION_CONNECTION = '");
-  serialization->append(trg_connection_cl_name.str);
-  serialization->append("'; ");
 
-  /*
-    append collation_connection information
-  */
-  serialization->append("SET COLLATION_DATABASE = '");
-  serialization->append(trg_db_cl_name.str);
-  serialization->append("'; ");
-
-  if (resolve_charset(trg_client_cs_name.str, NULL, &trg_client_cs))
-    ret= false;
-  else
-    serialization->append(trg_sql_original_stmt.str);
-  close_thread_tables(thd);
-  thd->lex->select_lex.table_list.empty();
-  serialization->set_charset(system_charset_info);
-  DBUG_RETURN(ret);
-}
-
-/**
-  Materialize the serialization string.
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
 
-  This method saves serialization string into a member variable.
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SHOW CREATE TRIGGER `%.*s`.`%.*s`",
+    (int) m_db_name.length(),
+    (const char *) m_db_name.ptr(),
+    (int) m_trigger_name.length(),
+    (const char *) m_trigger_name.ptr());
 
-  @param[in]  serialization_version   version number of this interface
-  @param[in]  serialization           the string from serialize()
+  Ed_result result(thd->mem_root);
 
-  @todo take serialization_version into account
-
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool TriggerObj::materialize(uint serialization_version,
-                             const String *serialization)
-{
-  DBUG_ENTER("TriggerObj::materialize()");
-  m_create_stmt.copy(*serialization);
-  DBUG_RETURN(0);
-}
+  if (run_query(thd, &query, &result) ||
+      result.get_warnings()->elements > 0)
+  {
+    /*
+      There should be no warnings. A warning means that serialization has
+      failed.
+    */
+    log_warnings(&result);
+    DBUG_RETURN(TRUE);
+  }
 
-/**
-  Create the object.
+  DBUG_ASSERT(result.elements == 1);
 
-  This method uses serialization string in a query and executes it.
+  Ed_result_set *rs= result.get_cur_result_set();
 
-  @param[in]  thd  Thread context.
+  DBUG_ASSERT(rs);
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool TriggerObj::do_execute(THD *thd)
-{
-  DBUG_ENTER("TriggerObj::execute()");
-  drop(thd);
-  DBUG_RETURN(execute_with_ctx(thd, &m_create_stmt, false));
-}
+  if (rs->data()->elements == 0)
+    DBUG_RETURN(TRUE);
 
-/**
-  Drop the object.
+  DBUG_ASSERT(rs->data()->elements == 1);
 
-  This method calls the silent_exec method to execute the query.
+  List_iterator_fast<Ed_row> row_it(*rs->data());
+  Ed_row *row= row_it++;
 
-  @note This uses "IF EXISTS" and does not return error if
-        object does not exist.
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 6);
 
-  @param[in]  thd            Thread context.
-  @param[out] serialization  The data needed to recreate this object.
+  const Ed_column *sql_mode= row->get_column(1);
+  const Ed_column *create_stmt= row->get_column(2);
+  const Ed_column *client_cs= row->get_column(3);
+  const Ed_column *connection_cl= row->get_column(4);
+  const Ed_column *db_cl= row->get_column(5);
+
+  os <<
+    "SET @saved_cs_client = @@character_set_client" <<
+    "SET @saved_col_connection = @@collation_connection" <<
+    "SET @saved_col_database = @@collation_database" <<
+    "SET character_set_client = utf8" <<
+    Fmt("USE `%.*s`", STR(m_db_name)) <<
+    Fmt("SET character_set_client = %.*s", LXS(client_cs)) <<
+    Fmt("SET collation_connection = %.*s", LXS(connection_cl)) <<
+    Fmt("SET collation_database = %.*s", LXS(db_cl)) <<
+    Fmt("SET sql_mode = '%.*s'", LXS(sql_mode)) <<
+    create_stmt <<
+    "SET character_set_client = @saved_cs_client" <<
+    "SET collation_connection = @saved_col_connection" <<
+    "SET collation_database = @saved_col_database";
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool TriggerObj::drop(THD *thd)
-{
-  DBUG_ENTER("TriggerObj::drop()");
-  DBUG_RETURN(drop_object(thd,
-                          (char *) "TRIGGER",
-                          &m_db_name,
-                          &m_trigger_name));
+  DBUG_RETURN(FALSE);
 }
 
 ///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: StoredProcObj class.
-//
-
 ///////////////////////////////////////////////////////////////////////////
 
-StoredProcObj::StoredProcObj(const String *db_name,
-                             const String *stored_proc_name)
+Stored_proc_obj::Stored_proc_obj(const char *db_name_str, int db_name_length,
+                             const char *sp_name_str, int sp_name_length)
 {
-  // copy strings to newly allocated memory
-  m_db_name.copy(*db_name);
-  m_stored_proc_name.copy(*stored_proc_name);
+  m_db_name.copy(db_name_str, db_name_length, system_charset_info);
+  m_sp_name.copy(sp_name_str, sp_name_length, system_charset_info);
 }
 
+///////////////////////////////////////////////////////////////////////////
+
 /**
   Serialize the object.
 
   This method produces the data necessary for materializing the object
   on restore (creates object).
 
-  @param[in]  thd            Thread context.
-  @param[out] serialization  The data needed to recreate this object.
+  @param[in]  thd Thread context.
+  @param[out] os  Output stream.
 
   @note this method will return an error if the db_name is either
         mysql or information_schema as these are not objects that
@@ -2458,107 +2175,99 @@ StoredProcObj::StoredProcObj(const Strin
 
   @returns Error status.
 */
-bool StoredProcObj::do_serialize(THD *thd, String *serialization)
-{
-  bool ret= false;
-  DBUG_ENTER("StoredProcObj::serialize()");
-  DBUG_PRINT("StoredProcObj::serialize", ("name: %s in %s",
-             m_stored_proc_name.c_ptr(), m_db_name.c_ptr()));
-  prepend_db(thd, serialization, &m_db_name);
-  ret= serialize_routine(thd, TYPE_ENUM_PROCEDURE, m_db_name,
-                         m_stored_proc_name, serialization);
-  serialization->set_charset(system_charset_info);
-  DBUG_RETURN(ret);
-}
-
-/**
-  Materialize the serialization string.
-
-  This method saves serialization string into a member variable.
 
-  @param[in]  serialization_version   version number of this interface
-  @param[in]  serialization           the string from serialize()
+bool Stored_proc_obj::do_serialize(THD *thd, Out_stream &os)
+{
+  DBUG_ENTER("Stored_proc_obj::do_serialize()");
+  DBUG_PRINT("Stored_proc_obj::do_serialize",
+             ("name: %.*s.%.*s",
+              m_db_name.length(), m_db_name.ptr(),
+              m_sp_name.length(), m_sp_name.ptr()));
+
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
+
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SHOW CREATE PROCEDURE `%.*s`.`%.*s`",
+    (int) m_db_name.length(),
+    (const char *) m_db_name.ptr(),
+    (int) m_sp_name.length(),
+    (const char *) m_sp_name.ptr());
 
-  @todo take serialization_version into account
+  Ed_result result(thd->mem_root);
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool StoredProcObj::materialize(uint serialization_version,
-                             const String *serialization)
-{
-  DBUG_ENTER("StoredProcObj::materialize()");
-  m_create_stmt.copy(*serialization);
-  DBUG_RETURN(0);
-}
+  if (run_query(thd, &query, &result) ||
+      result.get_warnings()->elements > 0)
+  {
+    /*
+      There should be no warnings. A warning means that serialization has
+      failed.
+    */
+    log_warnings(&result);
+    DBUG_RETURN(TRUE);
+  }
 
-/**
-  Create the object.
+  DBUG_ASSERT(result.elements == 1);
 
-  This method uses serialization string in a query and executes it.
+  Ed_result_set *rs= result.get_cur_result_set();
 
-  @param[in]  thd  current thread
+  DBUG_ASSERT(rs);
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool StoredProcObj::do_execute(THD *thd)
-{
-  DBUG_ENTER("StoredProcObj::execute()");
-  drop(thd);
-  DBUG_RETURN(execute_with_ctx(thd, &m_create_stmt, false));
-}
+  if (rs->data()->elements == 0)
+    DBUG_RETURN(TRUE);
 
-/**
-  Drop the object.
+  DBUG_ASSERT(rs->data()->elements == 1);
 
-  This method calls the silent_exec method to execute the query.
+  List_iterator_fast<Ed_row> row_it(*rs->data());
+  Ed_row *row= row_it++;
 
-  @note This uses "IF EXISTS" and does not return error if
-        object does not exist.
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 6);
 
-  @param[in]  thd            current thread
-  @param[out] serialization  the data needed to recreate this object
+  const Ed_column *sql_mode= row->get_column(1);
+  const Ed_column *create_stmt= row->get_column(2);
+  const Ed_column *client_cs= row->get_column(3);
+  const Ed_column *connection_cl= row->get_column(4);
+  const Ed_column *db_cl= row->get_column(5);
+
+  os <<
+    "SET @saved_cs_client = @@character_set_client" <<
+    "SET @saved_col_connection = @@collation_connection" <<
+    "SET @saved_col_database = @@collation_database" <<
+    "SET character_set_client = utf8" <<
+    Fmt("USE `%.*s`", STR(m_db_name)) <<
+    Fmt("SET character_set_client = %.*s", LXS(client_cs)) <<
+    Fmt("SET collation_connection = %.*s", LXS(connection_cl)) <<
+    Fmt("SET collation_database = %.*s", LXS(db_cl)) <<
+    Fmt("SET sql_mode = '%.*s'", LXS(sql_mode)) <<
+    create_stmt <<
+    "SET character_set_client = @saved_cs_client" <<
+    "SET collation_connection = @saved_col_connection" <<
+    "SET collation_database = @saved_col_database";
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool StoredProcObj::drop(THD *thd)
-{
-  DBUG_ENTER("StoredProcObj::drop()");
-  DBUG_RETURN(drop_object(thd,
-                          (char *) "PROCEDURE",
-                          &m_db_name,
-                          &m_stored_proc_name));
+  DBUG_RETURN(FALSE);
 }
 
 ///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: StoredFuncObj class.
-//
-
 ///////////////////////////////////////////////////////////////////////////
 
-StoredFuncObj::StoredFuncObj(const String *db_name,
-                             const String *stored_func_name)
+Stored_func_obj::Stored_func_obj(const char *db_name_str, int db_name_length,
+                             const char *sf_name_str, int sf_name_length)
 {
-  // copy strings to newly allocated memory
-  m_db_name.copy(*db_name);
-  m_stored_func_name.copy(*stored_func_name);
+  m_db_name.copy(db_name_str, db_name_length, system_charset_info);
+  m_sf_name.copy(sf_name_str, sf_name_length, system_charset_info);
 }
 
+///////////////////////////////////////////////////////////////////////////
+
 /**
   Serialize the object.
 
   This method produces the data necessary for materializing the object
   on restore (creates object).
 
-  @param[in]  thd            Thread context.
-  @param[out] serialization  The data needed to recreate this object.
+  @param[in]  thd Thread context.
+  @param[out] os  Output stream.
 
   @note this method will return an error if the db_name is either
         mysql or information_schema as these are not objects that
@@ -2567,108 +2276,102 @@ StoredFuncObj::StoredFuncObj(const Strin
   @returns Error status.
     @retval FALSE on success
     @retval TRUE on error
- */
-bool  StoredFuncObj::do_serialize(THD *thd, String *serialization)
-{
-  bool ret= false;
-  DBUG_ENTER("StoredFuncObj::serialize()");
-  DBUG_PRINT("StoredProcObj::serialize", ("name: %s in %s",
-              m_stored_func_name.c_ptr(), m_db_name.c_ptr()));
-  prepend_db(thd, serialization, &m_db_name);
-  ret= serialize_routine(thd, TYPE_ENUM_FUNCTION, m_db_name,
-                         m_stored_func_name, serialization);
-  serialization->set_charset(system_charset_info);
-  DBUG_RETURN(ret);
-}
-
-/**
-  Materialize the serialization string.
-
-  This method saves serialization string into a member variable.
+*/
 
-  @param[in]  serialization_version   version number of this interface
-  @param[in]  serialization           the string from serialize()
+bool Stored_func_obj::do_serialize(THD *thd, Out_stream &os)
+{
+  DBUG_ENTER("Stored_func_obj::do_serialize()");
+  DBUG_PRINT("Stored_func_obj::do_serialize",
+             ("name: %.*s.%.*s",
+              m_db_name.length(), m_db_name.ptr(),
+              m_sf_name.length(), m_sf_name.ptr()));
+
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
+
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SHOW CREATE FUNCTION `%.*s`.`%.*s`",
+    (int) m_db_name.length(),
+    (const char *) m_db_name.ptr(),
+    (int) m_sf_name.length(),
+    (const char *) m_sf_name.ptr());
 
-  @todo take serialization_version into account
+  Ed_result result(thd->mem_root);
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool StoredFuncObj::materialize(uint serialization_version,
-                             const String *serialization)
-{
-  DBUG_ENTER("StoredFuncObj::materialize()");
-  m_create_stmt.copy(*serialization);
-  DBUG_RETURN(0);
-}
+  if (run_query(thd, &query, &result) ||
+      result.get_warnings()->elements > 0)
+  {
+    /*
+      There should be no warnings. A warning means that serialization has
+      failed.
+    */
+    log_warnings(&result);
+    DBUG_RETURN(TRUE);
+  }
 
-/**
-  Create the object.
+  DBUG_ASSERT(result.elements == 1);
 
-  This method uses serialization string in a query and executes it.
+  Ed_result_set *rs= result.get_cur_result_set();
 
-  @param[in]  thd  Thread context.
+  DBUG_ASSERT(rs);
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool StoredFuncObj::do_execute(THD *thd)
-{
-  DBUG_ENTER("StoredFuncObj::execute()");
-  drop(thd);
-  DBUG_RETURN(execute_with_ctx(thd, &m_create_stmt, false));
-}
+  if (rs->data()->elements == 0)
+    DBUG_RETURN(TRUE);
 
-/**
-  Drop the object.
+  DBUG_ASSERT(rs->data()->elements == 1);
 
-  This method calls the silent_exec method to execute the query.
+  List_iterator_fast<Ed_row> row_it(*rs->data());
+  Ed_row *row= row_it++;
 
-  @note This uses "IF EXISTS" and does not return error if
-        object does not exist.
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 6);
 
-  @param[in]  thd            Thread context.
-  @param[out] serialization  The data needed to recreate this object.
+  const Ed_column *sql_mode= row->get_column(1);
+  const Ed_column *create_stmt= row->get_column(2);
+  const Ed_column *client_cs= row->get_column(3);
+  const Ed_column *connection_cl= row->get_column(4);
+  const Ed_column *db_cl= row->get_column(5);
+
+  os <<
+    "SET @saved_cs_client = @@character_set_client" <<
+    "SET @saved_col_connection = @@collation_connection" <<
+    "SET @saved_col_database = @@collation_database" <<
+    "SET character_set_client = utf8" <<
+    Fmt("USE `%.*s`", STR(m_db_name)) <<
+    Fmt("SET character_set_client = %.*s", LXS(client_cs)) <<
+    Fmt("SET collation_connection = %.*s", LXS(connection_cl)) <<
+    Fmt("SET collation_database = %.*s", LXS(db_cl)) <<
+    Fmt("SET sql_mode = '%.*s'", LXS(sql_mode)) <<
+    create_stmt <<
+    "SET character_set_client = @saved_cs_client" <<
+    "SET collation_connection = @saved_col_connection" <<
+    "SET collation_database = @saved_col_database";
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool StoredFuncObj::drop(THD *thd)
-{
-  DBUG_ENTER("StoredFuncObj::drop()");
-  DBUG_RETURN(drop_object(thd,
-                          (char *) "FUNCTION",
-                          &m_db_name,
-                          &m_stored_func_name));
+  DBUG_RETURN(FALSE);
 }
 
 ///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: EventObj class.
-//
-
 /////////////////////////////////////////////////////////////////////////////
+
 #ifdef HAVE_EVENT_SCHEDULER
-EventObj::EventObj(const String *db_name,
-                   const String *event_name)
+
+Event_obj::Event_obj(const char *db_name_str, int db_name_length,
+                   const char *event_name_str, int event_name_length)
 {
-  // copy strings to newly allocated memory
-  m_db_name.copy(*db_name);
-  m_event_name.copy(*event_name);
+  m_db_name.copy(db_name_str, db_name_length, system_charset_info);
+  m_event_name.copy(event_name_str, event_name_length, system_charset_info);
 }
 
+///////////////////////////////////////////////////////////////////////////
+
 /**
   Serialize the object.
 
   This method produces the data necessary for materializing the object
   on restore (creates object).
 
-  @param[in]  thd            Thread context.
-  @param[out] serialization  The data needed to recreate this object.
+  @param[in]  thd Thread context.
+  @param[out] os  Output stream.
 
   @note this method will return an error if the db_name is either
         mysql or information_schema as these are not objects that
@@ -2678,206 +2381,158 @@ EventObj::EventObj(const String *db_name
     @retval FALSE on success
     @retval TRUE on error
 */
-bool EventObj::do_serialize(THD *thd, String *serialization)
-{
-  bool ret= false;
-  Open_tables_state open_tables_backup;
-  Event_timed et;
-  LEX_STRING sql_mode;
-  DBUG_ENTER("EventObj::serialize()");
-  DBUG_PRINT("EventObj::serialize", ("name: %s.%s", m_db_name.c_ptr(),
-             m_event_name.c_ptr()));
-
-  prepend_db(thd, serialization, &m_db_name);
-  Event_db_repository *db_repository= Events::get_db_repository();
-  thd->reset_n_backup_open_tables_state(&open_tables_backup);
-  LEX_STRING db;
-  db.str= m_db_name.c_ptr();
-  db.length= m_db_name.length();
-  LEX_STRING ev;
-  ev.str= m_event_name.c_ptr();
-  ev.length= m_event_name.length();
-  ret= db_repository->load_named_event(thd, db, ev, &et);
-  thd->restore_backup_open_tables_state(&open_tables_backup);
-  if (sys_var_thd_sql_mode::symbolic_mode_representation(thd,
-    et.sql_mode, &sql_mode))
-    DBUG_RETURN(TRUE);
-  if (!ret)
-  {
-    /*
-      Prepend sql_mode command.
-    */
-    serialization->append("SET SQL_MODE = '");
-    serialization->append(sql_mode.str);
-    serialization->append("'; ");
-
-    /*
-      append time zone information
-    */
-    serialization->append("SET TIME_ZONE = '");
-    const String *tz= et.time_zone->get_name();
-    serialization->append(tz->ptr());
-    serialization->append("'; ");
 
-    /*
-      append character set client charset information
-    */
-    serialization->append("SET CHARACTER_SET_CLIENT = '");
-    serialization->append(et.creation_ctx->get_client_cs()->csname);
-    serialization->append("'; ");
+bool Event_obj::do_serialize(THD *thd, Out_stream &os)
+{
+  DBUG_ENTER("Event_obj::serialize()");
+  DBUG_PRINT("Event_obj::serialize",
+             ("name: %.*s.%.*s",
+              m_db_name.length(), m_db_name.ptr(),
+              m_event_name.length(), m_event_name.ptr()));
+
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
+
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SHOW CREATE EVENT `%.*s`.`%.*s`",
+    (int) m_db_name.length(),
+    (const char *) m_db_name.ptr(),
+    (int) m_event_name.length(),
+    (const char *) m_event_name.ptr());
 
-    /*
-      append collation_connection information
-    */
-    serialization->append("SET COLLATION_CONNECTION = '");
-    serialization->append(et.creation_ctx->get_connection_cl()->name);
-    serialization->append("'; ");
+  Ed_result result(thd->mem_root);
 
+  if (run_query(thd, &query, &result) ||
+      result.get_warnings()->elements > 0)
+  {
     /*
-      append collation_connection information
+      There should be no warnings. A warning means that serialization has
+      failed.
     */
-    serialization->append("SET COLLATION_DATABASE = '");
-    serialization->append(et.creation_ctx->get_db_cl()->name);
-    serialization->append("'; ");
-
-    if (et.get_create_event(thd, serialization))
-      DBUG_RETURN(0);
+    log_warnings(&result);
+    DBUG_RETURN(TRUE);
   }
-  serialization->set_charset(system_charset_info);
-  DBUG_RETURN(0);
-}
 
-/**
-  Materialize the serialization string.
+  DBUG_ASSERT(result.elements == 1);
 
-  This method saves serialization string into a member variable.
+  Ed_result_set *rs= result.get_cur_result_set();
 
-  @param[in]  serialization_version   version number of this interface
-  @param[in]  serialization           the string from serialize()
+  DBUG_ASSERT(rs);
 
-  @todo take serialization_version into account
+  if (rs->data()->elements == 0)
+    DBUG_RETURN(TRUE);
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool EventObj::materialize(uint serialization_version,
-                             const String *serialization)
-{
-  DBUG_ENTER("EventObj::materialize()");
-  m_create_stmt.copy(*serialization);
-  DBUG_RETURN(0);
-}
+  DBUG_ASSERT(rs->data()->elements == 1);
 
-/**
-  Create the object.
+  List_iterator_fast<Ed_row> row_it(*rs->data());
+  Ed_row *row= row_it++;
 
-  This method uses serialization string in a query and executes it.
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 7);
 
-  @param[in]  thd  Thread context.
+  const Ed_column *sql_mode= row->get_column(1);
+  const Ed_column *tz= row->get_column(2);
+  const Ed_column *create_stmt= row->get_column(3);
+  const Ed_column *client_cs= row->get_column(4);
+  const Ed_column *connection_cl= row->get_column(5);
+  const Ed_column *db_cl= row->get_column(6);
+
+  os <<
+    "SET @saved_time_zone = @@time_zone" <<
+    "SET @saved_cs_client = @@character_set_client" <<
+    "SET @saved_col_connection = @@collation_connection" <<
+    "SET @saved_col_database = @@collation_database" <<
+    "SET character_set_client = utf8" <<
+    Fmt("USE `%.*s`", STR(m_db_name)) <<
+    Fmt("SET time_zone = '%.*s'", LXS(tz)) <<
+    Fmt("SET character_set_client = %.*s", LXS(client_cs)) <<
+    Fmt("SET collation_connection = %.*s", LXS(connection_cl)) <<
+    Fmt("SET collation_database = %.*s", LXS(db_cl)) <<
+    Fmt("SET sql_mode = '%.*s'", LXS(sql_mode)) <<
+    create_stmt <<
+    "SET time_zone = @saved_time_zone" <<
+    "SET character_set_client = @saved_cs_client" <<
+    "SET collation_connection = @saved_col_connection" <<
+    "SET collation_database = @saved_col_database";
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool EventObj::do_execute(THD *thd)
-{
-  DBUG_ENTER("EventObj::execute()");
-  drop(thd);
-  DBUG_RETURN(execute_with_ctx(thd, &m_create_stmt, true));
+  DBUG_RETURN(FALSE);
 }
 
-/**
-  Drop the object.
-
-  This method calls the silent_exec method to execute the query.
-
-  @note This uses "IF EXISTS" and does not return error if
-        object does not exist.
-
-  @param[in]  thd            Thread context.
-  @param[out] serialization  the data needed to recreate this object
-
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool EventObj::drop(THD *thd)
-{
-  DBUG_ENTER("EventObj::drop()");
-  DBUG_RETURN(drop_object(thd,
-                          (char *) "EVENT",
-                          &m_db_name,
-                          &m_event_name));
-}
 #endif // HAVE_EVENT_SCHEDULER
 
 ///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: TablespaceObj class.
-//
-
 /////////////////////////////////////////////////////////////////////////////
 
-TablespaceObj::TablespaceObj(const String *ts_name)
-{
-  // copy strings to newly allocated memory
-  m_ts_name.copy(*ts_name);
-  m_datafile.length(0);
-  m_comments.length(0);
+Tablespace_obj::Tablespace_obj(
+  const char *ts_name_str, int ts_name_length,
+  const char *comment_str, int comment_length,
+  const char *data_file_name_str, int data_file_name_length,
+  const char *engine_str, int engine_length)
+{
+  m_ts_name.copy(ts_name_str, ts_name_length, system_charset_info);
+  m_comment.copy(comment_str, comment_length, system_charset_info);
+  m_data_file_name.copy(data_file_name_str, data_file_name_length,
+                        system_charset_info);
+  m_engine.copy(engine_str, engine_length, system_charset_info);
+
+  m_description.length(0);
+}
+
+Tablespace_obj::Tablespace_obj(const char *ts_name_str, int ts_name_length)
+{
+  m_ts_name.copy(ts_name_str, ts_name_length, system_charset_info);
+  m_comment.length(0);
+  m_data_file_name.length(0);
   m_engine.length(0);
+
+  m_description.length(0);
 }
 
+///////////////////////////////////////////////////////////////////////////
+
 /**
   Serialize the object.
 
   This method produces the data necessary for materializing the object
   on restore (creates object).
 
-  @param[in]  thd            Thread context.
-  @param[out] serialization  The data needed to recreate this object.
+  @param[in]  thd Thread context.
+  @param[out] os  Output stream.
 
   @returns Error status.
     @retval FALSE on success
     @retval TRUE on error
 */
-bool TablespaceObj::do_serialize(THD *thd, String *serialization)
-{
-  DBUG_ENTER("TablespaceObj::serialize()");
-  build_serialization();
-  serialization->copy(m_create_stmt);
-  DBUG_RETURN(FALSE);
-}
 
-/**
-  Materialize the serialization string.
+bool Tablespace_obj::do_serialize(THD *thd, Out_stream &os)
+{
+  DBUG_ENTER("Tablespace_obj::serialize()");
 
-  This method saves serialization string into a member variable.
-  Also extracts tablespace engine name from serialization string.
+  os << *get_description();
 
-  @param[in]  serialization_version   version number of this interface
-  @param[in]  serialization           the string from serialize()
+  DBUG_RETURN(FALSE);
+}
 
-  @todo take serialization_version into account
+///////////////////////////////////////////////////////////////////////////
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool TablespaceObj::materialize(uint serialization_version,
-                                const String *serialization)
+bool Tablespace_obj::materialize(uint serialization_version,
+                                 const String *serialization)
 {
-  DBUG_ENTER("TablespaceObj::materialize()");
-  m_create_stmt.copy(*serialization);
-  /* Extract engine from create statement */
-  String tmp_str= String("=", 1, system_charset_info);
-  int pos= m_create_stmt.strrstr(tmp_str, m_create_stmt.length());
-  m_engine.copy(m_create_stmt.ptr() + pos + 1, m_create_stmt.length() - pos - 1,
-                system_charset_info);
-  DBUG_RETURN(FALSE);
+  if (Abstract_obj::materialize(serialization_version, serialization))
+    return TRUE;
+
+  List_iterator_fast<String> it(m_stmt_lst);
+  String *desc= it++;
+
+  DBUG_ASSERT(desc);
+
+  m_description.set(desc->ptr(), desc->length(), desc->charset());
+
+  return FALSE;
 }
 
+///////////////////////////////////////////////////////////////////////////
+
 /**
   Get a description of the tablespace object.
 
@@ -2886,171 +2541,115 @@ bool TablespaceObj::materialize(uint ser
 
   @returns Serialization string.
 */
-const String *TablespaceObj::describe()
+
+const String *Tablespace_obj::get_description()
 {
-  DBUG_ENTER("TablespaceObj::describe()");
-  DBUG_RETURN(build_serialization());
-}
+  DBUG_ENTER("Tablespace_obj::get_description()");
 
-/**
-  Build the serialization string.
+  DBUG_ASSERT(m_description.length() ||
+              m_ts_name.length() && m_data_file_name.length());
 
-  This constructs the serialization string for identification
-  use in describing tablespace to the user and for creating the
-  tablespace.
+  if (m_description.length())
+    DBUG_RETURN(&m_description);
 
-  @todo take serialization_version into account
+  /* Construct the CREATE TABLESPACE command from the variables. */
 
-  @returns Serialization string.
-*/
-const String *TablespaceObj::build_serialization()
-{
-  DBUG_ENTER("TablespaceObj::build_serialization()");
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
 
-  if (m_create_stmt.length())
-    DBUG_RETURN(&m_create_stmt);
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "CREATE TABLESPACE `%.*s` ADD DATAFILE '%.*s' ",
+    (int) m_ts_name.length(),
+    (const char *) m_ts_name.ptr(),
+    (int) m_data_file_name.length(),
+    (const char *) m_data_file_name.ptr());
 
-  /*
-    Construct the CREATE TABLESPACE command from the variables.
-  */
-  m_create_stmt.length(0);
-  m_create_stmt.append("CREATE TABLESPACE ");
-  if (m_ts_name.length() > 0)
-  {
-    THD *thd= current_thd;
-    append_identifier(thd, &m_create_stmt,
-      m_ts_name.c_ptr(), m_ts_name.length());
-  }
-  m_create_stmt.append(" ADD DATAFILE '");
-  m_create_stmt.append(m_datafile);
-  if (m_comments.length())
+  m_description.length(0);
+  m_description.append(query.str, query.length);
+
+  if (m_comment.length())
   {
-    m_create_stmt.append("' COMMENT = '");
-    m_create_stmt.append(m_comments);
+    m_description.append("COMMENT = '");
+    m_description.append(m_comment);
+    m_description.append("' ");
   }
-  m_create_stmt.append("' ENGINE=");
-  m_create_stmt.append(m_engine);
-  DBUG_RETURN(&m_create_stmt);
-}
 
-/**
-  Create the object.
-
-  This method uses serialization string in a query and executes it.
+  m_description.append("ENGINE = ");
+  m_description.append(m_engine);
 
-  @param[in]  thd  Thread context.
-
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool TablespaceObj::do_execute(THD *thd)
-{
-  DBUG_ENTER("TablespaceObj::execute()");
-  build_serialization(); // Build the CREATE command.
-  DBUG_RETURN(silent_exec(thd, &m_create_stmt));
+  DBUG_RETURN(&m_description);
 }
 
 ///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: DbGrantObj class.
-//
 /////////////////////////////////////////////////////////////////////////////
 
-DbGrantObj::DbGrantObj(const String *grantee,
-                       const String *db_name,
-                       const String *priv_type)
-{
-  // copy strings to newly allocated memory
-  m_db_name.copy(*db_name);
-  m_grantee.copy(*grantee);
-  m_name.copy(*grantee);
-  m_priv_type.copy(*priv_type);
-}
-
-/**
-  Serialize the object.
+void Grant_obj::generate_unique_id(const String *user_name,
+                                   const String *host_name,
+                                   String *id)
+{
+  static unsigned long id_counter= 0;
 
-  This method produces the data necessary for materializing the object
-  on restore (creates object).
+  id->length(0);
 
-  @param[in]  thd            Thread context.
-  @param[out] serialization  The data needed to recreate this object.
+  if (user_name->length() && host_name->length())
+  {
+    id->append(*user_name);
+    id->append('@');
+    id->append(*host_name);
+  }
+  else
+    id->append("<no_name>");
 
-  @note this method will return an error if the db_name is either
-        mysql or information_schema as these are not objects that
-        should be recreated using this interface.
+  char buf[10];
+  snprintf(buf, 10, " %08lu", ++id_counter);
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool DbGrantObj::do_serialize(THD *thd, String *serialization)
-{
-  DBUG_ENTER("DbGrantObj::do_serialize()");
-  serialization->length(0);
-  serialization->append("GRANT ");
-  serialization->append(m_priv_type);
-  serialization->append(" ON ");
-  serialization->append(m_db_name);
-  serialization->append(".* TO ");
-  serialization->append(m_grantee);
-  DBUG_RETURN(0);
+  id->append(buf, 10);
 }
 
-/**
-  Materialize the serialization string.
+Grant_obj::Grant_obj(const char *user_name_str, int user_name_length,
+                     const char *host_name_str, int host_name_length,
+                     const char *priv_type_str, int priv_type_length,
+                     const char *db_name_str, int db_name_length,
+                     const char *table_name_str, int table_name_length,
+                     const char *column_name_str, int column_name_length)
+{
+  m_user_name.copy(user_name_str, user_name_length, system_charset_info);
+  m_host_name.copy(host_name_str, host_name_length, system_charset_info);
 
-  This method saves serialization string into a member variable.
+  /* Grant info. */
 
-  @param[in]  serialization_version   version number of this interface
-  @param[in]  serialization           the string from serialize()
+  m_grant_info.append(priv_type_str, priv_type_length);
 
-  @todo take serialization_version into account
+  if (column_name_length)
+  {
+    m_grant_info.append('(');
+    m_grant_info.append(column_name_str, column_name_length);
+    m_grant_info.append(')');
+  }
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool DbGrantObj::materialize(uint serialization_version,
-                             const String *serialization)
-{
-  DBUG_ENTER("DbGrantObj::materialize()");
-  m_grant_stmt.copy(*serialization);
-  DBUG_RETURN(0);
-}
+  m_grant_info.append(" ON ");
 
-/**
-  Create the object.
+  m_grant_info.append(db_name_str, db_name_length);
+  m_grant_info.append('.');
 
-  This method uses serialization string in a query and executes it.
+  if (table_name_length)
+    m_grant_info.append(table_name_str, table_name_length);
+  else
+    m_grant_info.append('*');
 
-  @param[in]  thd  Thread context.
+  /* Id. */
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool DbGrantObj::do_execute(THD *thd)
-{
-  DBUG_ENTER("DbGrantObj::do_execute()");
-  DBUG_RETURN(execute_with_ctx(thd, &m_grant_stmt, true));
+  generate_unique_id(&m_user_name, &m_host_name, &m_id);
 }
 
-///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: TblGrantObj class.
-//
-/////////////////////////////////////////////////////////////////////////////
-
-TblGrantObj::TblGrantObj(const String *grantee,
-                         const String *db_name,
-                         const String *table_name,
-                         const String *priv_type)
-: DbGrantObj(grantee, db_name, priv_type)
+Grant_obj::Grant_obj(const char *name_str, int name_length)
 {
-  // copy strings to newly allocated memory
-  m_table_name.copy(*table_name);
+  m_user_name.length(0);
+  m_host_name.length(0);
+  m_grant_info.length(0);
+
+  m_id.copy(name_str, name_length, system_charset_info);
 }
 
 /**
@@ -3059,8 +2658,8 @@ TblGrantObj::TblGrantObj(const String *g
   This method produces the data necessary for materializing the object
   on restore (creates object).
 
-  @param[in]  thd            Thread context.
-  @param[out] serialization  The data needed to recreate this object.
+  @param[in]  thd Thread context.
+  @param[out] os  Output stream.
 
   @note this method will return an error if the db_name is either
         mysql or information_schema as these are not objects that
@@ -3070,127 +2669,168 @@ TblGrantObj::TblGrantObj(const String *g
     @retval FALSE on success
     @retval TRUE on error
 */
-bool TblGrantObj::do_serialize(THD *thd, String *serialization)
+
+bool Grant_obj::do_serialize(THD *thd, Out_stream &os)
 {
-  DBUG_ENTER("TblGrantObj::do_serialize()");
-  serialization->length(0);
-  serialization->append("GRANT ");
-  serialization->append(m_priv_type);
-  serialization->append(" ON ");
-  serialization->append(m_db_name);
-  serialization->append(".");
-  serialization->append(m_table_name);
-  serialization->append(" TO ");
-  serialization->append(m_grantee);
-  DBUG_RETURN(0);
-}
+  DBUG_ENTER("Grant_obj::do_serialize()");
 
-///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: ColGrantObj class.
-//
-/////////////////////////////////////////////////////////////////////////////
+  os <<
+    m_user_name <<
+    m_host_name <<
+    m_grant_info <<
+    "SET @saved_cs_client = @@character_set_client" <<
+    "SET character_set_client= binary" <<
+    Fmt("GRANT %.*s TO '%.*s'@'%.*s'",
+        STR(m_grant_info), STR(m_user_name), STR(m_host_name)) <<
+    "SET character_set_client= @saved_cs_client";
 
-ColGrantObj::ColGrantObj(const String *grantee,
-                         const String *db_name,
-                         const String *table_name,
-                         const String *col_name,
-                         const String *priv_type)
-: TblGrantObj(grantee, db_name, table_name, priv_type)
-{
-  // copy strings to newly allocated memory
-  m_col_name.copy(*col_name);
+  DBUG_RETURN(FALSE);
 }
 
-/**
-  Serialize the object.
+bool Grant_obj::do_materialize(In_stream *is)
+{
+  LEX_STRING user_name;
+  LEX_STRING host_name;
+  LEX_STRING grant_info;
 
-  This method produces the data necessary for materializing the object
-  on restore (creates object).
+  if (is->next(&user_name))
+    return TRUE; /* Can not decode user name. */
 
-  @param[in]  thd            Thread context.
-  @param[out] serialization  The data needed to recreate this object.
+  if (is->next(&host_name))
+    return TRUE; /* Can not decode host name. */
 
-  @note this method will return an error if the db_name is either
-        mysql or information_schema as these are not objects that
-        should be recreated using this interface.
+  if (is->next(&grant_info))
+    return TRUE; /* Can not decode grant info. */
 
-  @returns Error status.
-    @retval FALSE on success
-    @retval TRUE on error
-*/
-bool ColGrantObj::do_serialize(THD *thd, String *serialization)
-{
-  DBUG_ENTER("ColGrantObj::do_serialize()");
-  serialization->length(0);
-  serialization->append("GRANT ");
-  serialization->append(m_priv_type);
-  serialization->append("(");
-  serialization->append(m_col_name);
-  serialization->append(") ON ");
-  serialization->append(m_db_name);
-  serialization->append(".");
-  serialization->append(m_table_name);
-  serialization->append(" TO ");
-  serialization->append(m_grantee);
-  DBUG_RETURN(0);
+  m_user_name.copy(user_name.str, user_name.length, system_charset_info);
+  m_host_name.copy(host_name.str, host_name.length, system_charset_info);
+  m_grant_info.copy(grant_info.str, grant_info.length, system_charset_info);
+
+  return Abstract_obj::do_materialize(is);
 }
 
 ///////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
 
 Obj *get_database(const String *db_name)
 {
-  return new DatabaseObj(db_name);
+  return new Database_obj(db_name->ptr(), db_name->length());
 }
 
 Obj *get_table(const String *db_name,
                const String *table_name)
 {
-  return new TableObj(db_name, table_name, false);
+  return new Table_obj(db_name->ptr(), db_name->length(),
+                      table_name->ptr(), table_name->length());
 }
 
 Obj *get_view(const String *db_name,
               const String *view_name)
 {
-  return new TableObj(db_name, view_name, true);
+  return new View_obj(db_name->ptr(), db_name->length(),
+                     view_name->ptr(), view_name->length());
 }
 
 Obj *get_trigger(const String *db_name,
                  const String *trigger_name)
 {
-  return new TriggerObj(db_name, trigger_name);
+  return new Trigger_obj(db_name->ptr(), db_name->length(),
+                        trigger_name->ptr(), trigger_name->length());
 }
 
 Obj *get_stored_procedure(const String *db_name,
                           const String *sp_name)
 {
-  return new StoredProcObj(db_name, sp_name);
+  return new Stored_proc_obj(db_name->ptr(), db_name->length(),
+                           sp_name->ptr(), sp_name->length());
 }
 
 Obj *get_stored_function(const String *db_name,
                          const String *sf_name)
 {
-  return new StoredFuncObj(db_name, sf_name);
+  return new Stored_func_obj(db_name->ptr(), db_name->length(),
+                           sf_name->ptr(), sf_name->length());
 }
 
 Obj *get_event(const String *db_name,
                const String *event_name)
 {
 #ifdef HAVE_EVENT_SCHEDULER
-  return new EventObj(db_name, event_name);
+  return new Event_obj(db_name->ptr(), db_name->length(),
+                      event_name->ptr(), event_name->length());
 #else
   return NULL;
 #endif
 }
 
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Obj_iterator *get_databases(THD *thd)
+{
+  return Database_iterator::create(thd);
+}
+
+Obj_iterator *get_db_tables(THD *thd, const String *db_name)
+{
+  return Db_tables_iterator::create(thd, db_name);
+}
+
+Obj_iterator *get_db_views(THD *thd, const String *db_name)
+{
+  return Db_views_iterator::create(thd, db_name);
+}
+
+Obj_iterator *get_db_triggers(THD *thd, const String *db_name)
+{
+  return Db_trigger_iterator::create(thd, db_name);
+}
+
+Obj_iterator *get_db_stored_procedures(THD *thd, const String *db_name)
+{
+  return Db_stored_proc_iterator::create(thd, db_name);
+}
+
+Obj_iterator *get_db_stored_functions(THD *thd, const String *db_name)
+{
+  return Db_stored_func_iterator::create(thd, db_name);
+}
+
+Obj_iterator *get_db_events(THD *thd, const String *db_name)
+{
+  return Db_event_iterator::create(thd, db_name);
+}
+
+Obj_iterator *get_all_db_grants(THD *thd, const String *db_name)
+{
+  return Grant_iterator::create(thd, db_name);
+}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Obj_iterator* get_view_base_tables(THD *thd,
+                                   const String *db_name,
+                                   const String *view_name)
+{
+  return View_base_table_iterator::create(thd, db_name, view_name);
+}
+
+Obj_iterator* get_view_base_views(THD *thd,
+                                  const String *db_name,
+                                  const String *view_name)
+{
+  return View_base_view_iterator::create(thd, db_name, view_name);
+}
 
 ///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
 
 Obj *materialize_database(const String *db_name,
                           uint serialization_version,
                           const String *serialization)
 {
-  Obj *obj= new DatabaseObj(db_name);
+  Obj *obj= new Database_obj(db_name->ptr(), db_name->length());
   obj->materialize(serialization_version, serialization);
 
   return obj;
@@ -3201,7 +2841,8 @@ Obj *materialize_table(const String *db_
                        uint serialization_version,
                        const String *serialization)
 {
-  Obj *obj= new TableObj(db_name, table_name, false);
+  Obj *obj= new Table_obj(db_name->ptr(), db_name->length(),
+                          table_name->ptr(), table_name->length());
   obj->materialize(serialization_version, serialization);
 
   return obj;
@@ -3212,7 +2853,8 @@ Obj *materialize_view(const String *db_n
                       uint serialization_version,
                       const String *serialization)
 {
-  Obj *obj= new TableObj(db_name, view_name, true);
+  Obj *obj= new View_obj(db_name->ptr(), db_name->length(),
+                         view_name->ptr(), view_name->length());
   obj->materialize(serialization_version, serialization);
 
   return obj;
@@ -3223,85 +2865,76 @@ Obj *materialize_trigger(const String *d
                          uint serialization_version,
                          const String *serialization)
 {
-  Obj *obj= new TriggerObj(db_name, trigger_name);
+  Obj *obj= new Trigger_obj(db_name->ptr(), db_name->length(),
+                            trigger_name->ptr(), trigger_name->length());
   obj->materialize(serialization_version, serialization);
 
   return obj;
 }
 
 Obj *materialize_stored_procedure(const String *db_name,
-                                  const String *stored_proc_name,
+                                  const String *sp_name,
                                   uint serialization_version,
                                   const String *serialization)
 {
-  Obj *obj= new StoredProcObj(db_name, stored_proc_name);
+  Obj *obj= new Stored_proc_obj(db_name->ptr(), db_name->length(),
+                                sp_name->ptr(), sp_name->length());
   obj->materialize(serialization_version, serialization);
 
   return obj;
 }
 
 Obj *materialize_stored_function(const String *db_name,
-                                 const String *stored_func_name,
+                                 const String *sf_name,
                                  uint serialization_version,
                                  const String *serialization)
 {
-  Obj *obj= new StoredFuncObj(db_name, stored_func_name);
+  Obj *obj= new Stored_func_obj(db_name->ptr(), db_name->length(),
+                                sf_name->ptr(), sf_name->length());
   obj->materialize(serialization_version, serialization);
 
   return obj;
 }
 
 #ifdef HAVE_EVENT_SCHEDULER
+
 Obj *materialize_event(const String *db_name,
                        const String *event_name,
                        uint serialization_version,
                        const String *serialization)
 {
-  Obj *obj= new EventObj(db_name, event_name);
+  Obj *obj= new Event_obj(db_name->ptr(), db_name->length(),
+                          event_name->ptr(), event_name->length());
   obj->materialize(serialization_version, serialization);
 
   return obj;
 }
+
 #endif
 
 Obj *materialize_tablespace(const String *ts_name,
                             uint serialization_version,
                             const String *serialization)
 {
-  Obj *obj= new TablespaceObj(ts_name);
+  Obj *obj= new Tablespace_obj(ts_name->ptr(), ts_name->length());
   obj->materialize(serialization_version, serialization);
 
   return obj;
 }
 
-Obj *get_db_grant(const String *grantee,
-                  const String *db_name)
-{
-  String priv_type;
-  priv_type.length(0);
-
-  return new DbGrantObj(grantee, db_name, &priv_type);
-}
-
 Obj *materialize_db_grant(const String *db_name,
-                          const String *grantee,
+                          const String *name,
                           uint serialization_version,
                           const String *serialization)
 {
-  /*
-    Here we create a grant for the purposes of applying the
-    grants. We use DbGrantObj for all types of grants because
-    we only have the GRANT statement in the serialization
-    string and therefore do not that the 'parts' to create
-    the specific types.
-  */
-  Obj *obj= get_db_grant(grantee, db_name);
+  Obj *obj= new Grant_obj(name->ptr(), name->length());
   obj->materialize(serialization_version, serialization);
 
   return obj;
 }
 
 ///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
 
 bool is_internal_db_name(const String *db_name)
 {
@@ -3319,370 +2952,222 @@ bool is_internal_db_name(const String *d
 
 ///////////////////////////////////////////////////////////////////////////
 
-bool check_db_existence(const String *db_name)
+bool check_db_existence(THD *thd, const String *db_name)
 {
-  return check_db_dir_existence(((String *) db_name)->c_ptr_safe());
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
+
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SHOW CREATE DATABASE `%.*s`",
+    (int) db_name->length(),
+    (const char *) db_name->ptr());
+
+  Ed_result result(thd->mem_root);
+  int rc= run_query(thd, &query, &result);
+
+  /* We're not interested in warnings/errors here. */
+
+  return rc != 0;
 }
 
-/*
-  Splits grantee clause into user and host portions. Needed for checking
-  to see if user exists on system.
-*/
-int split_user_host(String *grantee, String *user, String *host)
+///////////////////////////////////////////////////////////////////////////
+
+bool check_user_existence(THD *thd, const Obj *obj)
 {
-  int len= 0;
-  int tics= 0;
-  char *ptr= 0;
+#ifdef EMBEDDED_LIBRARY
+  return TRUE;
+#else
+  Grant_obj *grant_obj= (Grant_obj *) obj;
 
-  /*
-    Since passwords are single byte characters and usernames can be multibyte
-    characters and the 0x40 = 64 = @ can occur in the username, we must search
-    for the first @ from the right.
-  */
-  len= grantee->length();
-  len--;
-  ptr= grantee->c_ptr() + len;
-  while ((len > 0) && (*ptr != '@'))
-  {
-    len--;
-    ptr= grantee->c_ptr() + len;
-  }
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
 
-  if (ptr == 0)
-    return -1;
-  len= ptr - grantee->c_ptr();
-  user->length(0);
-  char *cptr= grantee->c_ptr();
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SELECT 1 "
+    "FROM mysql.user "
+    "WHERE user = '%.*s' AND host = '%.*s'",
+    (int) grant_obj->get_user_name()->length(),
+    (const char *) grant_obj->get_user_name()->ptr(),
+    (int) grant_obj->get_host_name()->length(),
+    (const char *) grant_obj->get_host_name()->ptr());
 
-  /*
-    String ' from strings.
-  */
-  if (strncmp(cptr, "'", 1) == 0)
-  {
-    cptr++;
-    len--;
-    tics++;
-  }
-  user->append(cptr, len - tics);
-  len= grantee->length() - len - 1 - tics;
-  host->length(0);
+  Ed_result result(thd->mem_root);
 
-  /*
-    String ' from strings.
-  */
-  cptr= ptr + 1;
-  tics= 0;
-  if (strncmp(cptr, "'", 1) == 0)
-  {
-    cptr++;
-    len--;
-  }
-  if (strncmp(cptr+len-1, "'", 1) == 0)
-    tics++;
-  host->append(cptr, len - tics);
-  return 0;
-}
-
-bool check_user_existence(THD *thd, const String *grantee)
-{
-  String user;
-  String host;
-  bool user_exists= FALSE;
-
-  user.length(0);
-  host.length(0);
-  if (grantee)
-  {
-#ifndef EMBEDDED_LIBRARY
-    split_user_host((String *)grantee, &user, &host);
-    if (!user.ptr())
-      user.append("''");
-    user_exists= is_acl_user(host.ptr(), user.ptr());
-#else
-    user_exists= TRUE;
-#endif
+  if (run_query(thd, &query, &result) ||
+      result.get_warnings()->elements > 0)
+  {
+    /* Should be no warnings. */
+    sql_print_information("");
+    log_warnings(&result);
+    return FALSE;
   }
-  return user_exists;
-}
 
-/**
-  Locate the row in the information_schema view for this tablespace.
+  Ed_result_set *rs= result.get_cur_result_set();
 
-  This method returns a row from a tablespace information_schema view
-  that matches the tablespace name passed.
+  if (!rs)
+    return FALSE;
 
-  @param[in]     thd           Thread context
-  @param[in]     is_table_idx  The information schema to search
-  @param[in]     ts_name       The name of the tablespace to find
-  @param[in]     ts_engine     Engine of the tablespace to find
-  @param[out]    datafile      The datafile for the tablespace
-  @param[out]    comments      The comments for the tablespace
-
-  @retval FALSE if tablespace exists and no errors
-  @retval TRUE if tablespace does not exist or errors
-*/
-static bool find_tablespace_schema_row(THD *thd,
-                                       enum_schema_tables is_table_idx,
-                                       const String *ts_name,
-                                       const String *ts_engine,
-                                       String *datafile,
-                                       String *comments)
-{
-  TABLE *is_table;
-  handler *ha;
-  my_bitmap_map *orig_col;
-  LEX_STRING lex_ts_name;
-  String found_ts_name, found_ts_engine;
-  bool retval= TRUE;
-  String data;
-  List<LEX_STRING> ts_list;
-  DBUG_ENTER("obs::find_tablespace_schema_row()");
+  return rs->data()->elements > 0;
+#endif
+}
 
-  /*
-    First, open the IS table.
-  */
-  lex_ts_name.str= (char *)ts_name->ptr();
-  lex_ts_name.length= ts_name->length();
-  ts_list.push_back(&lex_ts_name);
+///////////////////////////////////////////////////////////////////////////
 
-  if (InformationSchemaIterator::prepare_is_table(
-      thd, &is_table, &ha, &orig_col, is_table_idx, ts_list))
-    DBUG_RETURN(TRUE);
+const String *grant_get_user_name(const Obj *obj)
+{
+  return ((Grant_obj *) obj)->get_user_name();
+}
 
-  /* Locate the row in the schema table and retrive the data. */
-  switch (is_table_idx) {
-  case SCH_TABLESPACES:
-    while (!ha->rnd_next(is_table->record[0]))
-    {
-      is_table->field[IS_TABLESPACES_TABLESPACE_NAME]->val_str(&found_ts_name);
-      is_table->field[IS_TABLESPACES_ENGINE]->val_str(&found_ts_engine);
-      if (found_ts_name.length() && found_ts_engine.length() &&
-          !my_strnncoll(system_charset_info, (const uchar*) found_ts_name.ptr(),
-                        found_ts_name.length(), (const uchar*) ts_name->ptr(),
-                        ts_name->length()) &&
-          !my_strnncoll(system_charset_info,
-                        (const uchar*) found_ts_engine.ptr(),
-                        found_ts_engine.length(),
-                        (const uchar*) ts_engine->ptr(), ts_engine->length()))
-      {
-        retval= FALSE;
-        is_table->field[IS_TABLESPACES_TABLESPACE_COMMENT]->val_str(&data);
-        comments->copy(data);
-        DBUG_PRINT("find_tablespace_schema_row", (" Found tablespace %s",
-                   found_ts_name.ptr()));
-        break;
-      }
-      found_ts_name.length(0);
-      found_ts_engine.length(0);
-    }
-    break;
-  case SCH_FILES:
-    while (!ha->rnd_next(is_table->record[0]))
-    {
-      is_table->field[IS_FILES_TABLESPACE_NAME]->val_str(&found_ts_name);
-      is_table->field[IS_FILES_ENGINE]->val_str(&found_ts_engine);
-      if (found_ts_name.length() && found_ts_engine.length() &&
-          !my_strnncoll(system_charset_info, (const uchar*) found_ts_name.ptr(),
-                        found_ts_name.length(), (const uchar*) ts_name->ptr(),
-                        ts_name->length()) &&
-          !my_strnncoll(system_charset_info,
-                        (const uchar*) found_ts_engine.ptr(),
-                        found_ts_engine.length(),
-                        (const uchar*) ts_engine->ptr(), ts_engine->length()))
-      {
-        retval= FALSE;
-        is_table->field[IS_FILES_FILE_NAME]->val_str(&data);
-        datafile->copy(data);
-        DBUG_PRINT("find_tablespace_schema_row", (" Found tablespace %s",
-                   found_ts_name.ptr()));
-        break;
-      }
-      found_ts_name.length(0);
-      found_ts_engine.length(0);
-    }
-    break;
-  default:
-    DBUG_ASSERT(0);
-    break;
-  }
+///////////////////////////////////////////////////////////////////////////
 
-  /*
-    Cleanup
-  */
-  ha->ha_rnd_end();
+const String *grant_get_host_name(const Obj *obj)
+{
+  return ((Grant_obj *) obj)->get_host_name();
+}
+
+///////////////////////////////////////////////////////////////////////////
 
-  dbug_tmp_restore_column_map(is_table->read_set, orig_col);
-  free_tmp_table(thd, is_table);
-  DBUG_RETURN(retval);
+const String *grant_get_grant_info(const Obj *obj)
+{
+  return ((Grant_obj *) obj)->get_grant_info();
 }
 
-/**
-  Build a valid tablespace from the information_schema views.
+///////////////////////////////////////////////////////////////////////////
 
-  This method builds a @c TablespaceObj object if the tablespace
-  exists on the server.
+Obj *find_tablespace(THD *thd, const String *ts_name)
+{
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
 
-  @param[in]     thd           Thread context.
-  @param[out]    TablespaceObj A pointer to a new tablespace object
-  @param[in]     ts_name       The name of the tablespace to find
-  @param[in]     ts_engine     Engine of the tablespace to find
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SELECT t1.tablespace_comment, t2.file_name, t1.engine "
+    "FROM INFORMATION_SCHEMA.TABLESPACES AS t1, "
+         "INFORMATION_SCHEMA.FILES AS t2 "
+    "WHERE t1.tablespace_name = t2.tablespace_name AND "
+         "t1.tablespace_name = '%.*s'",
+    (int) ts_name->length(),
+    (const char *) ts_name->ptr());
 
-  @note Caller is responsible for destroying the tablespace object.
+  Ed_result result(thd->mem_root);
 
-  @retval FALSE if tablespace exists and no errors
-  @retval TRUE if tablespace does not exist or errors
-*/
-static bool get_tablespace_from_schema(THD *thd,
-                                       TablespaceObj **ts,
-                                       const String *ts_name,
-                                       const String *ts_engine)
-{
-  String datafile;
-  String comments;
-  DBUG_ENTER("obs::get_tablespace_from_schema()");
+  if (run_query(thd, &query, &result) ||
+      result.get_warnings()->elements > 0)
+  {
+    /* Should be no warnings. */
+    log_warnings(&result);
+    return NULL;
+  }
 
-  /*
-    Locate the row in TABLESPACES and get the comments.
-  */
-  if (find_tablespace_schema_row(thd, SCH_TABLESPACES,
-      ts_name, ts_engine, &datafile, &comments))
-    DBUG_RETURN(TRUE);
+  if (!result.elements)
+    return NULL;
 
-  /*
-    Locate the row in FILES and get the datafile.
-  */
-  if (find_tablespace_schema_row(thd, SCH_FILES,
-      ts_name, ts_engine, &datafile, &comments))
-    DBUG_RETURN(TRUE);
+  Ed_result_set *rs= result.get_cur_result_set();
 
-  /*
-    The datafile parameter is required.
-  */
-  if (datafile.length() == 0)
-    DBUG_RETURN(TRUE);
+  DBUG_ASSERT(rs->data()->elements == 1);
 
-  DBUG_PRINT("get_tablespace_from_schema", (" Found tablespace %s %s",
-    ts_name->ptr(), datafile.ptr()));
+  Ed_row *row= rs->get_cur_row();
 
-  TablespaceObj *ts_local= new TablespaceObj(ts_name);
-  *ts= ts_local;
-  ts_local->set_datafile(&datafile);
-  ts_local->set_comments(&comments);
-  ts_local->set_engine(ts_engine);
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 3);
 
-  DBUG_RETURN(FALSE);
+  const Ed_column *comment= row->get_column(0);
+  const Ed_column *data_file_name= row->get_column(1);
+  const Ed_column *engine= row->get_column(2);
+
+  return new Tablespace_obj(ts_name->ptr(), ts_name->length(),
+                            comment->str, comment->length,
+                            data_file_name->str, data_file_name->length,
+                            engine->str, engine->length);
 }
 
+///////////////////////////////////////////////////////////////////////////
+
 /**
   Retrieve the tablespace for a table if it exists
 
-  This method returns a @c TablespaceObj object if the table has a tablespace.
+  This method returns a @c Tablespace_obj object if the table has a tablespace.
 
-  @param[in]  thd       Thread context.
-  @param[in]  db_name   The database name for the table.
-  @param[in]  tbl_name  The table name.
+  @param[in]  thd         Thread context.
+  @param[in]  db_name     The database name for the table.
+  @param[in]  table_name  The table name.
 
   @note Caller is responsible for destroying the object.
 
   @retval Tablespace object if table uses a tablespace
   @retval NULL if table does not use a tablespace
 */
-Obj *get_tablespace_for_table(THD *thd,
-                              const String *db_name,
-                              const String *tbl_name)
-{
-  TablespaceObj *ts= NULL;
-  char path[FN_REFLEN];
-  String ts_name, ts_engine;
-  const char *ts_name_str= NULL;
-  DBUG_ENTER("obs::get_tablespace_for_table()");
-  DBUG_PRINT("obs::get_tablespace_for_table", ("name: %s.%s",
-             db_name->ptr(), tbl_name->ptr()));
-
-  const char *db= db_name->ptr();
-  const char *name= tbl_name->ptr();
-
-  build_table_filename(path, sizeof(path), db, name, "", 0);
-  ts_name.length(0);
-  ts_engine.length(0);
-
-  TABLE *table= open_temporary_table(thd, path, db, name,
-                    FALSE /* don't link to thd->temporary_tables */,
-                    OTM_OPEN);
 
-  if (table)
+Obj *find_tablespace_for_table(THD *thd,
+                               const String *db_name,
+                               const String *table_name)
+{
+  char query_buffer[QUERY_BUFFER_SIZE];
+  LEX_STRING query;
+
+  query.str= query_buffer;
+  query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+    "SELECT t1.tablespace_name, t1.engine, t1.tablespace_comment, t2.file_name "
+    "FROM INFORMATION_SCHEMA.TABLESPACES AS t1, "
+         "INFORMATION_SCHEMA.FILES AS t2, "
+         "INFORMATION_SCHEMA.TABLES AS t3 "
+    "WHERE t1.tablespace_name = t2.tablespace_name AND "
+         "t2.tablespace_name = t3.tablespace_name AND "
+         "t3.table_schema = '%.*s' AND "
+         "t3.table_name = '%.*s'",
+    (int) db_name->length(),
+    (const char *) db_name->ptr(),
+    (int) table_name->length(),
+    (const char *) table_name->ptr());
+
+  Ed_result result(thd->mem_root);
+
+  if (run_query(thd, &query, &result) ||
+      result.get_warnings()->elements > 0)
   {
-    if ((ts_name_str= table->file->get_tablespace_name()))
-    {
-      ts_name.append(ts_name_str);
-      ts_name.set_charset(system_charset_info);
-      ts_engine.append(table->file->engine_name()->str);
-      ts_engine.set_charset(system_charset_info);
-    }
-    intern_close_table(table);
-    my_free(table, MYF(0));
+    /* Should be no warnings. */
+    log_warnings(&result);
+    return NULL;
   }
-  else
-    goto end;
 
-  /*
-    Now open the information_schema table and get the tablespace information.
-  */
-  if (ts_name_str)
-    get_tablespace_from_schema(thd, &ts, &ts_name, &ts_engine);
-end:
-  DBUG_RETURN(ts);
-}
+  if (!result.elements)
+    return NULL;
 
-/**
-  Determine if tablespace exists.
+  Ed_result_set *rs= result.get_cur_result_set();
 
-  This method determines if a materialized tablespace exists on the
-  system. This compares the name and all saved attributes of the
-  tablespace. A FALSE return would mean either the tablespace does
-  not exist or the tablespace attributes are different.
+  if (!rs->data()->elements)
+    return NULL;
 
-  @param[in]  Obj  The TablspaceObj pointer to compare.
+  DBUG_ASSERT(rs->data()->elements == 1);
 
-  @retval TRUE if it exists
-  @retval FALSE if it does not exist
-*/
-bool tablespace_exists(THD *thd,
-                       Obj *ts)
-{
-  TablespaceObj *other_ts= NULL, *this_ts= static_cast<TablespaceObj*>(ts);
-  bool retval= FALSE;
-  DBUG_ENTER("obs::tablespace_exists()");
-  get_tablespace_from_schema(thd, &other_ts, this_ts->get_name(),
-                             this_ts->get_engine());
-  if (!other_ts)
-    DBUG_RETURN(retval);
-  retval= (my_strcasecmp(system_charset_info,
-           other_ts->build_serialization()->ptr(),
-           ((TablespaceObj *)ts)->build_serialization()->ptr()) == 0);
-  delete other_ts;
-  DBUG_RETURN(retval);
-}
+  Ed_row *row= rs->get_cur_row();
 
-/**
-  Is there a tablespace with the given name?
+  DBUG_ASSERT(row->get_metadata()->get_num_columns() == 4);
 
-  This method determines if the tablespace referenced by name exists on the
-  system. Returns a TablespaceObj if it exists or NULL if it doesn't.
+  const Ed_column *ts_name= row->get_column(0);
+  const Ed_column *engine= row->get_column(1);
+  const Ed_column *comment= row->get_column(2);
+  const Ed_column *data_file_name= row->get_column(3);
 
-  @param[in]  Obj  The TablspaceObj pointer to compare.
+  return new Tablespace_obj(ts_name->str, ts_name->length,
+                            comment->str, comment->length,
+                            data_file_name->str, data_file_name->length,
+                            engine->str, engine->length);
+}
 
-  @note Caller is responsible for destroying the tablespace object.
+///////////////////////////////////////////////////////////////////////////
 
-  @returns the tablespace if found or NULL if not found
-*/
-Obj *is_tablespace(THD *thd, Obj *ts)
+bool compare_tablespace_attributes(Obj *ts1, Obj *ts2)
 {
-  TablespaceObj *other_ts= NULL, *this_ts= static_cast<TablespaceObj*>(ts);
-  DBUG_ENTER("obs::is_tablespace()");
-  get_tablespace_from_schema(thd, &other_ts, this_ts->get_name(),
-                             this_ts->get_engine());
-  DBUG_RETURN(other_ts);
+  DBUG_ENTER("obs::compare_tablespace_attributes()");
+
+  Tablespace_obj *o1= (Tablespace_obj *) ts1;
+  Tablespace_obj *o2= (Tablespace_obj *) ts2;
+
+  DBUG_RETURN(my_strcasecmp(system_charset_info,
+                            o1->get_description()->ptr(),
+                            o2->get_description()->ptr()) == 0);
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -3861,6 +3346,6 @@ int Name_locker::release_name_locks()
   DBUG_RETURN(0);
 }
 
-} // obs namespace
-
 ///////////////////////////////////////////////////////////////////////////
+
+} // obs namespace

=== modified file 'sql/si_objects.h'
--- a/sql/si_objects.h	2008-10-27 13:06:21 +0000
+++ b/sql/si_objects.h	2008-11-13 19:34:18 +0000
@@ -15,38 +15,49 @@
 
 namespace obs {
 
+///////////////////////////////////////////////////////////////////////////
+
 /**
   Obj defines the basic set of operations for each database object.
 */
-
 class Obj
 {
 public:
-
-  bool serialize(THD *thd, String *serialization);
-
   /**
     Return the name of the object.
 
     @return object name.
   */
-  virtual const String *get_name() = 0;
+  virtual const String *get_name() const = 0;
 
   /**
     Return the database name of the object.
 
     @note this is a subject to remove.
   */
-  virtual const String *get_db_name() = 0;
+  virtual const String *get_db_name() const = 0;
+
+public:
+  /**
+    Serialize an object to a string. The serialization string is opaque
+    object for the client.
+
+    @return Error status.
+  */
+  virtual bool serialize(THD *thd, String *serialization) = 0;
+
+  /**
+    Materialize an object in the database.
 
-  bool execute(THD *thd);
+    @return Error status.
+  */
+  virtual bool execute(THD *thd) = 0;
 
 public:
   virtual ~Obj()
   { }
 
-private:
-
+protected:
   /**
     Read the object state from a given buffer and restores object state to
     the point, where it can be executed.
@@ -61,23 +72,6 @@ private:
   virtual bool materialize(uint serialization_version,
                            const String *serialization) = 0;
 
-  /// Primitive implementing @c serialize() method.
-  virtual bool do_serialize(THD *thd, String *serialization) = 0;
-
-  /// Primitive implementing @c execute() method.
-  virtual bool do_execute(THD *thd) = 0;
-
-  /**
-    Drop the object.
-
-    @param[in] thd              Server thread context.
-
-    @return error status.
-      @retval FALSE on success.
-      @retval TRUE on error.
-  */
-  virtual bool drop(THD *thd) = 0;
-
 private:
   friend Obj *materialize_database(const String *,
                                    uint,
@@ -124,91 +118,14 @@ private:
 
 };
 
-
-/**
-  Create the object in the database.
-
-  @param[in] thd              Server thread context.
-
-  @return error status.
-    @retval FALSE on success.
-    @retval TRUE on error.
-
-  @note The real work is done inside @c do_execute() primitive which should be
-  defied in derived classes. This method prepares appropriate context and calls
-  the primitive.
-*/
-inline
-bool Obj::execute(THD *thd)
-{
-  ulong saved_sql_mode= thd->variables.sql_mode;
-  thd->variables.sql_mode= 0;
-
-  set_var_collation_client saved_charset_settings(
-                             thd->variables.character_set_client,
-                             thd->variables.character_set_results,
-                             thd->variables.collation_connection);
-
-  set_var_collation_client new_charset_settings(::system_charset_info,
-                                                ::system_charset_info,
-                                                ::system_charset_info);
-  new_charset_settings.update(thd);
-
-  bool ret= do_execute(thd);
-
-  saved_charset_settings.update(thd);
-  thd->variables.sql_mode= saved_sql_mode;
-
-  return ret;
-}
-
-/**
-  Serialize object state into a buffer. The buffer actually should be a
-  binary buffer. String class is used here just because we don't have
-  convenient primitive for binary buffers.
-
-  Serialization format is opaque to the client, i.e. the client should
-  not make any assumptions about the format or the content of the
-  returned buffer.
-
-  Serialization format can be changed in the future versions. However,
-  the server must be able to materialize objects coded in any previous
-  formats.
-
-  @param[in] thd           Server thread context.
-  @param[in] serialization Buffer to serialize the object
-
-  @return error status.
-    @retval FALSE on success.
-    @retval TRUE on error.
-
-  @note The real work is done inside @c do_serialize() primitive which should be
-  defied in derived classes. This method prepares appropriate context and calls
-  the primitive.
-*/
-inline
-bool Obj::serialize(THD *thd, String *serialization)
-{
-  ulong saved_sql_mode= thd->variables.sql_mode;
-  thd->variables.sql_mode= 0;
-
-  bool ret= do_serialize(thd, serialization);
-
-  thd->variables.sql_mode= saved_sql_mode;
-
-  return ret;
-}
-
 ///////////////////////////////////////////////////////////////////////////
 
 /**
   Obj_iterator is a basic interface to enumerate the objects.
 */
-
 class Obj_iterator
 {
 public:
-
   Obj_iterator()
   { }
 
@@ -226,40 +143,6 @@ public:
 public:
   virtual ~Obj_iterator()
   { }
-
-};
-
-/**
-  GrantObjIternator is an encapsulation of the three iterators for each level
-  of grant supported: database-, table- and routine-, and column-level.
-*/
-class GrantObjIterator : public Obj_iterator
-{
-public:
-  GrantObjIterator(THD *thd, const String *db_name);
-
-  ~GrantObjIterator()
-  {
-    delete db_grants;
-    delete tbl_grants;
-    delete col_grants;
-  }
-
-  /**
-    This operation returns a pointer to the next object in an enumeration.
-    It returns NULL if there is no more objects.
-
-    The client is responsible to destroy the returned object.
-
-    @return a pointer to the object
-      @retval NULL if there is no more objects in an enumeration.
-  */
-  Obj *next();
-
-private:
-  Obj_iterator *db_grants;  ///< database-level grants
-  Obj_iterator *tbl_grants; ///< table- and routine-level grants
-  Obj_iterator *col_grants; ///< column-level grants
 };
 
 ///////////////////////////////////////////////////////////////////////////
@@ -283,7 +166,6 @@ private:
 
   @return a pointer to an instance of Obj representing given database.
 */
-
 Obj *get_database(const String *db_name);
 
 /**
@@ -299,7 +181,6 @@ Obj *get_database(const String *db_name)
 
   @return a pointer to an instance of Obj representing given table.
 */
-
 Obj *get_table(const String *db_name, const String *table_name);
 
 /**
@@ -315,7 +196,6 @@ Obj *get_table(const String *db_name, co
 
   @return a pointer to an instance of Obj representing given view.
 */
-
 Obj *get_view(const String *db_name, const String *view_name);
 
 /**
@@ -331,7 +211,6 @@ Obj *get_view(const String *db_name, con
 
   @return a pointer to an instance of Obj representing given trigger.
 */
-
 Obj *get_trigger(const String *db_name, const String *trigger_name);
 
 /**
@@ -349,7 +228,6 @@ Obj *get_trigger(const String *db_name, 
   @return a pointer to an instance of Obj representing given stored
   procedure.
 */
-
 Obj *get_stored_procedure(const String *db_name, const String *sp_name);
 
 /**
@@ -367,7 +245,6 @@ Obj *get_stored_procedure(const String *
   @return a pointer to an instance of Obj representing given stored
   function.
 */
-
 Obj *get_stored_function(const String *db_name, const String *sf_name);
 
 /**
@@ -383,7 +260,6 @@ Obj *get_stored_function(const String *d
 
   @return a pointer to an instance of Obj representing given event.
 */
-
 Obj *get_event(const String *db_name, const String *event_name);
 
 ///////////////////////////////////////////////////////////////////////////
@@ -393,6 +269,8 @@ Obj *get_event(const String *db_name, co
 //
 // The client is responsible for destroying the returned iterator.
 
+///////////////////////////////////////////////////////////////////////////
+
 /**
   Create an iterator over all databases in the server.
 
@@ -400,7 +278,6 @@ Obj *get_event(const String *db_name, co
 
   @return a pointer to an iterator object.
 */
-
 Obj_iterator *get_databases(THD *thd);
 
 /**
@@ -411,7 +288,6 @@ Obj_iterator *get_databases(THD *thd);
   @return a pointer to an iterator object.
     @retval NULL in case of error.
 */
-
 Obj_iterator *get_db_tables(THD *thd, const String *db_name);
 
 /**
@@ -422,7 +298,6 @@ Obj_iterator *get_db_tables(THD *thd, co
   @return a pointer to an iterator object.
     @retval NULL in case of error.
 */
-
 Obj_iterator *get_db_views(THD *thd, const String *db_name);
 
 /**
@@ -433,7 +308,6 @@ Obj_iterator *get_db_views(THD *thd, con
   @return a pointer to an iterator object.
     @retval NULL in case of error.
 */
-
 Obj_iterator *get_db_triggers(THD *thd, const String *db_name);
 
 /**
@@ -444,7 +318,6 @@ Obj_iterator *get_db_triggers(THD *thd, 
   @return a pointer to an iterator object.
     @retval NULL in case of error.
 */
-
 Obj_iterator *get_db_stored_procedures(THD *thd, const String *db_name);
 
 /**
@@ -455,7 +328,6 @@ Obj_iterator *get_db_stored_procedures(T
   @return a pointer to an iterator object.
     @retval NULL in case of error.
 */
-
 Obj_iterator *get_db_stored_functions(THD *thd, const String *db_name);
 
 /**
@@ -466,7 +338,6 @@ Obj_iterator *get_db_stored_functions(TH
   @return a pointer to an iterator object.
     @retval NULL in case of error.
 */
-
 Obj_iterator *get_db_events(THD *thd, const String *db_name);
 
 /*
@@ -483,6 +354,8 @@ Obj_iterator *get_all_db_grants(THD *thd
 //
 // The client is responsible for destroying the returned iterator.
 
+///////////////////////////////////////////////////////////////////////////
+
 /**
   Create an iterator overl all base tables in the particular view.
 
@@ -491,7 +364,6 @@ Obj_iterator *get_all_db_grants(THD *thd
   @return a pointer to an iterator object.
     @retval NULL in case of error.
 */
-
 Obj_iterator* get_view_base_tables(THD *thd,
                                    const String *db_name,
                                    const String *view_name);
@@ -504,7 +376,6 @@ Obj_iterator* get_view_base_tables(THD *
   @return a pointer to an iterator object.
     @retval NULL in case of error.
 */
-
 Obj_iterator* get_view_base_views(THD *thd,
                                   const String *db_name,
                                   const String *view_name);
@@ -516,6 +387,8 @@ Obj_iterator* get_view_base_views(THD *t
 //
 // The client is responsible for destroying the returned iterator.
 
+///////////////////////////////////////////////////////////////////////////
+
 Obj *materialize_database(const String *db_name,
                           uint serialization_version,
                           const String *serialization);
@@ -554,8 +427,8 @@ Obj *materialize_tablespace(const String
                             uint serialization_version,
                             const String *serialization);
 
-Obj *materialize_db_grant(const String *grantee,
-                          const String *db_name,
+Obj *materialize_db_grant(const String *db_name,
+                          const String *name,
                           uint serialization_version,
                           const String *serialization);
 
@@ -565,14 +438,11 @@ Obj *materialize_db_grant(const String *
   Check if the given database name is reserved for internal use.
 
   @return
-    @retval TRUE if the given database name is reserved for internal use
+    @retval TRUE if the given database name is reserved for internal use.
     @retval FALSE otherwise.
 */
-
 bool is_internal_db_name(const String *db_name);
 
-///////////////////////////////////////////////////////////////////////////
-
 /**
   Check if the given directory actually exists.
 
@@ -580,42 +450,54 @@ bool is_internal_db_name(const String *d
     @retval FALSE on success (the database exists and accessible).
     @retval TRUE on error (the database either not exists, or not accessible).
 */
+bool check_db_existence(THD *thd, const String *db_name);
 
-bool check_db_existence(const String *db_name);
+/**
+  Check if the user is defined on the system.
 
-/*
-  Check if the given user is actually defined on the system.
+  @return
+    @retval TRUE if user is defined
+    @retval FALSE otherwise
+*/
+bool check_user_existence(THD *thd, const Obj *obj);
 
-  @return Existence status.
-    @retval TRUE if user is defined on the system.
-    @retval FALSE if user does not exist.
+/**
+  Return user name of materialized grant object.
 */
+const String *grant_get_user_name(const Obj *obj);
 
-bool check_user_existence(THD *thd, const String *grantee);
+/**
+  Return host name of materialized grant object.
+*/
+const String *grant_get_host_name(const Obj *obj);
 
-/*
-  This method returns a @c TablespaceObj object if the table has a tablespace.
+/**
+  Return grant info of materialized grant object.
 */
+const String *grant_get_grant_info(const Obj *obj);
 
-Obj *get_tablespace_for_table(THD *thd,
-                              const String *db_name,
-                              const String *tbl_name);
+/**
+  Determine if the tablespace referenced by name exists on the system.
 
-/*
-  This method determines if a materialized tablespace exists on the
-  system. This compares the name and all saved attributes of the
-  tablespace. A FALSE return would mean either the tablespace does
-  not exist or the tablespace attributes are different.
+  @return a Tablespace_obj if it exists or NULL if it doesn't.
 */
+Obj *find_tablespace(THD *thd, const String *ts_name);
 
-bool tablespace_exists(THD *thd, Obj *ts);
-
-/*
-  This method determines if the tablespace referenced by name exists on the
-  system. Returns a TablespaceObj if it exists or NULL if it doesn't.
+/**
+  This method returns a @c Tablespace_obj object if the table has a
+  tablespace.
 */
+Obj *find_tablespace_for_table(THD *thd,
+                               const String *db_name,
+                               const String *table_name);
 
-Obj *is_tablespace(THD *thd, Obj *ts);
+/**
+  This method determines if a materialized tablespace exists on the system.
+  This compares the name and all saved attributes of the tablespace. A
+  FALSE return would mean either the tablespace does not exist or the
+  tablespace attributes are different.
+*/
+bool compare_tablespace_attributes(Obj *ts1, Obj *ts2);
 
 ///////////////////////////////////////////////////////////////////////////
 
@@ -623,6 +505,8 @@ Obj *is_tablespace(THD *thd, Obj *ts);
 // DDL blocker methods.
 //
 
+///////////////////////////////////////////////////////////////////////////
+
 /**
   Turn on the ddl blocker.
 
@@ -664,14 +548,6 @@ void ddl_blocker_exception_on(THD *thd);
 void ddl_blocker_exception_off(THD *thd);
 
 /*
-  Creates a WHERE clause for information schema table lookups of the
-  for FROM INFORMATION_SCHEMA.X WHERE <db_col> IN ('a','b','c').
-*/
-COND *create_db_select_condition(THD *thd,
-                                 TABLE *t,
-                                 List<LEX_STRING> *db_list);
-
-/*
   The following class is used to manage name locks on a list of tables.
 
   This class uses a list of type List<Obj> to establish the table list

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2008-11-07 14:04:18 +0000
+++ b/sql/sql_class.cc	2008-11-13 19:34:18 +0000
@@ -400,7 +400,6 @@ Diagnostics_area::reset_diagnostics_area
 {
   DBUG_ENTER("reset_diagnostics_area");
 #ifdef DBUG_OFF
-  can_overwrite_status= FALSE;
   /** Don't take chances in production */
   m_message[0]= '\0';
   m_sql_errno= 0;
@@ -409,6 +408,7 @@ Diagnostics_area::reset_diagnostics_area
   m_last_insert_id= 0;
   m_total_warn_count= 0;
 #endif
+  can_overwrite_status= FALSE;
   is_sent= FALSE;
   /** Tiny reset in debug mode to see garbage right away */
   m_status= DA_EMPTY;
@@ -504,6 +504,9 @@ Diagnostics_area::set_error_status(THD *
   m_sql_errno= sql_errno_arg;
   strmake(m_message, message_arg, sizeof(m_message)-1);
 
+  if (is_set() && is_sent)
+    is_sent= FALSE;
+
   m_status= DA_ERROR;
   DBUG_VOID_RETURN;
 }

=== modified file 'sql/sql_error.cc'
--- a/sql/sql_error.cc	2008-10-08 15:37:32 +0000
+++ b/sql/sql_error.cc	2008-11-13 19:34:18 +0000
@@ -51,9 +51,9 @@ This file contains the implementation of
   got after the query has been executed.
 */
 
-void MYSQL_ERROR::set_msg(THD *thd, const char *msg_arg)
+void MYSQL_ERROR::set_msg(MEM_ROOT *mem_root, const char *msg_arg)
 {
-  msg= strdup_root(&thd->warn_root, msg_arg);
+  msg= strdup_root(mem_root, msg_arg);
 }
 
 
@@ -151,7 +151,8 @@ void push_warning(THD *thd, MYSQL_ERROR:
   if (thd->warn_list.elements < thd->variables.max_error_count)
   {
     /* We have to use warn_root, as mem_root is freed after each query */
-    if ((err= new (&thd->warn_root) MYSQL_ERROR(thd, code, level, msg)))
+    if ((err= new (&thd->warn_root) MYSQL_ERROR(&thd->warn_root, code, level,
+                                                msg)))
       thd->warn_list.push_back(err, &thd->warn_root);
   }
   thd->warn_count[(uint) level]++;

=== modified file 'sql/sql_error.h'
--- a/sql/sql_error.h	2008-07-29 22:03:57 +0000
+++ b/sql/sql_error.h	2008-11-13 19:34:18 +0000
@@ -23,16 +23,23 @@ public:
   enum_warning_level level;
   char *msg;
   
-  MYSQL_ERROR(THD *thd, uint code_arg, enum_warning_level level_arg,
+  MYSQL_ERROR(MEM_ROOT *mem_root, uint code_arg, enum_warning_level level_arg,
 	      const char *msg_arg)
     :code(code_arg), level(level_arg)
   {
     if (msg_arg)
-      set_msg(thd, msg_arg);
+      set_msg(mem_root, msg_arg);
+  }
+
+  MYSQL_ERROR(MEM_ROOT *mem_root, const MYSQL_ERROR *err)
+    :code(err->code), level(err->level)
+  {
+    if (err->msg)
+      set_msg(mem_root, err->msg);
   }
 
 private:
-  void set_msg(THD *thd, const char *msg_arg);
+  void set_msg(MEM_ROOT *mem_root, const char *msg_arg);
 };
 
 void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,

=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc	2008-10-16 02:13:16 +0000
+++ b/sql/sql_lex.cc	2008-11-13 19:34:18 +0000
@@ -144,6 +144,7 @@ Lex_input_stream::Lex_input_stream(THD *
   found_semicolon(NULL),
   ignore_space(test(thd->variables.sql_mode & MODE_IGNORE_SPACE)),
   stmt_prepare_mode(FALSE),
+  multi_statements(TRUE),
   in_comment(NO_COMMENT),
   m_underscore_cs(NULL)
 {

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2008-11-04 11:30:00 +0000
+++ b/sql/sql_lex.h	2008-11-13 19:34:18 +0000
@@ -1481,6 +1481,11 @@ public:
   */
   bool stmt_prepare_mode;
 
+  /**
+    TRUE if we should allow multi-statements.
+  */
+  bool multi_statements;
+
   /** State of the lexical analyser for comments. */
   enum_comment_state in_comment;
 

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2008-11-06 18:39:27 +0000
+++ b/sql/sql_parse.cc	2008-11-13 19:34:18 +0000
@@ -1471,8 +1471,7 @@ void log_slow_statement(THD *thd)
          thd->variables.long_query_time ||
          ((thd->server_status &
            (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
-          opt_log_queries_not_using_indexes &&
-           !(sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND))) &&
+          opt_log_queries_not_using_indexes)) &&
         thd->examined_row_count >= thd->variables.min_examined_row_limit)
     {
       thd_proc_info(thd, "logging slow query");
@@ -2012,9 +2011,6 @@ mysql_execute_command(THD *thd)
     if (!(res= check_table_access(thd, SELECT_ACL, all_tables, FALSE, FALSE,
                                   UINT_MAX)))
       res= execute_sqlcom_select(thd, all_tables);
-    /* Don't log SHOW STATUS commands to slow query log */
-    thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
-                           SERVER_QUERY_NO_GOOD_INDEX_USED);
     /*
       restore status variables, as we don't want 'show status' to cause
       changes
@@ -4578,6 +4574,13 @@ finish:
     start_waiting_global_read_lock(thd);
   }
 
+  if (sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND)
+  {
+    /* Don't log SHOW STATUS commands to slow query log */
+    thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
+                           SERVER_QUERY_NO_GOOD_INDEX_USED);
+  }
+
   /* If commit fails, we should be able to reset the OK status. */
   thd->main_da.can_overwrite_status= TRUE;
   opt_implicit_commit(thd, CF_IMPLICIT_COMMIT_END);

=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc	2008-11-06 18:39:27 +0000
+++ b/sql/sql_prepare.cc	2008-11-13 19:34:18 +0000
@@ -127,12 +127,12 @@ class Prepared_statement: public Stateme
 public:
   enum flag_values
   {
-    IS_IN_USE= 1
+    IS_IN_USE= 1,
+    IS_SQL_PREPARE= 2,
   };
 
   THD *thd;
   Select_fetch_protocol_binary result;
-  Protocol *protocol;
   Item_param **param_array;
   uint param_count;
   uint last_errno;
@@ -148,7 +148,7 @@ public:
                                List<LEX_STRING>& varnames,
                                String *expanded_query);
 public:
-  Prepared_statement(THD *thd_arg, Protocol *protocol_arg);
+  Prepared_statement(THD *thd_arg);
   virtual ~Prepared_statement();
   void setup_set_params();
   virtual Query_arena::Type type() const;
@@ -156,11 +156,13 @@ public:
   bool set_name(LEX_STRING *name);
   inline void close_cursor() { delete cursor; cursor= 0; }
   inline bool is_in_use() { return flags & (uint) IS_IN_USE; }
-  inline bool is_protocol_text() const { return protocol == &thd->protocol_text; }
+  inline bool is_sql_prepare() const { return flags & (uint) IS_SQL_PREPARE; }
+  void set_sql_prepare() { flags|= (uint) IS_SQL_PREPARE; }
   bool prepare(const char *packet, uint packet_length);
   bool execute_loop(String *expanded_query,
                     bool open_cursor,
                     uchar *packet_arg, uchar *packet_end_arg);
+  bool execute_immediate(const char *stmt, uint length);
   /* Destroy this statement */
   void deallocate();
 private:
@@ -1361,7 +1363,7 @@ static int mysql_test_select(Prepared_st
   */
   if (unit->prepare(thd, 0, 0))
     goto error;
-  if (!lex->describe && !stmt->is_protocol_text())
+  if (!lex->describe && !stmt->is_sql_prepare())
   {
     /* Make copy of item list, as change_columns may change it */
     List<Item> fields(lex->select_lex.item_list);
@@ -1995,7 +1997,7 @@ static bool check_prepared_statement(Pre
     break;
   }
   if (res == 0)
-    DBUG_RETURN(stmt->is_protocol_text() ?
+    DBUG_RETURN(stmt->is_sql_prepare() ?
                 FALSE : (send_prep_stmt(stmt, 0) || thd->protocol->flush()));
 error:
   DBUG_RETURN(TRUE);
@@ -2065,6 +2067,7 @@ static bool init_param_array(Prepared_st
 
 void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length)
 {
+  Protocol *save_protocol= thd->protocol;
   Prepared_statement *stmt;
   DBUG_ENTER("mysql_stmt_prepare");
 
@@ -2073,7 +2076,7 @@ void mysql_stmt_prepare(THD *thd, const 
   /* First of all clear possible warnings from the previous command */
   mysql_reset_thd_for_next_command(thd);
 
-  if (! (stmt= new Prepared_statement(thd, &thd->protocol_binary)))
+  if (! (stmt= new Prepared_statement(thd)))
     DBUG_VOID_RETURN; /* out of memory: error is set in Sql_alloc */
 
   if (thd->stmt_map.insert(thd, stmt))
@@ -2088,11 +2091,16 @@ void mysql_stmt_prepare(THD *thd, const 
   sp_cache_flush_obsolete(&thd->sp_proc_cache);
   sp_cache_flush_obsolete(&thd->sp_func_cache);
 
+  thd->protocol= &thd->protocol_binary;
+
   if (stmt->prepare(packet, packet_length))
   {
     /* Statement map deletes statement on erase */
     thd->stmt_map.erase(stmt);
   }
+
+  thd->protocol= save_protocol;
+
   /* check_prepared_statemnt sends the metadata packet in case of success */
   DBUG_VOID_RETURN;
 }
@@ -2226,7 +2234,7 @@ void mysql_sql_stmt_prepare(THD *thd)
   uint query_len;
   DBUG_ENTER("mysql_sql_stmt_prepare");
   LINT_INIT(query_len);
-  DBUG_ASSERT(thd->protocol == &thd->protocol_text);
+  // XXX: DBUG_ASSERT(thd->protocol == &thd->protocol_text);
 
   if ((stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name)))
   {
@@ -2244,11 +2252,13 @@ void mysql_sql_stmt_prepare(THD *thd)
   }
 
   if (! (query= get_dynamic_sql_string(lex, &query_len)) ||
-      ! (stmt= new Prepared_statement(thd, &thd->protocol_text)))
+      ! (stmt= new Prepared_statement(thd)))
   {
     DBUG_VOID_RETURN;                           /* out of memory */
   }
 
+  stmt->set_sql_prepare();
+
   /* Set the name first, insert should know that this statement has a name */
   if (stmt->set_name(name))
   {
@@ -2428,6 +2438,7 @@ void mysql_stmt_execute(THD *thd, char *
   String expanded_query;
   uchar *packet_end= packet + packet_length;
   Prepared_statement *stmt;
+  Protocol *save_protocol= thd->protocol;
   bool open_cursor;
   DBUG_ENTER("mysql_stmt_execute");
 
@@ -2455,7 +2466,9 @@ void mysql_stmt_execute(THD *thd, char *
 
   open_cursor= test(flags & (ulong) CURSOR_TYPE_READ_ONLY);
 
+  thd->protocol= &thd->protocol_binary;
   stmt->execute_loop(&expanded_query, open_cursor, packet, packet_end);
+  thd->protocol= save_protocol;
 
   DBUG_VOID_RETURN;
 }
@@ -2508,7 +2521,6 @@ void mysql_sql_stmt_execute(THD *thd)
   DBUG_VOID_RETURN;
 }
 
-
 /**
   COM_STMT_FETCH handler: fetches requested amount of rows from cursor.
 
@@ -2751,6 +2763,117 @@ void mysql_stmt_get_longdata(THD *thd, c
   DBUG_VOID_RETURN;
 }
 
+/**************************************************************************
+ Execute direct.
+**************************************************************************/
+
+bool save_warn_list(THD *thd,
+                    MEM_ROOT *mem_root,
+                    List<MYSQL_ERROR> *warn_list)
+{
+  init_sql_alloc(mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
+
+  List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+
+  while (true)
+  {
+    MYSQL_ERROR *err= it++;
+
+    if (!err)
+      break;
+
+    MYSQL_ERROR *err_copy= new (mem_root) MYSQL_ERROR(mem_root, err);
+
+    if (!err_copy || warn_list->push_back(err_copy, mem_root))
+      return TRUE;
+  }
+}
+
+void restore_warn_list(THD *thd,
+                       MEM_ROOT *mem_root,
+                       List<MYSQL_ERROR> *warn_list)
+{
+  List_iterator_fast<MYSQL_ERROR> it(*warn_list);
+
+  mysql_reset_errors(thd, TRUE);
+  while (true)
+  {
+    MYSQL_ERROR *err= it++;
+
+    if (!err)
+      break;
+
+    push_warning(thd, err->level, err->code, err->msg);
+  }
+
+  free_root(mem_root, MYF(0));
+}
+
+static bool
+mysql_execute_direct_impl(THD *thd, const LEX_STRING *query, Protocol *p)
+{
+  MEM_ROOT tmp_mem_root;
+  List<MYSQL_ERROR> warn_list_saved;
+
+  if (save_warn_list(thd, &tmp_mem_root, &warn_list_saved))
+    return TRUE;
+
+  mysql_reset_thd_for_next_command(thd);
+  mysql_reset_errors(thd, TRUE);
+
+  Prepared_statement *stmt= new Prepared_statement(thd);
+
+  if (!stmt)
+    return TRUE;
+
+  sp_cache_flush_obsolete(&thd->sp_proc_cache);
+  sp_cache_flush_obsolete(&thd->sp_func_cache);
+
+#if defined(ENABLED_PROFILING)
+  thd->profiling.set_query_source(query->str, query->length);
+#endif
+
+  Protocol *protocol_saved= thd->protocol;
+  thd->protocol= p;
+
+  bool rc= stmt->execute_immediate(query->str, query->length);
+  rc= thd->protocol->on_end_statement() || rc;
+
+  thd->protocol= protocol_saved;
+
+  delete stmt;
+
+  restore_warn_list(thd, &tmp_mem_root, &warn_list_saved);
+
+  return rc;
+}
+
+/**
+  Execute one SQL statement.
+
+  @param thd    Thread handle.
+  @param query  Query to execute.
+*/
+
+bool mysql_execute_direct(THD *thd, const LEX_STRING *query, Ed_result *result)
+{
+  bool rc;
+
+  if (result)
+  {
+    Protocol_local p(thd, result);
+    rc= mysql_execute_direct_impl(thd, query, &p);
+  }
+  else
+  {
+    Protocol_void p(thd);
+    rc= mysql_execute_direct_impl(thd, query, &p);
+  }
+
+  thd->main_da.reset_diagnostics_area();
+
+  return rc;
+}
 
 /***************************************************************************
  Select_fetch_protocol_binary
@@ -2801,12 +2924,11 @@ Select_fetch_protocol_binary::send_data(
  Prepared_statement
 ****************************************************************************/
 
-Prepared_statement::Prepared_statement(THD *thd_arg, Protocol *protocol_arg)
+Prepared_statement::Prepared_statement(THD *thd_arg)
   :Statement(NULL, &main_mem_root,
              INITIALIZED, ++thd_arg->statement_id_counter),
   thd(thd_arg),
   result(thd_arg),
-  protocol(protocol_arg),
   param_array(0),
   param_count(0),
   last_errno(0),
@@ -2895,7 +3017,8 @@ void Prepared_statement::cleanup_stmt()
   DBUG_ENTER("Prepared_statement::cleanup_stmt");
   DBUG_PRINT("enter",("stmt: %p", this));
 
-  DBUG_ASSERT(lex->sphead == 0);
+  delete lex->sphead;
+  lex->sphead= 0;
   /* The order is important */
   lex->unit.cleanup();
   cleanup_items(free_list);
@@ -3008,6 +3131,7 @@ bool Prepared_statement::prepare(const c
 
   Parser_state parser_state(thd, thd->query, thd->query_length);
   parser_state.m_lip.stmt_prepare_mode= TRUE;
+  parser_state.m_lip.multi_statements= FALSE;
   lex_start(thd);
 
   error= parse_sql(thd, & parser_state, NULL) ||
@@ -3246,6 +3370,73 @@ reexecute:
 }
 
 
+
+bool
+Prepared_statement::execute_immediate(const char *query, uint length)
+{
+  Statement stmt_backup;
+  bool error;
+
+  state= CONVENTIONAL_EXECUTION;
+
+  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();
+
+  if (lex->sql_command == SQLCOM_PREPARE || lex->sql_command == SQLCOM_EXECUTE)
+  {
+    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)
+  {
+    error= mysql_execute_command(thd);
+  }
+
+  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;
+}
+
+
 /**
   Reprepare this prepared statement.
 
@@ -3269,7 +3460,9 @@ Prepared_statement::reprepare()
   bool cur_db_changed;
   bool error;
 
-  Prepared_statement copy(thd, &thd->protocol_text);
+  Prepared_statement copy(thd);
+
+  copy.set_sql_prepare(); /* To suppress sending metadata to the client. */
 
   status_var_increment(thd->status_var.com_stmt_reprepare);
 
@@ -3327,7 +3520,7 @@ bool Prepared_statement::validate_metada
     return FALSE -- the metadata of the original SELECT,
     if any, has not been sent to the client.
   */
-  if (is_protocol_text() || lex->describe)
+  if (is_sql_prepare() || lex->describe)
     return FALSE;
 
   if (lex->select_lex.item_list.elements !=
@@ -3390,7 +3583,6 @@ Prepared_statement::swap_prepared_statem
   DBUG_ASSERT(thd == copy->thd);
   last_error[0]= '\0';
   last_errno= 0;
-  /* Do not swap protocols, the copy always has protocol_text */
 }
 
 
@@ -3429,6 +3621,8 @@ bool Prepared_statement::execute(String 
 
   LEX_STRING stmt_db_name= { db, db_length };
 
+  // XXX: DBUG_ASSERT(thd->protocol == &thd->protocol_binary);
+
   status_var_increment(thd->status_var.com_stmt_execute);
 
   /* Check if we got an error when sending long data */
@@ -3531,8 +3725,6 @@ bool Prepared_statement::execute(String 
   thd->stmt_arena= this;
   reinit_stmt_before_use(thd, lex);
 
-  thd->protocol= protocol;                      /* activate stmt protocol */
-
   /* Go! */
 
   if (open_cursor)
@@ -3570,8 +3762,6 @@ bool Prepared_statement::execute(String 
   if (cur_db_changed)
     mysql_change_db(thd, &saved_cur_db_name, TRUE);
 
-  thd->protocol= &thd->protocol_text;         /* use normal protocol */
-
   /* Assert that if an error, no cursor is open */
   DBUG_ASSERT(! (error && cursor));
 
@@ -3585,7 +3775,13 @@ bool Prepared_statement::execute(String 
     state= Query_arena::EXECUTED;
 
   if (this->lex->sql_command == SQLCOM_CALL)
-    protocol->send_out_parameters(&this->lex->param_list);
+  {
+    if (is_sql_prepare())
+      thd->protocol_text.send_out_parameters(&this->lex->param_list);
+    else
+      thd->protocol->send_out_parameters(&this->lex->param_list);
+  }
+
 
   /*
     Log COM_EXECUTE to the general log. Note, that in case of SQL

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2008-11-06 18:39:27 +0000
+++ b/sql/sql_yacc.yy	2008-11-13 19:34:18 +0000
@@ -1485,7 +1485,7 @@ query:
             Lex_input_stream *lip = YYLIP;
 
             if ((YYTHD->client_capabilities & CLIENT_MULTI_QUERIES) &&
-                ! lip->stmt_prepare_mode &&
+                lip->multi_statements &&
                 ! lip->eof())
             {
               /*

Thread
bzr commit into mysql-6.0-runtime branch (kostja:2745)Konstantin Osipov13 Nov