List:Commits« Previous MessageNext Message »
From:cbell Date:March 23 2007 10:40pm
Subject:bk commit into 5.1 tree (cbell:1.2490)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of cbell. When cbell does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-03-23 18:40:07-04:00, cbell@mysql_cab_desk. +4 -0
  WL#3573 - Table def backup and freeze
  
  This patch adds the metadata backup methods to meta_backup.cc. The patch also
  includes a test driver to be used until the code is integrated with the
  backup kernel.

  sql/backup/meta_backup.cc@stripped, 2007-03-23 18:39:56-04:00, cbell@mysql_cab_desk. +439 -0
    WL#3573 - Table def backup and freeze
    
    This patch adds the metadata backup methods. 
    
    get_db_metadata()    Places the db-specific CREATE PROCEDURE and CREATE FUNCTION
                         SQL statements in the backup::Buffer.data memory.
    get_table_metadata() Places the CREATE TABLE and CREATE TRIGGER SQL statements
                         in the backup::Buffer.data memory.
    execute_metadata()   Executes the SQL commands in a backup::Buffer.data memory.

  sql/backup/sql_backup.cc@stripped, 2007-03-23 18:39:56-04:00, cbell@mysql_cab_desk. +1 -0
    WL#3573 - Table def backup and freeze
    
    This patch adds the an include for the meta_backup header file. Note: This may
    not be needed depending on how the metadata backup methods are integrated with
    the backup kernel code.

  sql/sql_parse.cc@stripped, 2007-03-23 18:39:55-04:00, cbell@mysql_cab_desk. +73 -1
    WL#3573 - Table def backup and freeze
    
    This patch adds a test harness for the metadata backup methods. This is temporary
    and will be removed once review of the metadata backup methods is complete.

  sql/sql_yacc.yy@stripped, 2007-03-23 18:39:55-04:00, cbell@mysql_cab_desk. +5 -1
    WL#3573 - Table def backup and freeze
    
    This patch adds a variant of the backup command that takes a list of tables. 
    This is used in the test harness for the metadata backup methods. This is temporary
    and will be removed once review of the metadata backup methods is complete.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	cbell
# Host:	mysql_cab_desk.
# Root:	C:/source/c++/mysql-5.1_WL_3573

--- 1.632/sql/sql_parse.cc	2007-03-23 18:40:19 -04:00
+++ 1.633/sql/sql_parse.cc	2007-03-23 18:40:19 -04:00
@@ -27,6 +27,8 @@
 #include "sp_cache.h"
 #include "events.h"
 #include "event_data_objects.h"
+#include "backup_engine.h"
+#include "meta_backup.h"
 
 #ifndef EMBEDDED_LIBRARY
 #include "backup/backup_kernel.h"
@@ -85,7 +87,6 @@
   "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED"
 };
 
