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-04-10 16:06:22-04:00, cbell@mysql_cab_desk. +12 -0
WL#3327 : Online Backup Plan - Phase 2
This patch adds a series of refinements to the code to meet the goals
of the phase 2 (Alpha release) of online backup.
Refinements include:
- ability to backup multiple databases
- additional error handling
- storage of database metadata in the archive
- storage of table metadata in the archive
- prototype for a show command 'SHOW BACKUP'
sql/backup/archive.cc@stripped, 2007-04-10 16:06:15-04:00, cbell@mysql_cab_desk. +12 -0
WL#3327 : Online Backup Plan - Phase 2
This patch adds a utility that can be used in phase 3 or for testing
of the new catalog structure.
sql/backup/archive.h@stripped, 2007-04-10 16:06:16-04:00, cbell@mysql_cab_desk. +43 -18
WL#3327 : Online Backup Plan - Phase 2
This patch adds a new structure for managing the archive catalog.
The catalog contains the list of databases, the SQL commands to
create them as well as all of the tables in each database and the
SQL commands to create each table.
sql/backup/backup_kernel.h@stripped, 2007-04-10 16:06:16-04:00, cbell@mysql_cab_desk. +4 -2
WL#3327 : Online Backup Plan - Phase 2
This patch adds a parameter to determine if the operation on the
file path is a read (restore) or a write (backup). The patch also
added the database list to the do_backup method.
sql/backup/be_default.cc@stripped, 2007-04-10 16:06:16-04:00, cbell@mysql_cab_desk. +29 -3
WL#3327 : Online Backup Plan - Phase 2
This patch corrects two problems found during testing. 1) if a database
that is being backed up has a table that does not support a delete all
rows operation, the code ignores the response because the table is
being dropped anyway. 2) If a database is being backed up with empty
tables, no data is requested for those empty tables and therefore the
linear advance mechanism in the default backup drive fails to sync with
the backup pump. The code change allows for seeking the table specified
in the buffer (buf.stream_no).
sql/backup/data_backup.cc@stripped, 2007-04-10 16:06:17-04:00, cbell@mysql_cab_desk. +2 -2
WL#3327 : Online Backup Plan - Phase 2
This patch increases the size of the buffers to accomodate tables with
large record buffers.
sql/backup/meta_backup.cc@stripped, 2007-04-10 16:06:17-04:00, cbell@mysql_cab_desk. +490
-153
WL#3327 : Online Backup Plan - Phase 2
This patch adds the code to support reading and writing of the archive
catalog. Methods were added to retrieve the metadata strings for both
databases and tables. Changes were made to accomodate the new methods
and to build the catalog in memory prior to backup.
sql/backup/sql_backup.cc@stripped, 2007-04-10 16:06:17-04:00, cbell@mysql_cab_desk. +285 -43
WL#3327 : Online Backup Plan - Phase 2
This patch adds code to process the new catalog structure. It also
includes minor changes to the feedback to the client.
sql/backup/tables.cc@stripped, 2007-04-10 16:06:18-04:00, cbell@mysql_cab_desk. +20 -0
WL#3327 : Online Backup Plan - Phase 2
This patch adds a method to build a TABLE_LIST from a pair of strings
(table_name, database_name). The method is used during restore for
processing the table metadata found in the catalog.
sql/backup/tables.h@stripped, 2007-04-10 16:06:18-04:00, cbell@mysql_cab_desk. +1 -1
WL#3327 : Online Backup Plan - Phase 2
This patch adds a method to build a TABLE_LIST from a pair of strings
(table_name, database_name). The method is used during restore for
processing the table metadata found in the catalog.
sql/sql_lex.h@stripped, 2007-04-10 16:06:14-04:00, cbell@mysql_cab_desk. +1 -0
WL#3327 : Online Backup Plan - Phase 2
This patch adds an enum for a prototype of a show command
for online backup. The enum is used in the big switch to
run the code for the SHOW BACKUP command.
sql/sql_parse.cc@stripped, 2007-04-10 16:06:14-04:00, cbell@mysql_cab_desk. +19 -6
WL#3327 : Online Backup Plan - Phase 2
This patch adds the code for the SHOW BACKUP command and basic
error handling for the BACKUP/RESTORE DATABASE commands.
sql/sql_yacc.yy@stripped, 2007-04-10 16:06:15-04:00, cbell@mysql_cab_desk. +44 -7
WL#3327 : Online Backup Plan - Phase 2
This patch adds code to the parser to capture the database list for
the BACKUP/RESTORE DATABASE commands.
# 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-backup-phase2
--- 1.264/sql/sql_lex.h 2007-04-10 16:06:37 -04:00
+++ 1.265/sql/sql_lex.h 2007-04-10 16:06:37 -04:00
@@ -113,6 +113,7 @@
SQLCOM_CREATE_SERVER, SQLCOM_DROP_SERVER, SQLCOM_ALTER_SERVER,
SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT, SQLCOM_DROP_EVENT,
SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS,
+ SQLCOM_SHOW_ARCHIVE,
/* This should be the last !!! */
--- 1.634/sql/sql_parse.cc 2007-04-10 16:06:37 -04:00
+++ 1.635/sql/sql_parse.cc 2007-04-10 16:06:37 -04:00
@@ -1856,24 +1856,37 @@
break;
}
#endif
+ case SQLCOM_SHOW_ARCHIVE:
+ {
+ backup::Location *loc;
+ LEX_STRING where = lex->backup_dir;
+ loc= backup::Location::find(where, TRUE);
+ if (!loc)
+ goto error; // TODO: report something meaningfull
+ backup::show_archive_catalog(thd,*loc);
+ loc->free();
+ break;
+ }
case SQLCOM_BACKUP:
case SQLCOM_RESTORE:
{
#ifndef EMBEDDED_LIBRARY
-
+ backup::Location *loc;
+
// TODO: make sanity checks on parameters.
LEX_STRING where = lex->backup_dir;
- backup::Location *loc= backup::Location::find(where);
-
+ if (lex->sql_command==SQLCOM_BACKUP)
+ loc= backup::Location::find(where, FALSE);
+ else
+ loc= backup::Location::find(where, TRUE);
if (!loc)
goto error; // TODO: report something meaningfull
-
if (lex->sql_command==SQLCOM_BACKUP)
- backup::do_backup(thd,*loc);
+ backup::do_backup(thd,*loc, &lex->db_list);
else
- backup::do_restore(thd,*loc);
+ backup::do_restore(thd,*loc);
loc->free();
#endif
--- 1.546/sql/sql_yacc.yy 2007-04-10 16:06:37 -04:00
+++ 1.547/sql/sql_yacc.yy 2007-04-10 16:06:37 -04:00
@@ -5582,18 +5582,50 @@
restore:
- RESTORE_SYM /* table_or_tables */ FROM TEXT_STRING_sys
+ RESTORE_SYM DATABASE
{
- Lex->sql_command= SQLCOM_RESTORE;
- Lex->backup_dir= $3;
- };
+ Lex->sql_command = SQLCOM_RESTORE;
+ Lex->db_list.empty();
+ }
+ /*database_list*/ FROM TEXT_STRING_sys
+ {
+ Lex->backup_dir = $5;
+ };
backup:
- BACKUP_SYM /* table_or_tables */ TO_SYM TEXT_STRING_sys
+ BACKUP_SYM DATABASE
{
Lex->sql_command = SQLCOM_BACKUP;
- Lex->backup_dir= $3;
- };
+ Lex->db_list.empty();
+ }
+ database_list TO_SYM TEXT_STRING_sys
+ {
+ Lex->backup_dir = $6;
+ };
+
+database_list:
+ '*'
+ {
+ LEX_STRING wild_buff;
+ if (!(wild_buff.str= alloc_root(YYTHD->mem_root, 3)))
+ YYABORT;
+ strmake(wild_buff.str, "*", 1);
+ if (Lex->db_list.push_back((LEX_STRING*)
+ sql_memdup(&wild_buff, sizeof(LEX_STRING))))
+ YYABORT;
+ }
+ | ident
+ {
+ if (Lex->db_list.push_back((LEX_STRING*)
+ sql_memdup(&$1, sizeof(LEX_STRING))))
+ YYABORT;
+ }
+ | database_list ',' ident
+ {
+ if (Lex->db_list.push_back((LEX_STRING*)
+ sql_memdup(&$3, sizeof(LEX_STRING))))
+ YYABORT;
+ };
checksum:
CHECKSUM_SYM table_or_tables
@@ -8701,6 +8733,11 @@
Lex->spname= $3;
Lex->sql_command = SQLCOM_SHOW_CREATE_EVENT;
}
+ | BACKUP_SYM TEXT_STRING_sys
+ {
+ Lex->sql_command = SQLCOM_SHOW_ARCHIVE;
+ Lex->backup_dir = $2;
+ }
;
show_engine_param:
--- 1.10/sql/backup/be_default.cc 2007-04-10 16:06:37 -04:00
+++ 1.11/sql/backup/be_default.cc 2007-04-10 16:06:37 -04:00
@@ -442,8 +442,12 @@
DBUG_ENTER("Default_backup::truncate_table)");
hdl= tbl->file;
last_write_res= cur_table->file->delete_all_rows();
- DBUG_ASSERT(last_write_res == 0);
- if (last_write_res != 0)
+ /*
+ Check to see if delete all rows was ok. Ignore if the handler
+ doesn't support it.
+ */
+ DBUG_ASSERT((last_write_res == 0)||(last_write_res == HA_ERR_WRONG_COMMAND));
+ if ((last_write_res != 0) && (last_write_res != HA_ERR_WRONG_COMMAND))
DBUG_RETURN(backup::ERROR);
DBUG_RETURN(backup::OK);
}
@@ -572,7 +576,29 @@
int res;
get_next_table= 0;
- res= next_table();
+ /*
+ It is possible for the backup system to send data to this
+ engine out of sequence from the table list. When a non-sequential
+ access is detected, start the table list at the beginning and
+ find the table in question. This is needed if any tables (more
+ than MAX_RETRIES are empty!
+ */
+ if ((tbl_num + 1) == buf.stream_no) //do normal sequential lookup
+ res= next_table();
+ else //do linear search
+ {
+ int i= 0;
+
+ cur_table= NULL;
+ tables_in_backup= all_tables;
+ do
+ {
+ i++;
+ res= next_table();
+ }
+ while ((i != buf.stream_no) && !res);
+ tbl_num= i - 1;
+ }
if (res)
{
if (cur_table == NULL)
--- 1.15/sql/backup/sql_backup.cc 2007-04-10 16:06:37 -04:00
+++ 1.16/sql/backup/sql_backup.cc 2007-04-10 16:06:37 -04:00
@@ -8,6 +8,7 @@
//#define TEST yes
+//int sortcmp(const String *s,const String *t, CHARSET_INFO *cs);
namespace backup {
@@ -29,16 +30,21 @@
IStream* open_for_read(const Location&);
OStream* open_for_write(const Location&);
-bool collect_tables_to_backup(THD*,Backup_info&);
+bool collect_tables_to_backup(THD *,Backup_info &);
+bool collect_databases_to_backup(THD *thd, Backup_info &info);
bool write_header(const Backup_info&,OStream&);
-bool write_table_definitions(THD*,const Backup_info&,OStream&);
+bool write_catalog(const Backup_info&,OStream&);
bool write_table_data(const Backup_info&,OStream&);
+bool get_table_metadata(THD *thd, TABLE_LIST *tbl,
+ List<String> *buffer);
+bool get_db_metadata(THD *thd, const char *db,
+ List<String> *buffer);
/*
Implements BACKUP command -- called from sql_parse.cc
*/
-int do_backup(THD *thd, const Location &loc)
+int do_backup(THD *thd, const Location &loc, List <LEX_STRING> *db_list)
{
DBUG_ENTER("backup::do_backup");
@@ -52,7 +58,6 @@
size_t total_size= 0;
size_t header_size= 0;
- size_t table_size= 0;
size_t data_size= 0;
bool stream_opened= FALSE;
@@ -67,22 +72,30 @@
stream_opened= TRUE;
Backup_info info;
+ info.db_list= db_list;
+ List_iterator<LEX_STRING> db_names(*info.db_list);
+ LEX_STRING *dbstr= db_names++;
+ if (!my_strcasecmp(system_charset_info,
+ dbstr->str, "*"))
+ {
+ info.db_list->empty();
+ collect_databases_to_backup(thd, info);
+ }
if(!collect_tables_to_backup(thd,info))
goto error;
DBUG_PRINT("backup",("Writing image header"));
- write_header(info,*backup_stream);
+ backup_stream->bytes= 0; // must initialize to 0
- header_size= backup_stream->bytes;
+ write_header(info,*backup_stream);
- DBUG_PRINT("backup",("Writing table definitons"));
+ DBUG_PRINT("backup",("Writing image catalog"));
- if(!write_table_definitions(thd,info,*backup_stream))
- goto error;
+ write_catalog(info,*backup_stream);
- table_size= backup_stream->bytes - header_size;
+ header_size= backup_stream->bytes;
DBUG_PRINT("backup",("Writing backup images"));
@@ -90,7 +103,7 @@
goto error;
total_size= backup_stream->bytes;
- data_size= total_size -table_size -header_size;
+ data_size= total_size -header_size;
DBUG_PRINT("backup",("Backup image written"));
@@ -98,22 +111,28 @@
char buf[255];
- my_snprintf(buf,sizeof(buf),"Backed-up %d tables.",info.table_count);
+ if (info.catalog.elements == 1)
+ my_snprintf(buf,sizeof(buf),"This archive contains %d
database",info.catalog.elements);
+ else
+ my_snprintf(buf,sizeof(buf),"This archive contains %d
databases",info.catalog.elements);
protocol->prepare_for_resend();
protocol->store(buf,system_charset_info);
protocol->write();
- my_snprintf(buf,sizeof(buf),"Wrote %d bytes of backup archive.",total_size);
+ if (info.table_count == 1)
+ my_snprintf(buf,sizeof(buf),"and a total of %d table.",info.table_count);
+ else
+ my_snprintf(buf,sizeof(buf),"and a total of %d tables.",info.table_count);
protocol->prepare_for_resend();
protocol->store(buf,system_charset_info);
protocol->write();
- my_snprintf(buf,sizeof(buf)," header = %-8d bytes",header_size);
+ my_snprintf(buf,sizeof(buf)," ");
protocol->prepare_for_resend();
protocol->store(buf,system_charset_info);
protocol->write();
- my_snprintf(buf,sizeof(buf)," table defs = %-8d bytes",table_size);
+ my_snprintf(buf,sizeof(buf)," header = %-8d bytes",header_size);
protocol->prepare_for_resend();
protocol->store(buf,system_charset_info);
protocol->write();
@@ -123,6 +142,16 @@
protocol->store(buf,system_charset_info);
protocol->write();
+ my_snprintf(buf,sizeof(buf)," = --------------",data_size);
+ protocol->prepare_for_resend();
+ protocol->store(buf,system_charset_info);
+ protocol->write();
+
+ my_snprintf(buf,sizeof(buf)," total %-8d bytes", total_size);
+ protocol->prepare_for_resend();
+ protocol->store(buf,system_charset_info);
+ protocol->write();
+
send_eof(thd);
goto end;
@@ -146,8 +175,12 @@
// Currently we try to backup all tables in 'test' database (but only tables for which
// appropriate backup engine is found will be included in the image).
-bool collect_tables_to_backup(THD *thd, Backup_info &info)
+bool collect_tables_to_backup(THD *thd,Backup_info &info)
{
+ LEX_STRING *tmp;
+ schema_ref *cat;
+ String db_name;
+
DBUG_ENTER("backup::collect_tables_to_backup");
// open and scan I_S.TABLES table
@@ -163,21 +196,67 @@
::handler *ha = i_s_tables->file;
// TODO: locking
- ha->ha_rnd_init(TRUE);
- // TODO: use conditions, do it properly
- while( ! ha->rnd_next(i_s_tables->record[0]) )
- {
- Table tbl(i_s_tables);
+ /*
+ Build catalog for writing...
+ For each database in the db_list,
+ create a new catalog struct
+ fill with tables and their metadata
+ add catalog to list
+ */
+ List_iterator<LEX_STRING> databases(*info.db_list);
- if( tbl && tbl.db().name() == String("test",default_charset) ) // TODO:
tbl.db() == test_db
+ table_info *ti;
+ while ((tmp= databases++))
+ {
+ /*
+ Save this database in the catalog along with metadata
+ */
+ cat= new schema_ref(); // create a new catalog struct
+ cat->db_name= new (current_thd->mem_root) String();
+ cat->db_name->length(0);
+ cat->db_name->append(tmp->str); // save the database name
+
+ DBUG_PRINT("backup", ("Creating database metadata."));
+ get_db_metadata(thd, cat->db_name->c_ptr(), &cat->db_metadata);
+ DBUG_PRINT("backup", ("Database metadata created."));
+
+ ha->ha_rnd_init(TRUE);
+
+ // TODO: use conditions, do it properly
+ while( ! ha->rnd_next(i_s_tables->record[0]) )
{
- DBUG_PRINT("backup", ("Found table %s in test database",
- tbl.name().ptr()));
-
- // Backup_info::add method selects/creates sub-image appropriate for storing given
table
- info.add(tbl,tbl.hton());
+ Table tbl(i_s_tables);
+ db_name= tbl.db().name();
+ if (tbl && !my_strcasecmp(system_charset_info,
+ db_name.c_ptr(), tmp->str) &&
+ my_strcasecmp(system_charset_info,
+ db_name.c_ptr(), "information_schema"))
+ {
+ DBUG_PRINT("backup", ("Found table %s for database %s",
+ tbl.name().ptr(), tmp->str));
+ // Backup_info::add method selects/creates sub-image appropriate for storing
given table
+ info.add(tbl,tbl.hton());
+ /*
+ Add the table to this database's table list
+ */
+ ti= new table_info();
+ ti->table_name= new (current_thd->mem_root) String();
+ ti->table_name->length(0);
+ ti->table_name->append(tbl.name());
+ /*
+ Get the metadata for the table
+ */
+ TABLE_LIST *ptr=
+ build_table_list_str((char *)tbl.name().ptr(), db_name.c_ptr(), TL_READ);
+ get_table_metadata(thd, ptr, &ti->table_metadata);
+ /*
+ Save the table_info to the tables list for this database
+ */
+ cat->tables.push_back(ti);
+ }
}
+ info.catalog.push_back(cat); //add this catalog to the list of catalogs
}
DBUG_PRINT("backup", ("No more tables in I_S"));
@@ -185,10 +264,56 @@
ha->ha_rnd_end();
// TODO: close i_s_tables
-
+ i_s_tables->file->close();
DBUG_RETURN(TRUE);
}
+bool collect_databases_to_backup(THD *thd, Backup_info &info)
+{
+ LEX_STRING *tmp;
+ String db_name;
+
+ DBUG_ENTER("backup::collect_databases_to_backup");
+
+ // open and scan I_S.TABLES table
+
+ TABLE *db_table = get_schema_table(thd, ::get_schema_table(SCH_SCHEMATA));
+
+ if (!db_table)
+ {
+ DBUG_PRINT("backup",("get_schema_table returned NULL!"));
+ DBUG_ERROR(ERROR);
+ }
+
+ ::handler *ha = db_table->file;
+
+ // TODO: locking
+
+ ha->ha_rnd_init(TRUE);
+
+ // TODO: use conditions, do it properly
+ while (!ha->rnd_next(db_table->record[0]))
+ {
+ db_name.length(0);
+ db_table->field[1]->val_str(&db_name);
+ if (my_strcasecmp(system_charset_info,
+ db_name.c_ptr(), "information_schema"))
+ {
+ DBUG_PRINT("backup", ("Found database %s", db_name.ptr()));
+ tmp= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING));
+ tmp->str= my_malloc(MAX_ALIAS_NAME, MYF(MY_WME));
+ strcpy(tmp->str, db_name.c_ptr());
+ info.db_list->push_back(tmp);
+ }
+ }
+
+ DBUG_PRINT("backup", ("No more databases in I_S"));
+
+ ha->ha_rnd_end();
+
+ db_table->file->close();
+ DBUG_RETURN(TRUE);
+}
/*
Logic for selecting sub-image format for a given location:
@@ -297,9 +422,88 @@
namespace backup {
bool read_header(IStream&,Restore_info&);
-bool create_all_tables(THD*,const Restore_info&,IStream&);
+bool read_catalog(IStream&,Restore_info&);
+bool restore_metadata(THD *thd, const Restore_info &info);
bool restore_table_data(const Restore_info&,IStream&);
+/*
+ Get the metadata for the backup file specified and display
+ it to the client interface.
+
+ SYNOPSIS
+ show_archive_catalog()
+ THD *thd - The current thread instance.
+ Location loc - The name of the archive with path.
+
+ DESCRIPTION
+ This procedure opens the archive and extracts the metadata
+ for the databases and tables stored in the archive. A simple
+ list of the tables by database is sent to the client.
+
+ RETURNS
+ 0 - no errors.
+ -1 - database cannot be read or doesn't exist.
+*/
+int show_archive_catalog(THD *thd, const Location &loc)
+{
+ Protocol *protocol= thd->protocol;
+ List<Item> field_list;
+ Item *item;
+
+ DBUG_ENTER("backup::show_archive_catalog");
+ field_list.push_back(item= new Item_empty_string("Database",255));
+ field_list.push_back(item= new Item_empty_string("Table",255));
+ field_list.push_back(item= new Item_empty_string("Metadata",255));
+ item->maybe_null= TRUE;
+ protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
Protocol::SEND_EOF);
+ Restore_info info;
+
+ IStream *backup_str= open_for_read(loc);
+
+ if (!backup_str)
+ DBUG_RETURN(-1);
+
+ // for debug purposes -- grep for 'stream: ' in server trace
+ dump_stream(*backup_str);
+
+ backup_str->rewind();
+ DBUG_ASSERT( read_header(*backup_str,info) );
+ DBUG_ASSERT( read_catalog(*backup_str,info) );
+ backup_str->close();
+
+ // send catalog to client
+
+ /*
+ Loop through the catalog and list the contents by
+ database.
+ */
+ List<schema_ref> cat1= info.catalog;
+ List_iterator<schema_ref> catalog(cat1);
+ schema_ref *tmp;
+ while ((tmp= catalog++))
+ {
+ List_iterator<table_info> tbls(tmp->tables);
+ table_info *t;
+ while ((t= tbls++))
+ {
+ /*
+ Send the following data:
+ database name (from tmp->db_name)
+ table name (from t->table_name)
+ CREATE TABLE SQL for the table (first string in table_metadata)
+ */
+ protocol->prepare_for_resend();
+ protocol->store(tmp->db_name->c_ptr(),system_charset_info);
+ protocol->store(t->table_name->c_ptr(),system_charset_info);
+ List_iterator<String> tbl_meta(t->table_metadata);
+ String *tmp= tbl_meta++; //just get the first string which is create
+ protocol->store(tmp->c_ptr(),system_charset_info);
+ protocol->write();
+ }
+ }
+ send_eof(thd);
+ DBUG_RETURN(OK);
+}
int do_restore(THD *thd, const Location &loc)
{
@@ -315,7 +519,6 @@
size_t total_size= 0;
size_t header_size= 0;
- size_t table_size= 0;
size_t data_size= 0;
Restore_info info;
@@ -332,6 +535,8 @@
DBUG_ASSERT( read_header(*backup_str,info) );
+ DBUG_ASSERT( read_catalog(*backup_str,info) );
+
header_size= backup_str->bytes;
DBUG_PRINT("restore",("Got archive header"));
@@ -353,18 +558,16 @@
DBUG_PRINT("restore",("== end of catalog"));
- res= create_all_tables(thd,info,*backup_str);
+ res= restore_metadata(thd, info);
DBUG_ASSERT(res);
- table_size= backup_str->bytes - header_size;
-
DBUG_PRINT("restore",("All tables created, restoring data"));
res= restore_table_data(info,*backup_str);
DBUG_ASSERT(res);
total_size= backup_str->bytes;
- data_size= total_size -table_size -header_size;
+ data_size= total_size -header_size;
DBUG_PRINT("restore",("Done."));
@@ -374,22 +577,29 @@
char buf[255];
- my_snprintf(buf,sizeof(buf),"Restored %d tables.",info.table_count);
+
+ if (info.catalog.elements == 1)
+ my_snprintf(buf,sizeof(buf),"This archive restored %d
database",info.catalog.elements);
+ else
+ my_snprintf(buf,sizeof(buf),"This archive restored %d
databases",info.catalog.elements);
protocol->prepare_for_resend();
protocol->store(buf,system_charset_info);
protocol->write();
- my_snprintf(buf,sizeof(buf),"Read %d bytes of backup archive.",total_size);
+ if (info.table_count == 1)
+ my_snprintf(buf,sizeof(buf),"and a total of %d table.",info.table_count);
+ else
+ my_snprintf(buf,sizeof(buf),"and a total of %d tables.",info.table_count);
protocol->prepare_for_resend();
protocol->store(buf,system_charset_info);
protocol->write();
- my_snprintf(buf,sizeof(buf)," header = %-8d bytes",header_size);
+ my_snprintf(buf,sizeof(buf)," ");
protocol->prepare_for_resend();
protocol->store(buf,system_charset_info);
protocol->write();
- my_snprintf(buf,sizeof(buf)," table defs = %-8d bytes",table_size);
+ my_snprintf(buf,sizeof(buf)," header = %-8d bytes",header_size);
protocol->prepare_for_resend();
protocol->store(buf,system_charset_info);
protocol->write();
@@ -399,6 +609,16 @@
protocol->store(buf,system_charset_info);
protocol->write();
+ my_snprintf(buf,sizeof(buf)," = --------------",data_size);
+ protocol->prepare_for_resend();
+ protocol->store(buf,system_charset_info);
+ protocol->write();
+
+ my_snprintf(buf,sizeof(buf)," total %-8d bytes",data_size+header_size);
+ protocol->prepare_for_resend();
+ protocol->store(buf,system_charset_info);
+ protocol->write();
+
send_eof(thd);
error:
@@ -467,12 +687,34 @@
Location*
-Location::find(const LEX_STRING &where)
+Location::find(const LEX_STRING &where, bool read)
{
- // FIXME: this is incomplete
-
- // TODO: analyse path and check that it is valid
+ char buff[FN_REFLEN];
+ int length;
+ length = dirname_part(buff, where.str);
+ /*
+ If reading, file must exist.
+ If writing, path must exist.
+ */
+ if (read)
+ {
+ if (my_access(where.str, F_OK) || (length == where.length))
+ {
+ my_error(ER_CANT_OPEN_FILE, MYF(0), where.str,
+ ER_CANT_OPEN_FILE);
+ return NULL;
+ }
+ }
+ else
+ {
+ if (my_access(buff, (F_OK|W_OK)))
+ {
+ my_error(ER_CANT_CREATE_FILE, MYF(0), where.str,
+ ER_CANT_CREATE_FILE);
+ return NULL;
+ }
+ }
return new File_loc(where.str);
}
@@ -532,7 +774,7 @@
/* restore wild field */
thd->lex= saved_lex;
-
+
return t;
}
--- 1.3/sql/backup/archive.cc 2007-04-10 16:06:37 -04:00
+++ 1.4/sql/backup/archive.cc 2007-04-10 16:06:37 -04:00
@@ -5,6 +5,17 @@
namespace backup {
+bool find_db_in_list(List<LEX_STRING> *db_list, String db_name)
+{
+ bool found= false;
+ List_iterator<LEX_STRING> databases(*db_list);
+ LEX_STRING *tmp;
+ while ((tmp= databases++))
+ if (!my_strcasecmp(system_charset_info, tmp->str, db_name.c_ptr()))
+ return(TRUE);
+ return(found);
+}
+
Backup_info::~Backup_info()
{
List_iterator<Backup_subimage> it(images);
@@ -12,6 +23,7 @@
while ((img= it++))
delete img;
+ catalog.empty();
}
Restore_info::~Restore_info()
--- 1.5/sql/backup/archive.h 2007-04-10 16:06:37 -04:00
+++ 1.6/sql/backup/archive.h 2007-04-10 16:06:37 -04:00
@@ -83,14 +83,13 @@
public:
- version_t m_ver;
+ version_t m_ver;
- Restore_subimage(uint no, version_t ver):
- Subimage_info(no), m_drv(NULL), m_ver(ver)
- {}
+ Restore_subimage(uint no, version_t ver):
+ Subimage_info(no), m_drv(NULL), m_ver(ver)
+ {}
- version_t ver() const
- { return m_ver; }
+ version_t ver() const { return m_ver; }
result_t create_driver()
{
@@ -110,7 +109,7 @@
static Restore_subimage* create_from_stream(uint,IStream&);
- protected:
+protected:
virtual result_t do_create_driver() =0;
@@ -130,28 +129,54 @@
{}
};
+// Information about databases and their tables.
+struct table_info
+{
+ String *table_name; // table name
+ List<String> table_metadata; // metadata for table
+ ~table_info()
+ { table_metadata.empty(); }
+};
+
+struct schema_ref
+{
+ String *db_name; // the name of the database
+ List<String> db_metadata; // metadata for the database
+ List<table_info> tables; // the list of tables
+ ~schema_ref()
+ {
+ db_metadata.empty();
+ tables.empty();
+ }
+};
+
+bool find_db_in_list(List<LEX_STRING> *db_list, String db_name);
+
struct Backup_info: public Image_info
{
- List<Backup_subimage> images;
- Backup_subimage *default_image;
+ List<Backup_subimage> images;
+ Backup_subimage *default_image;
+ List<LEX_STRING> *db_list; // list of databases
+ List<schema_ref> catalog; // list of tables by database
- Backup_info(): Image_info(7), default_image(NULL)
- {}
+ Backup_info(): Image_info(7), default_image(NULL)
+ {}
- ~Backup_info();
+ ~Backup_info();
- // Add table stored in a given storage engine
- bool add(const Table_ref &tbl, const ::handlerton *hton);
+ // Add table stored in a given storage engine
+ bool add(const Table_ref &tbl, const ::handlerton *hton);
};
struct Restore_info: public Image_info
{
- List<Restore_subimage> images;
+ List<Restore_subimage> images;
+ List<schema_ref> catalog; // list of tables by database
- Restore_info(): Image_info(7)
- {}
+ Restore_info(): Image_info(7)
+ {}
- ~Restore_info();
+ ~Restore_info();
};
} // backup namespace
--- 1.2/sql/backup/backup_kernel.h 2007-04-10 16:06:37 -04:00
+++ 1.3/sql/backup/backup_kernel.h 2007-04-10 16:06:37 -04:00
@@ -21,6 +21,7 @@
// of location object.
enum enum_type {SERVER_FILE, INVALID};
+ bool read;
virtual enum_type type() const
{ return INVALID; }
@@ -37,7 +38,7 @@
@returns NULL if the string doesn't denote a valid location
*/
- static Location* find(const LEX_STRING&);
+ static Location* find(const LEX_STRING&, bool);
};
//@{
@@ -45,7 +46,8 @@
Functions used to implement BACKUP/RESTORE SQL statements.
They are called from sql_parse.cc
*/
-int do_backup(THD*, const Location&);
+int show_archive_catalog(THD *thd, const Location &loc);
+int do_backup(THD*, const Location&, List <LEX_STRING> *db_list);
int do_restore(THD*, const Location&);
//@}
--- 1.9/sql/backup/data_backup.cc 2007-04-10 16:06:37 -04:00
+++ 1.10/sql/backup/data_backup.cc 2007-04-10 16:06:37 -04:00
@@ -129,7 +129,7 @@
private:
- static const uint m_buf_size= 1024;
+ static const uint m_buf_size= 2048;
static const uint get_buf_retries= 3; /**< if block writer has no buffers, retry
this many times before giving up */
uint m_drv_no;
@@ -231,7 +231,7 @@
Block_writer bw;
Pump(OStream &s, Backup_subimage &img, size_t pos):
- Backup_pump(img,bw), start_pos(pos), bw(1024,s)
+ Backup_pump(img,bw), start_pos(pos), bw(2048,s)
{}
friend class Scheduler;
--- 1.7/sql/backup/meta_backup.cc 2007-04-10 16:06:37 -04:00
+++ 1.8/sql/backup/meta_backup.cc 2007-04-10 16:06:37 -04:00
@@ -6,6 +6,8 @@
#include "archive.h"
#include "be_default.h"
#include "backup_aux.h"
+#include "sp.h"
+#include "sql_trigger.h"
namespace backup {
@@ -21,6 +23,10 @@
stream_result::value res= str.write2int(info.ver);
TEST_WR_RES(res);
+ DBUG_PRINT("restore",("header written"));
+
+ DBUG_PRINT("restore",("write images"));
+
List_iterator<Backup_subimage>
it(const_cast<List<Backup_subimage>&>(info.images));
Backup_subimage *img;
@@ -36,15 +42,90 @@
str.end_chunk();
+ DBUG_PRINT("restore",("images written"));
+
if( ino == 0 )
DBUG_RETURN(TRUE);
DBUG_PRINT("backup",(" ==="));
+ DBUG_RETURN(TRUE);
+}
+
+/*
+ Write the catalog to the stream.
- // write catalogs
+ SYNOPSIS
+ write_catalog()
+ Backup_info *info - The backup information for this archive.
+ OStream str - The stream to write to.
- it.rewind();
+ DESCRIPTION
+ This procedure writes the contents of the catalog to the
+ stream. Lists are prequalified with the number of elements to
+ enable faster construction of the catalog on read.
+
+ NOTES
+ The format of this information is stored in the stream as
+ follows:
+
+ <int> #schema_refs to read
+ schema_ref
+ db_name
+ <int> #db metadata strings
+ db_metadata
+ ...
+ <int> #table_info structs to read
+ table_info
+ table_name
+ <int> # table metadata strings
+ table_metadata
+ ...
+ ...
+ ...
+
+ RETURNS
+ 0 - no errors.
+ -1 - table or table name missing or not found in string.
+*/
+bool write_catalog(const Backup_info &info, OStream &str)
+{
+ uint ino;
+
+ DBUG_ENTER("backup::write_catalog");
+ List_iterator<Backup_subimage>
it(const_cast<List<Backup_subimage>&>(info.images));
+ Backup_subimage *img;
+
+ List<schema_ref> cat= info.catalog;
+ List_iterator<schema_ref> catalog(cat);
+ schema_ref *tmp;
+ str.write2int(cat.elements); // write # of schema_refs to read on restore
+ while ((tmp= catalog++))
+ {
+ str.writestr(tmp->db_name->c_ptr()); // write db name
+ str.write2int(tmp->db_metadata.elements); // write # db metadata strings
+ String *dbstr;
+ List_iterator<String> db_meta(tmp->db_metadata);
+ while ((dbstr= db_meta++))
+ str.writestr(dbstr->c_ptr()); // write db metadata string
+ str.write2int(tmp->tables.elements); // write # table_info structs
+ table_info *t;
+ List_iterator<table_info> tbls(tmp->tables);
+ str.end_chunk();
+ while ((t= tbls++))
+ {
+ str.writestr(t->table_name->c_ptr());
+ str.write2int(t->table_metadata.elements); // # table metadata strings
+ String *s;
+ List_iterator<String> tbl_meta(t->table_metadata);
+ while ((s= tbl_meta++))
+ str.writestr(s->c_ptr()); // write table metadata string
+ str.end_chunk();
+ }
+ }
+
+ // Write list of tables
+ it.rewind();
for( ino=0 ; (img= it++) ; ino++ )
{
str << img->tables; // write list of tables stored in the image
@@ -57,13 +138,16 @@
bool read_header(IStream &str, Restore_info &info)
{
- DBUG_ENTER("restore::read_header");
+ Restore_subimage *img;
+ uint ino;
+ DBUG_ENTER("restore::read_header");
stream_result::value res= str.read2int(info.ver);
TEST_RD_RES(res);
- Restore_subimage *img;
- uint ino;
+ DBUG_PRINT("restore",("header read"));
+
+ DBUG_PRINT("restore",("read images"));
for (ino=0 ; (img= Restore_subimage::create_from_stream(ino,str)); ino++)
{
@@ -75,9 +159,99 @@
res= str.next_chunk(); // move to next_chunk
+ DBUG_PRINT("restore",("images read"));
+
if( ino == 0 || res != stream_result::OK )
DBUG_RETURN(res == stream_result::OK);
+ DBUG_RETURN(TRUE);
+}
+
+/*
+ Read the catalog from the stream.
+
+ SYNOPSIS
+ read_catalog()
+ Restore_info *info - The restore information for this archive.
+ OStream str - The stream to write to.
+
+ DESCRIPTION
+ This procedure writes the contents of the catalog to the
+ stream. Lists are prequalified with the number of elements to
+ enable faster construction of the catalog on read.
+
+ RETURNS
+ 0 - no errors.
+ -1 - table or table name missing or not found in string.
+*/
+bool read_catalog(IStream &str, Restore_info &info)
+{
+ stream_result::value res; // result from read stream
+ Restore_subimage *img; // the image read
+ uint ino; // number of image read
+ schema_ref *cat; // reference to database data
+ String db_name; // database name
+ uint num_schemas= 0; // num of schemas to read
+ uint num_db_strings= 0; // num of db metadata strings
+ uint num_table_strings= 0; // num of table metadata strings
+ uint num_tables= 0; // num of tables to read
+ table_info *ti; // table data
+ String *s; // string for reading
+
+ DBUG_ENTER("restore::read_catalog");
+ res= str.read2int(num_schemas); // read # of schema_refs to read
+ TEST_RD_RES(res);
+ for (uint i= 0; i < num_schemas; i++)
+ {
+ cat= new schema_ref(); // create a new catalog struct
+ cat->db_name= new (current_thd->mem_root) String();
+ s= new (current_thd->mem_root) String();
+ s->length(0);
+ str.readstr(*s); // read db name
+ cat->db_name->length(0);
+ cat->db_name->append(s->c_ptr()); // save the database name
+ num_db_strings= 0;
+ res= str.read2int(num_db_strings); // read # db metadata strings
+ TEST_RD_RES(res);
+ for (uint j= 0; j < num_db_strings; j++)
+ {
+ s= new (current_thd->mem_root) String();
+ s->length(0);
+ res= str.readstr(*s); // read db metadata string
+ TEST_RD_RES(res);
+ cat->db_metadata.push_back(s);
+ }
+ num_tables= 0;
+ res= str.read2int(num_tables); // read # tables to read
+ TEST_RD_RES(res);
+ res= str.next_chunk();
+ for (uint j= 0; j < num_tables; j++)
+ {
+ s= new (current_thd->mem_root) String();
+ s->length(0);
+ res= str.readstr(*s); // read table name
+ TEST_RD_RES(res);
+ ti= new table_info();
+ ti->table_name= new (current_thd->mem_root) String();
+ ti->table_name->length(0);
+ ti->table_name->append(*s);
+ num_table_strings= 0;
+ res= str.read2int(num_table_strings); // read # table metadata strings
+ TEST_RD_RES(res);
+ for (uint k= 0; k < num_table_strings; k++)
+ {
+ s= new (current_thd->mem_root) String();
+ s->length(0);
+ res= str.readstr(*s); // read table metadata string
+ TEST_RD_RES(res);
+ ti->table_metadata.push_back(s);
+ }
+ res= str.next_chunk();
+ cat->tables.push_back(ti);
+ }
+ info.catalog.push_back(cat); // add db data to catalog
+ }
+
// read list of tables
List_iterator<Restore_subimage> it(info.images);
@@ -91,6 +265,9 @@
DBUG_PRINT("restore",("catalog read"));
+ if( ino == 0 || res != stream_result::OK )
+ DBUG_RETURN(res == stream_result::OK);
+
DBUG_RETURN(TRUE);
}
@@ -218,189 +395,349 @@
***********************************************************/
-bool get_create_stmt(THD*,TABLE_LIST*,String&);
-
-bool write_table_definitions(THD *thd, const Backup_info &info, OStream &s)
-{
- DBUG_ENTER("backup::write_table_definitions");
- DBUG_ASSERT(thd);
-
- List_iterator<Backup_subimage> it(const_cast< List<Backup_subimage>&
>(info.images));
- Backup_subimage *img;
-
- while ( (img= it++) )
- {
- TABLE_LIST *tl= build_table_list(img->tables,TL_READ);
-
- DBUG_PRINT("backup", ( "calling open_and_lock_tables" ));
-
- if ( ::open_and_lock_tables(thd, tl) )
- {
- DBUG_PRINT("backup", ( "error!" ));
- DBUG_RETURN(FALSE);
- }
-
- DBUG_PRINT("backup", ( "saving table defs" ));
- stream_result::value res;
-
- TABLE_LIST *ptr= tl;
-
- while (ptr)
- {
- String create_statement;
- DBUG_ASSERT(!get_create_stmt(thd,ptr,create_statement));
-
- ptr= tl->next_global;
- // free memory? (it is allocated using sql_alloc)
- tl= ptr;
-
- res= s.writestr(create_statement);
- TEST_WR_RES(res);
- }
-
- s.end_chunk();
-
- DBUG_PRINT("backup",("Table defs written, closing tables"));
- ::close_thread_tables(thd,FALSE,TRUE);
-
- } // sub-image loop
-
-
- DBUG_PRINT("backup",("All table definitions written"));
+/*
+ Get the metadata for the table specified.
- DBUG_RETURN(TRUE);
-}
+ SYNOPSIS
+ get_table_metadata()
+ THD *thd - The current thread instance.
+ TABLE_LIST *tbl - The list of tables.
+ List<String> - A string list for storing the SQL strings.
-/// Execute SQL query without sending anything to client.
+ DESCRIPTION
+ This procedure loads the string list with the SQL statements for
+ creating the table and all of the triggers associated with it.
-bool silent_exec_query(THD*, String&);
+ NOTES
+ Method is designed to process one table at a time thereby only
+ locking one table at a time.
-bool create_all_tables(THD *thd, const Restore_info &info, IStream &s)
+ RETURNS
+ 0 - no errors.
+ -1 - error reading table or trigger metadata
+*/
+bool get_table_metadata(THD *thd, TABLE_LIST *table,
+ List<String> *buffer)
{
- DBUG_ENTER("restore::create_all_tables");
- DBUG_ASSERT(thd);
+ String *tbl_sql;
- int err;
- List_iterator<Restore_subimage> it(const_cast<
List<Restore_subimage>& >(info.images));
- Restore_subimage *img;
-
- while ( (img= it++) ) // loop over sub-images
+ DBUG_ENTER("get_table_metadata");
+ /*
+ Check to see if tables exist and open them. Abort if
+ something is wrong or tables cannot be locked.
+ */
+ table->lock_type= TL_READ;
+ DBUG_PRINT("metadata_backup", ("opening the tables"));
+ if (open_and_lock_tables(thd, table))
{
- uint tno= img->tables.count();
- DBUG_PRINT("restore",("Creating %d tables forom %s image",tno,img->name()));
-
- TABLE_LIST *tl= build_table_list(img->tables,TL_READ);
-
- // remove tables which exist
-
- err= mysql_rm_table_part2_with_lock(thd, tl, TRUE, FALSE, TRUE); // = DROP TABLE IF
EXISTS
- DBUG_PRINT("restore",(" drop tables result= %d",err));
-
- DBUG_ASSERT( err == 0 );
-
- // create tables
+ DBUG_PRINT("metadata_backup", ( "error opening tables!" ));
+ DBUG_RETURN(-1);
+ }
- String create_statement;
- stream_result::value res;
+ tbl_sql= new (current_thd->mem_root) String();
+ 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);
+ insert_db_in_create(table, tbl_sql); // patch SQL statement
+ DBUG_PRINT("metadata_backup", ("query size = %d", tbl_sql->length()));
+ DBUG_PRINT("metadata_backup", ("query = %s", tbl_sql->c_ptr()));
+ buffer->push_back(tbl_sql);
- while ((res= s.readstr(create_statement)) == stream_result::OK)
+ /*
+ 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++)
{
- // execute the statement
-
- bool res= silent_exec_query(thd,create_statement);
- DBUG_PRINT("restore",(" res=%d after executing %s",res,create_statement.c_ptr()));
-
- if (!res)
- DBUG_RETURN(res);
+ 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= new (current_thd->mem_root) String();
+ 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(table->db);
+ tbl_sql->append(".");
+ tbl_sql->append(table->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.
+ */
+ DBUG_PRINT("metadata_backup", ("trg query size = %d",
+ tbl_sql->length()));
+ DBUG_PRINT("metadata_backup", ("trg query = %s", tbl_sql->c_ptr()));
+ buffer->push_back(tbl_sql);
+ }
+ /*
+ Skip this trigger if it isn't for this table.
+ */
+ else
+ continue;
+ }
}
-
- DBUG_ASSERT(res==stream_result::EOC);
- s.next_chunk();
-
- } // sub-image loop
-
- DBUG_PRINT("restore",("All tables created"));
-
- DBUG_RETURN(TRUE);
+ }
+ /*
+ 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;
+ }
+ DBUG_RETURN(0);
}
-/**
- Produce a CREATE TABLE statement corresponding to a given table.
-
- @note The statement uses qualified table name (<db name>.<table>) so
- that it works correctly regardless of the current database.
+/*
+ Get the metadata for the database specified.
- @param tbl (in) open TABLE_LIST structure for the table
- @param s (out) String where the statement is stored.
+ SYNOPSIS
+ get_db_metadata()
+ THD *thd - The current thread instance.
+ char *db - The name of the database.
+ List<String> - A string list for storing the SQL strings.
- @returns TRUE if there were errors, FALSE otherwise.
- */
+ DESCRIPTION
+ This procedure loads the string list with the SQL statements for
+ creating the database and all of the stored procedures and
+ functions associated with it.
-bool get_create_stmt(THD *thd, TABLE_LIST *tbl, String &s)
+ RETURNS
+ 0 - no errors.
+ -1 - database cannot be read or doesn't exist.
+*/
+bool get_db_metadata(THD *thd, const char *db,
+ List<String> *buffer)
{
- String table_name; // Buffer to store table name
- uint len; // store length of the table name
- int index= 0; // index of table name in create string
- int period= 0; // index of "." in create string
-
- DBUG_ENTER("backup::get_create_stmt");
+ TABLE *proc_table;
+ TABLE_LIST proc_tables;
+ String *db_sql;
+ String tmp;
+ LEX_STRING db_name;
+ DBUG_ENTER("get_db_metadata");
/*
- If table is NULL or the table's database name is missing,
- abort.
+ Check to see if database is valid name.
*/
- if (!tbl || !tbl->db)
+ DBUG_PRINT("metadata_backup", ("checking the database"));
+ db_name.str= thd->alloc(strlen(db) + 2);
+ db_name.length= strlen(db);
+ if (check_db_name(&db_name))
{
- DBUG_PRINT("backup", ("table or database not specified: "));
- DBUG_RETURN(TRUE);
+ DBUG_PRINT("metadata_backup", ("error with database name"));
+ DBUG_RETURN(-1);
}
- bool res= store_create_info(thd,tbl,&s,NULL);
-
- if (res)
- DBUG_RETURN(TRUE);
-
/*
- Aparrently, it is not possible to make the store_create_info() function
- produce a CREATE TABLE statement with qualified table names.
-
- Therefore we modify the returned statement replacing table name with the
- qualified one.
+ Write the CREATE statement.
*/
-
- table_name.length(0);
- table_name.append(tbl->table_name);
- len= table_name.length();
- index= s.strstr(table_name); // locate table name in the statement
-
- table_name.set_ascii(".",1);
- period= s.strstr(table_name); // to check if db name is already there
+ db_sql= new (current_thd->mem_root) String();
+ db_sql->length(0);
+ db_sql->append("CREATE DATABASE IF NOT EXISTS ");
+ db_sql->append(db);
+ buffer->push_back(db_sql);
/*
- If the table name isn't found in the string or if a period appears
- in the string before the table name (indicating the db.table is
- already in there), abort.
+ Setup a new table list that contains the proc table.
*/
- if (!index || ((period > 0) && (period < index)))
+ 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("backup", ("table name not found in string!"));
- DBUG_RETURN(TRUE);
+ DBUG_PRINT("metadata_backup", ("error with proc table"));
+ DBUG_RETURN(-1);
}
- table_name.length(0);
- table_name.append(tbl->db);
- table_name.append("`.`");
- table_name.append(tbl->table_name);
-
/*
- Insert the database.table string at the location
- of the table name in the CREATE command.
+ Loop through all of the results in the proc table.
+ Construct the CREATE PROCEDURE and CREATE FUNCTION SQL commands
+ for this database.
*/
- DBUG_PRINT("backup", ("inserting database %s into %s",
- table_name.c_ptr() , s.c_ptr()));
- DBUG_RETURN(s.replace(index, len, table_name));
+ 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);
+ }
+ DBUG_PRINT("metadata_backup", ("db query = %s", db_sql->c_ptr()));
+ buffer->push_back(db_sql);
+ }
+ }
+ DBUG_PRINT("metadata_backup", ("closing the proc table"));
+ proc_table->file->ha_index_end();
+ close_proc_table(thd, &open_tables_state_backup);
+ DBUG_RETURN(0);
}
+/// Execute SQL query without sending anything to client.
+
+bool silent_exec_query(THD*, String&);
+
+/*
+ Use the catalog read to get the metadata for the databases
+ in the archive and execute them.
+
+ SYNOPSIS
+ restore_metadata()
+ THD *thd - The current thread instance.
+ Restore_info info - Restore information.
+
+ DESCRIPTION
+ This procedure iterates through the catalog and executes
+ the metadata strings for each database and table in the
+ catalog.
+
+ NOTES
+ - Algorithm:
+ For each database, drop the db then execute SQL strings
+ For each table in table_info, execute SQL strings
+ - Currently processes all databases and tables in the catalog.
+
+ RETURNS
+ 0 - no errors.
+ -1 - error on execute SQL string.
+*/
+bool restore_metadata(THD *thd, const Restore_info &info)
+{
+ String sql;
+ schema_ref *tmp;
+
+ DBUG_ENTER("restore::restore_metadata");
+ DBUG_ASSERT(thd);
+
+ List<schema_ref> cat= info.catalog;
+ List_iterator<schema_ref> catalog(cat);
+ while ((tmp= catalog++))
+ {
+ /*
+ DROP DATABASE: Execute the DROP DATABASE IF EXISTS
+ */
+ sql.length(0);
+ sql.append("DROP DATABASE IF EXISTS ");
+ sql.append(tmp->db_name->c_ptr());
+ bool res= silent_exec_query(thd, sql);
+ DBUG_PRINT("restore",(" res=%d after executing %s", res, sql.c_ptr()));
+
+ /*
+ Run the DB metadata strings
+ */
+ String *dbstr;
+ List_iterator<String> db_meta(tmp->db_metadata);
+ while ((dbstr= db_meta++))
+ {
+ bool res= silent_exec_query(thd, *dbstr);
+ DBUG_PRINT("restore",(" res=%d after executing %s", res, dbstr->c_ptr()));
+ }
+ table_info *t;
+ List_iterator<table_info> tbls(tmp->tables);
+ while ((t= tbls++))
+ {
+ /*
+ Run the table metadata strings
+ */
+ String *s;
+ List_iterator<String> tbl_meta(t->table_metadata);
+ while ((s= tbl_meta++))
+ {
+ bool res= silent_exec_query(thd, *s);
+ DBUG_PRINT("restore",(" res=%d after executing %s", res, s->c_ptr()));
+ }
+ }
+ }
+
+ DBUG_PRINT("backup",("databases dropped then created"));
+ DBUG_PRINT("backup",("tables created"));
+ DBUG_RETURN(TRUE);
+}
// Change net.vio idea taken from execute_init_command in sql_parse.cc
--- 1.1/sql/backup/tables.cc 2007-04-10 16:06:37 -04:00
+++ 1.2/sql/backup/tables.cc 2007-04-10 16:06:37 -04:00
@@ -155,6 +155,26 @@
return tl;
}
+TABLE_LIST *build_table_list_str(char *name, char *db, thr_lock_type lock)
+{
+ TABLE_LIST *tl= NULL;
+
+ TABLE_LIST *ptr= (TABLE_LIST*)sql_alloc(sizeof(TABLE_LIST));
+ DBUG_ASSERT(ptr);
+ bzero(ptr,sizeof(TABLE_LIST));
+
+ ptr->alias= ptr->table_name= const_cast<char*>(name);
+ ptr->db= const_cast<char*>(db);
+ ptr->lock_type= lock;
+
+ // and add it to the list
+
+ ptr->next_global= ptr->next_local=
+ ptr->next_name_resolution_table= tl;
+ tl= ptr;
+// tl->table= ptr->table;
+ return tl;
+}
} // backup namespace
--- 1.1/sql/backup/tables.h 2007-04-10 16:06:37 -04:00
+++ 1.2/sql/backup/tables.h 2007-04-10 16:06:37 -04:00
@@ -53,7 +53,7 @@
};
TABLE_LIST *build_table_list(const Table_list&, thr_lock_type);
-
+TABLE_LIST *build_table_list_str(char *name, char *db, thr_lock_type lock);
// Table_ref implementation which gets table identity from a filled record
// of I_S.TABLES table.
| Thread |
|---|
| • bk commit into 5.1 tree (cbell:1.2505) | cbell | 10 Apr |