-
 static void unlock_locked_tables(THD *thd)
 {
   if (thd->locked_tables)
@@ -1859,6 +1860,77 @@
 
   case SQLCOM_BACKUP_TABLE:
   {
+    /*
+      Chuck's test code for metadata backup.  
+      REMINDER: Remove #include for backup_engine.h
+    */
+    if (all_tables != 0)
+    {
+      backup::Buffer db_buf;
+      backup::Buffer tbl_buf;
+      String db_name;
+
+      db_name.length(0);
+      db_name.append(thd->db);
+      db_buf.data= (byte *)my_malloc(4096, MYF(MY_WME));
+      db_buf.size= 4096;
+      tbl_buf.data= (byte *)my_malloc(4096, MYF(MY_WME));
+      tbl_buf.size= 4096;
+     
+      // get the metadata for the database
+      if (get_db_metadata(thd, db_name.c_ptr(), db_buf))
+      {
+        DBUG_PRINT("metadata_backup_test", ("Error in database metadata."));
+        goto error;
+      }
+      printf("\nCALL: get_db_metadata()\n");
+      dump_buffer(db_buf);
+
+      // get the metadata for the tables
+      if (get_table_metadata(thd, all_tables, tbl_buf))
+      {
+        DBUG_PRINT("metadata_backup_test", ("Error in table metadata."));
+        goto error;
+      }
+      printf("\nCALL: get_tbl_metadata()\n");
+      dump_buffer(tbl_buf);
+
+      // Drop the current database
+      strcpy(thd->query, "DROP DATABASE ");
+      strcat(thd->query, db_name.c_ptr());
+      thd->query_length= strlen(thd->query);
+      mysql_parse(thd, thd->query, thd->query_length);
+
+      // recreate the current database
+      strcpy(thd->query, "CREATE DATABASE ");
+      strcat(thd->query, db_name.c_ptr());
+      thd->query_length= strlen(thd->query);
+      mysql_parse(thd, thd->query, thd->query_length);
+
+      // set current database (there is probably a better way to do this!)
+      strcpy(thd->query, "USE ");
+      strcat(thd->query, db_name.c_ptr());
+      thd->query_length= strlen(thd->query);
+      mysql_parse(thd, thd->query, thd->query_length);
+
+      // replay the db SQL commands
+      if (execute_metadata(thd, db_buf))
+      {
+        DBUG_PRINT("metadata_backup_test", ("Error executing SQL statements."));
+        goto error;
+      }
+
+      // replay the table create statements
+      if (execute_metadata(thd, tbl_buf))
+      {
+        DBUG_PRINT("metadata_backup_test", ("Error executing SQL statements."));
+        goto error;
+      }
+
+      // We're done.
+      send_ok(thd);
+    }
+    else
 #ifndef EMBEDDED_LIBRARY
      backup::do_backup(thd);
 #endif

--- 1.545/sql/sql_yacc.yy	2007-03-23 18:40:19 -04:00
+++ 1.546/sql/sql_yacc.yy	2007-03-23 18:40:20 -04:00
@@ -5596,7 +5596,11 @@
 */
 
 backup:
-	BACKUP_SYM /* table_or_tables */
+	BACKUP_SYM table_list
+	{
+	   Lex->sql_command = SQLCOM_BACKUP_TABLE;
+  }
+	|	BACKUP_SYM /* table_or_tables */
 	{
 	   Lex->sql_command = SQLCOM_BACKUP_TABLE;
 /*           WARN_DEPRECATED(yythd, "5.2", "BACKUP TABLE",

--- 1.13/sql/backup/sql_backup.cc	2007-03-23 18:40:20 -04:00
+++ 1.14/sql/backup/sql_backup.cc	2007-03-23 18:40:20 -04:00
@@ -1,6 +1,7 @@
 #include "../mysql_priv.h"
 #include "archive.h"
 #include "backup_aux.h"
+#include "meta_backup.h"
 
 //#define TEST  yes
 

--- 1.1/sql/backup/meta_backup.cc	2007-03-23 18:40:20 -04:00
+++ 1.2/sql/backup/meta_backup.cc	2007-03-23 18:40:20 -04:00
@@ -2,6 +2,10 @@
 #include "tables.h"
 #include "archive.h"
 #include "backup_aux.h"
+#include "sql_show.h"
+#include "sp.h"
+#include "sql_trigger.h"
+#include "meta_backup.h"
 
 namespace backup {
 
@@ -138,6 +142,441 @@
 
 } // prototype namespace
 
+/*
+  Get the metadata for the database specified.
+
+  SYNOPSIS
+    get_db_metadata()
+    THD *thd    - The current thread instance.
+    char *db    - The name of the database.
+    Buffer &buf - A reference to a backup::Buffer struct used
+                  for storing the SQL strings.
+
+  DESCRIPTION
+    This procedure loads the buffer with the SQL statements for
+    creating the database and all of the stored procedures and
+    functions associated with it. 
+
+  NOTES
+    SQL strings are stored in the Buffer.data memory with the size
+    (int) of the string followed by the string. A list of SQL 
+    strings are terminated by a int value of 0. The format of the
+    Buffer.data memory would resemble the following for 3 SQL strings:
+
+    <int size> | <char *> SQL string    // first string 
+    <int size> | <char *> SQL string    // second string 
+    <int size> | <char *> SQL string    // third string 
+    <int size>                          // size = 0 EOB terminator 
+
+  RETURNS
+    0  - no errors.
+    -1 - database cannot be read or doesn't exist.
+*/
+int get_db_metadata(THD *thd, const char *db, Buffer &buf)
+{
+  TABLE *proc_table;
+  TABLE_LIST proc_tables;
+  String db_sql, tmp;
+  char *ptr= (char *)buf.data;
+  int blk_size= 0;
+  int size;
+  LEX_STRING db_name;
+
+  DBUG_ENTER("get_db_metadata");
+  /*
+    Check to see if database is valid name.
+  */
+  DBUG_PRINT("metadata_backup", ("checking the database"));
+  db_name.str= thd->alloc(strlen(thd->db) + 2);
+  db_name.length= strlen(thd->db);
+  if (check_db_name(&db_name))
+  {
+    DBUG_PRINT("metadata_backup", ("error with database name"));
+    DBUG_RETURN(-1);
+  }
+
+  /*
+    Setup a new table list that contains the proc table.
+  */
+  bzero((char*) &proc_tables,sizeof(proc_tables));
+  proc_tables.db= (char*) db;
+  proc_tables.db_length= strlen(db);
+  proc_tables.table_name= proc_tables.alias= (char*) "proc";
+  proc_tables.table_name_length= 4;
+  proc_tables.lock_type= TL_READ;
+  Open_tables_state open_tables_state_backup;
+ 
+  /*
+    Check to see if the proc table can be opened for reading.
+  */
+  DBUG_PRINT("metadata_backup", ("opening the proc table"));
+  if (!(proc_table= open_proc_table_for_read(thd, &open_tables_state_backup)))
+  {
+    DBUG_PRINT("metadata_backup", ("error with proc table"));
+    DBUG_RETURN(-1);
+  }
+
+  /*
+    Loop through all of the results in the proc table.
+    Construct the CREATE PROCEDURE and CREATE FUNCTION SQL commands
+    for this database.
+  */
+  proc_table->file->ha_index_init(0, 1);
+  while (!proc_table->file->index_next(proc_table->record[0]))
+  {
+    get_field(thd->mem_root, proc_table->field[0], &tmp);
+    if (my_strcasecmp(system_charset_info, tmp.c_ptr(), db) == 0)
+    {
+      /*
+        Setup preamble for create statements including definer or
+        invoker access options.
+      */
+      DBUG_PRINT("metadata_backup", 
+                ("constructing the CREATE PROCEDURE/FUNCION statement"));
+      db_sql.length(0);
+      db_sql.append("CREATE ");     
+      get_field(thd->mem_root, proc_table->field[7], &tmp);
+      db_sql.append(tmp);     
+      get_field(thd->mem_root, proc_table->field[11], &tmp);
+      db_sql.append(" = ");     
+      db_sql.append(tmp);     
+      get_field(thd->mem_root, proc_table->field[2], &tmp);
+      db_sql.append(" ");     
+      db_sql.append(tmp);    
+      if (!my_strcasecmp(system_charset_info, tmp.c_ptr(), "PROCEDURE"))
+      { 
+        /* It's a procedure */ 
+        get_field(thd->mem_root, proc_table->field[1], &tmp);
+        db_sql.append(" ");     
+        db_sql.append(tmp);     
+        get_field(thd->mem_root, proc_table->field[8], &tmp);
+        db_sql.append(" (");     
+        db_sql.append(tmp);     
+        get_field(thd->mem_root, proc_table->field[10], &tmp);
+        db_sql.append(") \n");     
+        db_sql.append(tmp);
+      }
+      else
+      {
+        /* It's a function */
+        get_field(thd->mem_root, proc_table->field[1], &tmp);
+        db_sql.append(" ");     
+        db_sql.append(tmp);     
+        get_field(thd->mem_root, proc_table->field[8], &tmp);
+        db_sql.append(" (");     
+        db_sql.append(tmp);     
+        db_sql.append(") \nRETURNS ");     
+        get_field(thd->mem_root, proc_table->field[9], &tmp);
+        db_sql.append(tmp);
+        get_field(thd->mem_root, proc_table->field[6], &tmp);
+        if (!my_strcasecmp(system_charset_info, tmp.c_ptr(), "YES"))
+          db_sql.append(" DETERMINISTIC ");
+        else
+          db_sql.append(" ");
+        get_field(thd->mem_root, proc_table->field[10], &tmp);
+        db_sql.append(tmp);     
+      }
+      /*
+        Store the size of the string in the buffer followed by the
+        SQL string. Adjust pointer for next SQL string.
+      */
+      size= db_sql.length();
+      memcpy((int *)ptr, (int *)&size, sizeof(int));
+      DBUG_PRINT("metadata_backup", ("db query size = %d", size));
+      DBUG_PRINT("metadata_backup", ("db query = %s", db_sql.c_ptr()));
+      ptr= ptr + sizeof(int);
+      memcpy(ptr, db_sql.c_ptr(), db_sql.length());
+      ptr= ptr + db_sql.length();
+      blk_size= blk_size + sizeof(int) + db_sql.length();
+    }
+  }
+  DBUG_PRINT("metadata_backup", ("closing the proc table"));
+  proc_table->file->ha_index_end();
+  close_proc_table(thd, &open_tables_state_backup);
+
+  /* 
+    Write "end of block" marker to terminate SQL strings.
+  */
+  DBUG_PRINT("metadata_backup", ("write EOB terminator"));
+  size= 0;
+  memcpy((int *)ptr, (int *)&size, sizeof(int));
+  blk_size= blk_size + sizeof(int);
+  DBUG_PRINT("metadata_backup", ("block size = %d", blk_size));
+  buf.size= blk_size;
+  buf.stream_no= 0;
+  DBUG_RETURN(0);
+}
+
+/*
+  Get the metadata for the list of tables specified.
+
+  SYNOPSIS
+    get_table_metadata()
+    THD *thd        - The current thread instance.
+    TABLE_LIST *tbl - The list of tables.
+    Buffer &buf     - A reference to a backup::Buffer struct used
+                      for storing the SQL strings.
+
+  DESCRIPTION
+    This procedure loads the buffer with the SQL statements for
+    creating the tablee and all of the triggers associated with it.
+
+  NOTES
+    SQL strings are stored in the Buffer.data memory with the size
+    (int) of the string followed by the string. A list of SQL 
+    strings are terminated by a int value of 0. The format of the
+    Buffer.data memory would resemble the following for 3 SQL strings:
+
+    <int size> | <char *> SQL string    // first string 
+    <int size> | <char *> SQL string    // second string 
+    <int size> | <char *> SQL string    // third string 
+    <int size>                          // size = 0 EOB terminator 
+
+  RETURNS
+    0  - no errors.
+    -1 - error reading table or trigger metadata
+*/
+int get_table_metadata(THD *thd, TABLE_LIST *tbl, Buffer &buf)
+{
+  String tbl_sql;
+  char *ptr= (char *)buf.data;
+  int blk_size= 0;
+  int size;
+  TABLE_LIST *table;
+
+  DBUG_ENTER("get_table_metadata");
+  /*
+    Check to see if tables exist and open them. Abort if 
+    something is wrong or tables cannot be locked.
+  */
+  tbl->lock_type= TL_READ;
+  DBUG_PRINT("metadata_backup", ("opening the tables"));
+  if (open_and_lock_tables(thd, tbl))
+  {
+    DBUG_PRINT("metadata_backup", ( "error opening tables!" ));
+    DBUG_RETURN(-1);
+  }
+
+  for (table= tbl; table; table= table->next_local)
+  {
+    tbl_sql.length(0);
+    /* 
+      Get the CREATE statement for the table and store it in the buffer.
+    */
+    DBUG_PRINT("metadata_backup", ("constructing CREATE TABLE statement"));
+    store_create_info(thd, table, &tbl_sql, NULL);
+    size= tbl_sql.length();
+    DBUG_PRINT("metadata_backup", ("query size = %d", size));
+    DBUG_PRINT("metadata_backup", ("query = %s", tbl_sql.c_ptr()));
+    memcpy((int *)ptr, (int *)&size, sizeof(int));
+    ptr= ptr + sizeof(int);
+    memcpy((char *)ptr, tbl_sql.c_ptr(), tbl_sql.length());
+    ptr= ptr + tbl_sql.length();
+    blk_size= blk_size + sizeof(int) + tbl_sql.length();
+
+    /* 
+      If triggers exist for this table, open the trigger list
+      and construct the CREATE TRIGGER statements placing them in
+      the buffer.
+    */
+    if (table->table->triggers)
+    {
+      Table_triggers_list *triggers= table->table->triggers;
+      int event, timing;
+      for (event= 0; event < (int)TRG_EVENT_MAX; event++)
+      {
+        for (timing= 0; timing < (int)TRG_ACTION_MAX; timing++)
+        {
+          LEX_STRING trigger_name;
+          LEX_STRING trigger_stmt;
+          ulong sql_mode;
+          char definer_holder[USER_HOST_BUFF_SIZE];
+          LEX_STRING definer_buffer;
+          definer_buffer.str= definer_holder;
+          if (!triggers->get_trigger_info(thd, (enum trg_event_type) event,
+                                         (enum trg_action_time_type)timing,
+                                         &trigger_name, &trigger_stmt,
+                                         &sql_mode,
+                                         &definer_buffer))
+          {
+            DBUG_PRINT("metadata_backup", 
+                      ("constructing the CREATE TRIGGER statement"));
+            tbl_sql.length(0);
+            tbl_sql.append("CREATE DEFINER = ");
+            tbl_sql.append(definer_buffer.str);
+            tbl_sql.append(" TRIGGER ");
+            tbl_sql.append(trigger_name.str);
+            tbl_sql.append(" ");
+            tbl_sql.append(trg_action_time_type_names[timing].str);
+            tbl_sql.append(" ");
+            tbl_sql.append(trg_event_type_names[event].str);
+            tbl_sql.append(" ON ");
+            tbl_sql.append(tbl->table_name);
+            tbl_sql.append(" \nFOR EACH ROW ");
+            tbl_sql.append(trigger_stmt.str);
+            /*
+              Store the size of the string in the buffer followed by the
+              SQL string. Adjust pointer for next SQL string.
+            */
+            size= tbl_sql.length();
+            DBUG_PRINT("metadata_backup", ("trg query size = %d", size));
+            DBUG_PRINT("metadata_backup", ("trg query = %s", tbl_sql.c_ptr()));
+            memcpy((int *)ptr, (int *)&size, sizeof(int));
+            ptr= ptr + sizeof(int);
+            memcpy(ptr, tbl_sql.c_ptr(), tbl_sql.length());
+            ptr= ptr + tbl_sql.length();
+            blk_size= blk_size + sizeof(int) + tbl_sql.length();
+          }
+          /* 
+            Skip this trigger if it isn't for this table.
+          */
+          else
+            continue; 
+        }
+      }
+    }
+    /*
+      If the size of the sql strings has exceeded the size of the
+      buffer, exit with an error.
+    */
+    if (blk_size > buf.size)
+    {
+      DBUG_PRINT("metadata_backup", ("buffer size too small!"));
+      DBUG_RETURN(-1); /* buffer too small! */
+    }
+  }
+  /*
+    Remove read lock on the tables
+  */
+  DBUG_PRINT("metadata_backup", ("closing the tables"));
+  if (thd->lock)
+  {
+    mysql_unlock_tables(thd, thd->lock);
+    thd->lock=0;
+  }
+
+  /* 
+    Write "end of block" marker to terminate SQL strings.
+  */
+  DBUG_PRINT("metadata_backup", ("write EOB terminator"));
+  size= 0;
+  memcpy((int *)ptr, (int *)&size, sizeof(int));
+  blk_size= blk_size + sizeof(int);
+  DBUG_PRINT("metadata_backup", ("block size = %d", blk_size));
+  buf.size= blk_size;
+  buf.stream_no= 0;
+  DBUG_RETURN(0);
+}
+
+/*
+  Execute the SQL strings in the backup::Buffer.data memory.
+
+  SYNOPSIS
+    execute_metadata()
+    THD *thd        - The current thread instance.
+    Buffer &buf     - A reference to a backup::Buffer struct used
+                      for storing the SQL strings.
+
+  DESCRIPTION
+    This procedure reads the buffer with the SQL statements and
+    executes each statement in the buffer.
+
+  NOTES
+    Method returns -1 and stops processing SQL statements if an
+    error occurs during execution. Remaining statments are not 
+    processed.
+
+  RETURNS
+    0  - no errors.
+    -1 - error executing a SQL statement
+*/
+int execute_metadata(THD *thd, Buffer &buf)
+{
+  char *ptr= (char *)buf.data;
+  int query_size= -1;
+  int bytes_read= 0;
+
+  DBUG_ENTER("execute_metadata");
+  /*
+    While the query_size is > 0 and there are bytes left to read in
+    the backup::Buffer.data memory, read the size of the query string
+    place it in the thd->query_length attribute and read the query
+    string and place it in the thd->query attribute. Setup the thd
+    to execute the query then call mysql_parse() to run the query.
+  */
+  while ((query_size != 0) && (bytes_read < buf.size))
+  {
+    /* 
+      Read the size of the query. If > 0, get the statement and
+      execute it. 
+    */
+    memcpy(&query_size, (int *)ptr, sizeof(int));
+    DBUG_PRINT("metadata_backup", ("query size = %d", query_size));
+    ptr= ptr + sizeof(int);
+    if (query_size > 0)
+    {
+      /*
+        Copy the query string and size into the thread.
+      */
+      memcpy(thd->query, ptr, query_size);
+      ptr= ptr + query_size;
+      thd->query_length= query_size;
+      thd->query[query_size]= 0; /* C string terminator */
+      DBUG_PRINT("metadata_backup", ("query = %s", thd->query));
+      /* 
+        Setup the thread to run the query and execute.
+      */
+      thd->set_time(time(NULL));
+      VOID(pthread_mutex_lock(&LOCK_thread_count));
+      thd->query_id = next_query_id();
+      VOID(pthread_mutex_unlock(&LOCK_thread_count));
+      thd->variables.pseudo_thread_id= thread_id;	
+      DBUG_PRINT("metadata_backup", ("executing the query..."));
+      mysql_parse(thd, thd->query, thd->query_length);
+      /*
+        If there were errors during query execution, exit with an error.
+      */
+      if (thd->query_error)
+      {
+        DBUG_PRINT("metadata_backup", 
+                  ("error executing the query! err = %d", thd->query_error));
+        DBUG_RETURN(-1);
+      }
+    }
+  }
+  DBUG_PRINT("metadata_backup", ("end of block"));
+  DBUG_RETURN(0);
+}
+
+/*
+  This method is a debugging tool to print out the contents of a 
+  backup::Buffer.data memory containing a list of SQL Strings.
+*/
+void dump_buffer(Buffer &buf)
+{
+  char *ptr= (char *)buf.data;
+  int query_size= -1;
+  int bytes_read= 0;
+  char *tmp = new char[4096];
+
+  printf("\nDumping buffer.data:\n-------------------------------------------------------------------------------\n");
+  while ((query_size != 0) && (bytes_read < buf.size))
+  {
+    /* Read the size of the query */
+    memcpy(&query_size, (int *)ptr, sizeof(int));
+    ptr= ptr + sizeof(int);
+    if (query_size > 0)
+    {
+      strcpy(tmp, "");
+      printf("Query Size = %d\n", query_size);
+      memcpy(tmp, ptr, query_size);
+      tmp[query_size]= 0;
+      printf("%s\n", tmp);
+      ptr= ptr + query_size;
+    }
+  }
+  printf("-------------------------------------------------------------------------------\n<END OF BUFFER>\n");
+}
 
 // Writing/reading table definitions
 // This implementation uses temporary formad to be replaced by DDL statements later.

Thread
bk commit into 5.1 tree (cbell:1.2490)cbell23 Mar