MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Ingo Struewing Date:October 29 2008 3:25pm
Subject:bzr commit into mysql-6.0 branch (ingo.struewing:2717) WL#4534
View as plain text  
#At file:///home2/mydev/bzrroot/mysql-6.0-wl4534-3/

 2717 Ingo Struewing	2008-10-29
      WL#4534 - Backup client program
      
      Fifth prototype for final design review.
      
      This is based on the fourth prototype.
      Changes over fourth prototype:
      Reading of compressed backup images
      Improved error reporting
      Slightly changed output format
      
      This is a complete prototype for milestone 1.
      It does have command line options (find them with --help).
      Sizes are printed in human readable form by default.
      It has search functionality (see --search option in --help).
      
      Basic test cases are provided.
added:
  client/backup_stream.c
  client/backup_stream.h
  client/mysqlbackup.cc
  mysql-test/suite/backup/r/backup_client.result
  mysql-test/suite/backup/r/backup_client_binlog.result
  mysql-test/suite/backup/t/backup_client.test
  mysql-test/suite/backup/t/backup_client_binlog.test
modified:
  .bzrignore
  client/Makefile.am
  mysql-test/mysql-test-run.pl

per-file messages:
  .bzrignore
    WL#4534 - Backup client program
    Added mysqlbackup related files.
  client/Makefile.am
    WL#4534 - Backup client program
    Added mysqlbackup client build requirements.
  client/backup_stream.c
    WL#4534 - Backup client program
    Backup stream reader.
  client/backup_stream.h
    WL#4534 - Backup client program
    Backup stream reader declarations.
  client/mysqlbackup.cc
    WL#4534 - Backup client program
    The new mysqlbackup program.
  mysql-test/mysql-test-run.pl
    WL#4534 - Backup client program
    Added mysqlbackup client to the list of environment variables.
  mysql-test/suite/backup/r/backup_client.result
    WL#4534 - Backup client program
    Test result.
  mysql-test/suite/backup/r/backup_client_binlog.result
    WL#4534 - Backup client program
    Test result.
  mysql-test/suite/backup/t/backup_client.test
    WL#4534 - Backup client program
    New test case.
  mysql-test/suite/backup/t/backup_client_binlog.test
    WL#4534 - Backup client program
    New test case.
=== modified file '.bzrignore'
--- a/.bzrignore	2008-10-01 12:02:28 +0000
+++ b/.bzrignore	2008-10-29 15:25:00 +0000
@@ -1898,3 +1898,6 @@ mysql-test/tps.log
 libmysqld/event_parse_data.cc
 client/transaction.h
 libmysqld/transaction.cc
+client/mysqlbackup
+client/stream_v1.h
+client/stream_v1_services.h

=== modified file 'client/Makefile.am'
--- a/client/Makefile.am	2008-09-04 18:30:34 +0000
+++ b/client/Makefile.am	2008-10-29 15:25:00 +0000
@@ -42,6 +42,7 @@ CLEANFILES =			$(BUILT_SOURCES)
 
 bin_PROGRAMS =			mysql \
 				mysqladmin \
+				mysqlbackup \
 				mysqlbinlog \
 				mysqlcheck \
 				mysqldump \
@@ -57,6 +58,12 @@ mysql_LDADD =			@readline_link@ @TERMCAP
 				$(LDADD) $(CXXLDFLAGS)
 mysqladmin_SOURCES =		mysqladmin.cc
 
+mysqlbackup_SOURCES =		mysqlbackup.cc \
+				backup_stream.c \
+				$(top_srcdir)/sql/backup/stream_v1.c \
+				$(top_srcdir)/sql/backup/stream_v1_transport.c
+mysqlbackup_LDADD =		$(LDADD) $(CXXLDFLAGS)
+
 mysqlbinlog_SOURCES =		mysqlbinlog.cc \
 				$(top_srcdir)/mysys/mf_tempdir.c \
 				$(top_srcdir)/mysys/my_new.cc \
@@ -110,6 +117,7 @@ sql_src=log_event.h mysql_priv.h rpl_con
 	rpl_record_old.h rpl_record_old.cc \
 	transaction.h
 strings_src=decimal.c dtoa.c
+backup_src=stream_v1.h stream_v1_services.h
 
 link_sources:
 	for f in $(sql_src) ; do \
@@ -120,6 +128,10 @@ link_sources:
 	  rm -f $(srcdir)/$$f; \
 	  @LN_CP_F@ $(top_srcdir)/strings/$$f $$f; \
 	done; \
+	for f in $(backup_src) ; do \
+	  rm -f $(srcdir)/$$f; \
+	  @LN_CP_F@ $(top_srcdir)/sql/backup/$$f $$f; \
+	done; \
 	rm -f $(srcdir)/my_user.c; \
 	@LN_CP_F@ $(top_srcdir)/sql-common/my_user.c my_user.c;
 	echo timestamp > link_sources;

=== added file 'client/backup_stream.c'
--- a/client/backup_stream.c	1970-01-01 00:00:00 +0000
+++ b/client/backup_stream.c	2008-10-29 15:25:00 +0000
@@ -0,0 +1,2446 @@
+/* Copyright (C) 2008 Sun Microsystems Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/*
+  MySQL Backup Image Stream reading
+*/
+
+#include "backup_stream.h"
+
+/* MY_STAT */
+#include "my_dir.h"
+/* fprintf, stderr */
+#include <stdio.h>
+/* strerror, memcmp */
+#include <string.h>
+#ifdef HAVE_COMPRESS
+/* zlib functions */
+#include <zlib.h>
+#endif
+
+#ifdef HAVE_COMPRESS
+#define ZBUF_SIZE 65536 // compression I/O buffer size
+#endif
+
+/*
+  ====================================================
+  Convenience functions for access to st_blob objects.
+  ====================================================
+*/
+
+/**
+  Backup blob length.
+
+  This is a function, not a macro, for better type checking.
+
+  @param[in]    blob            blob
+
+  @return       length
+*/
+
+ulong BBL(struct st_blob *blob)
+{
+  DBUG_ASSERT(blob);
+  DBUG_ASSERT(blob->end >= blob->begin);
+  return ((ulong) (blob->end - blob->begin));
+}
+
+
+/**
+  Backup blob string.
+
+  This is a function, not a macro, for better type checking.
+
+  @param[in]    blob            blob
+
+  @return       string
+*/
+
+char *BBS(struct st_blob *blob)
+{
+  DBUG_ASSERT(blob);
+  DBUG_ASSERT(blob->end >= blob->begin);
+  return ((char*) blob->begin);
+}
+
+
+/*
+  ====================================================
+  Memory allocation.
+  These are callback functions for the stream library.
+  ====================================================
+*/
+
+/**
+  Allocate given amount of memory and return pointer to it.
+
+  @param[in]    size            amount of memory to allocate
+
+  @return       pointer to allocated memory
+*/
+
+bstream_byte* bstream_alloc(unsigned long int size)
+{
+  return my_malloc(size, MYF(MY_WME));
+}
+
+
+/**
+  Free previously allocated memory.
+
+  @param[in]    ptr             pointer to allocated memory
+*/
+
+void bstream_free(bstream_byte *ptr)
+{
+  my_free(ptr, MYF(MY_ALLOW_ZERO_PTR));
+}
+
+
+/*
+  ====================================================
+  Helper functions for the stream library.
+  These are callback functions for the stream library.
+  Low-level stream access.
+  ====================================================
+*/
+
+/*
+  Helper struct for stream access functions.
+
+  The stream access functions do not read the backup image file
+  directly. They call back functions provided in st_backup_stream by the
+  application.
+
+  The struct st_stream ties together the st_backup_stream
+  with the data required by the I/O functions provided by this
+  application. Note that 'st_backup_stream' must be the first part of
+  the helper struct.
+
+  'stream_pos' is used to describe which section/chunk of a backup
+  image we have read last.
+*/
+struct st_stream
+{
+  struct st_backup_stream       bupstrm;        /* Must be first in st_stream */
+  File                          fd;             /* File descriptor */
+  my_off_t                      pos;            /* Byte position in file */
+  my_off_t                      size;           /* File size */
+  const char                    *path;          /* File name */
+  const char                    *stream_pos;    /* Verbal stream position */
+  const char                    *zalgo;         /* Compression algorithm */
+#ifdef HAVE_COMPRESS
+  uchar                         *zbuf;          /* Buffer for compressed data */
+  z_stream                      zstream;        /* zlib helper struct */
+#endif
+};
+
+
+/**
+  Read from the stream/image.
+
+  @param[in,out]    strm        stream handle, updating position
+  @param[in,out]    data        data container, updating contents and ptrs
+  @param            envelope    not used
+
+  @return       status
+    @retval     BSTREAM_OK      ok
+    @retval     BSTREAM_EOS     end of stream
+    @retval     otherwise       error
+
+  @note The return value is specified as 'int' in stream_v1.h
+  though only values from enum_bstream_ret_codes are expected.
+*/
+
+static int
+str_read(struct st_stream *strm, struct st_blob *data,
+         struct st_blob envelope __attribute__((unused)))
+{
+  size_t        lgt;
+  int           rc= BSTREAM_OK;
+  DBUG_ENTER("str_read");
+  DBUG_ASSERT(strm && strm->path);
+  DBUG_ASSERT(data && data->begin && data->end);
+
+  /*
+    Compute wanted length.
+  */
+  lgt= BBL(data);
+  DBUG_PRINT("bupstrm", ("want bytes: %lu", (ulong) lgt));
+
+  /*
+    Read.
+  */
+#ifdef HAVE_COMPRESS
+  if (strm->zbuf)
+  {
+    int zerr;
+    z_stream *zstream= &strm->zstream;
+
+    /* Set output buffer pointer and size. */
+    zstream->next_out= data->begin;
+    /*
+      Zstream can process in one go a block whose size fits into uInt
+      type. If we have more space available in the buffer, we ignore the
+      extra bytes.
+    */
+    if (lgt > ~((uInt)0))
+      lgt= ~((uInt)0);
+    zstream->avail_out= (uInt) lgt;
+
+    lgt= 0; /* In case zbuf is empty and we are at EOF. */
+    do
+    {
+      /* If input buffer is empty, load data from compressed image. */
+      if (!zstream->avail_in)
+      {
+        zstream->avail_in= (uInt) my_read(strm->fd, strm->zbuf, ZBUF_SIZE,
+                                           MYF(0));
+        if (zstream->avail_in == (uInt) MY_FILE_ERROR)
+        {
+          fprintf(stderr, "ERROR: cannot read compressed image '%s': %s\n",
+                  strm->path, strerror(my_errno));
+          rc= BSTREAM_ERROR;
+          goto end;
+        }
+        else if (!zstream->avail_in)
+        {
+          /* EOF. If first read, we leave with lgt == 0 here. */
+          break;
+        }
+        zstream->next_in= strm->zbuf;
+      }
+      /* Decompress, */
+      zerr= inflate(zstream, Z_NO_FLUSH);
+      /* Set output length. */
+      lgt= zstream->next_out - data->begin;
+      if (zerr == Z_STREAM_END)
+      {
+        /* EOF. If first decompress, we leave with lgt == 0 here. */
+        break;
+      }
+      else if (zerr != Z_OK)
+      {
+        fprintf(stderr, "ERROR: cannot decompress image '%s': %d: %s\n",
+                strm->path, zerr, zstream->msg);
+        rc= BSTREAM_ERROR;
+        goto end;
+      }
+    } while (zstream->avail_out);
+    /* lgt contains the number of bytes decompressed. */
+  }
+  else
+#endif
+  {
+    lgt= my_read(strm->fd, data->begin, lgt, MYF(0));
+    if (lgt == MY_FILE_ERROR)
+    {
+      fprintf(stderr, "ERROR: cannot read image '%s': %s\n",
+              strm->path, strerror(my_errno));
+      rc= BSTREAM_ERROR;
+      goto end;
+    }
+  }
+  DBUG_PRINT("bupstrm", ("read bytes: %lu", (ulong) lgt));
+
+  /*
+    Check for end of stream.
+  */
+  if (lgt == 0)
+  {
+    rc= BSTREAM_EOS;
+    goto end;
+  }
+
+  /*
+    Update stream handle and data container.
+  */
+  strm->pos+= lgt;
+  data->begin+= lgt;
+
+ end:
+  DBUG_RETURN(rc);
+}
+
+
+/**
+  Skip part of the stream/image.
+
+  @param[in,out]    strm        stream handle, updating position
+  @param[in,out]    len         number of bytes to skip, skipped
+
+  @return       status
+    @retval     BSTREAM_OK      ok
+    @retval     otherwise       error
+
+  @note The return value is specified as 'int' in stream_v1.h
+  though only values from enum_bstream_ret_codes are expected.
+*/
+
+static int
+str_forward(struct st_stream *strm, size_t *len)
+{
+  int           rc= BSTREAM_OK;
+  DBUG_ENTER("str_forward");
+  DBUG_ASSERT(strm && strm->path);
+  DBUG_ASSERT(len);
+
+#ifdef HAVE_COMPRESS
+  if (strm->zbuf)
+  {
+    /* Need to read *len bytes from decompressed stream. */
+    z_stream    *zstream= &strm->zstream;
+    size_t      lgt= *len;
+    int         zerr;
+    uchar       iobuff[IO_SIZE];
+
+    /*
+      Zstream can process in one go a block whose size fits into uInt
+      type. If we have more space available in the buffer, we ignore
+      the extra bytes.
+    */
+    DBUG_ASSERT(IO_SIZE <= ~((uInt)0));
+
+    do
+    {
+      /* Set output buffer pointer and size. */
+      zstream->next_out= iobuff;
+      if (lgt > IO_SIZE)
+        zstream->avail_out= IO_SIZE;
+      else
+        zstream->avail_out= (uInt) lgt;
+
+      /* If input buffer is empty, load data from compressed image. */
+      if (!zstream->avail_in)
+      {
+        zstream->avail_in= (uInt) my_read(strm->fd, strm->zbuf, ZBUF_SIZE,
+                                          MYF(0));
+        if (zstream->avail_in == (uInt) MY_FILE_ERROR)
+        {
+          fprintf(stderr, "ERROR: cannot read compressed image '%s': %s\n",
+                  strm->path, strerror(my_errno));
+          rc= BSTREAM_ERROR;
+          goto end;
+        }
+        else if (!zstream->avail_in)
+        {
+          /* EOF. This is an error on seek. */
+          fprintf(stderr, "ERROR: end of stream in seek on image '%s'\n",
+                  strm->path);
+          rc= BSTREAM_EOS;
+          goto end;
+        }
+        zstream->next_in= strm->zbuf;
+      }
+      /* Decompress, */
+      zerr= inflate(zstream, Z_NO_FLUSH);
+      /* Reduce wanted length by what we got. */
+      lgt-= zstream->next_out - iobuff;
+      if (zerr == Z_STREAM_END)
+      {
+        /* EOF. This is an error on seek. */
+        fprintf(stderr, "ERROR: end of stream in seek on image '%s'\n",
+                strm->path);
+        rc= BSTREAM_EOS;
+        goto end;
+      }
+      else if (zerr != Z_OK)
+      {
+        fprintf(stderr, "ERROR: cannot decompress image '%s': %d: %s\n",
+                strm->path, zerr, zstream->msg);
+        rc= BSTREAM_ERROR;
+        goto end;
+      }
+    } while (lgt);
+
+    /* Remember current file position. */
+    strm->pos+= *len;
+  }
+  else
+#endif
+  {
+    my_off_t      off_new;
+
+#if !defined(DBUG_OFF)
+    /*
+      Check if internal counter matches real file position.
+    */
+    my_off_t off_cur= my_seek(strm->fd, (my_off_t) 0, SEEK_CUR, MYF(0));
+    if (off_new == MY_FILEPOS_ERROR)
+    {
+      fprintf(stderr, "ERROR: cannot seek in image '%s': %s\n",
+              strm->path, strerror(my_errno));
+      rc= BSTREAM_ERROR;
+      goto end;
+    }
+    DBUG_ASSERT(off_cur == strm->pos);
+#endif
+
+    /*
+      Advance file pointer by *len bytes.
+    */
+    off_new= my_seek(strm->fd, (my_off_t) *len, SEEK_CUR, MYF(0));
+    if (off_new == MY_FILEPOS_ERROR)
+    {
+      fprintf(stderr, "ERROR: cannot seek in image '%s': %s\n",
+              strm->path, strerror(my_errno));
+      rc= BSTREAM_ERROR;
+      goto end;
+    }
+
+    /* Compute actual skip length from old and new file positions. */
+    *len= off_new - strm->pos;
+    /* Remember current file position. */
+    strm->pos= off_new;
+  }
+
+ end:
+  DBUG_RETURN(rc);
+}
+
+/**
+  Open the stream/image for reading.
+
+  A backup stream has a prefix, consisting of 8 bytes magic number
+  and 2 bytes version number.
+
+  TODO A compressed image has a gzip magic number.
+  TODO An encrypted image has yet another magic number.
+
+  @param[in,out]    strm        stream handle, updating path, fd, bupstrm
+  @param[in]        path        image path name
+  @param[out]       version_p   detected image version
+
+  @return       status
+    @retval     BSTREAM_OK      ok
+    @retval     otherwise       error
+
+  @note The return value is specified as 'int' in stream_v1.h
+  though only values from enum_bstream_ret_codes are expected.
+*/
+
+static int
+str_open_rd(struct st_stream *strm, const char *path, uint *version_p)
+{
+  MY_STAT               stat_area;
+  size_t                lgt;
+  int                   rc= BSTREAM_OK;
+  int                   errpos= 0;
+  uint16                version;
+  const unsigned char   backup_magic_bytes[8]=
+    {
+      0xE0, // ###.....
+      0xF8, // #####...
+      0x7F, // .#######
+      0x7E, // .######.
+      0x7E, // .######.
+      0x5F, // .#.#####
+      0x0F, // ....####
+      0x03  // ......##
+    };
+#ifdef HAVE_COMPRESS
+  const unsigned char   gzip_magic_bytes[3]=
+    {
+      0x1f,
+      0x8b,
+      0x08
+    };
+#endif
+  uchar  prefix[sizeof(backup_magic_bytes) + sizeof(version)];
+  DBUG_ENTER("str_open_rd");
+  DBUG_ASSERT(strm);
+  DBUG_ASSERT(path);
+  DBUG_ASSERT(version_p);
+
+  /*
+    Initialize stream struct.
+  */
+  bzero(strm, sizeof(*strm));
+
+  /*
+    Set image path name.
+  */
+  strm->path= path;
+  DBUG_PRINT("bupstrm", ("opening image file: '%s'", strm->path));
+
+  /*
+    Open the image file.
+  */
+  strm->fd= my_open(strm->path, O_RDONLY, MYF(0));
+  if (strm->fd < 0)
+  {
+    fprintf(stderr, "ERROR: cannot open backup image '%s': %s\n",
+            strm->path, strerror(my_errno));
+    goto err;
+  }
+  errpos= 10;
+  DBUG_PRINT("bupstrm", ("opened  image file: '%s'  fd: %d",
+                         strm->path, strm->fd));
+
+  if (my_fstat(strm->fd, &stat_area, MYF(0)))
+  {
+    fprintf(stderr, "ERROR: cannot fstat open backup image '%s': %s\n",
+            strm->path, strerror(my_errno));
+    goto err;
+  }
+  strm->size= stat_area.st_size;
+
+  /*
+    Read prefix with magic number and image version.
+  */
+  lgt= my_read(strm->fd, prefix, sizeof(prefix), MYF(0));
+  if (lgt != sizeof(prefix))
+  {
+    if (lgt == MY_FILE_ERROR)
+      fprintf(stderr, "ERROR: cannot read image '%s': %s\n",
+              strm->path, strerror(my_errno));
+    else
+      fprintf(stderr, "ERROR: image file has only %lu bytes of at least %lu\n",
+              (ulong) lgt, (ulong) sizeof(prefix));
+    goto err;
+  }
+  DBUG_PRINT("bupstrm", ("read magic number and version"));
+
+#ifdef HAVE_COMPRESS
+  /*
+    Check for compression.
+  */
+  if (!memcmp(prefix, gzip_magic_bytes, sizeof(gzip_magic_bytes)))
+  {
+    int                 zerr;
+    bstream_blob        blob;
+
+    if (!(strm->zbuf= (uchar*) my_malloc(ZBUF_SIZE, MYF(MY_WME))))
+    {
+      /* Error message sent by my_malloc(). */
+      goto err;
+    }
+    errpos= 20;
+    strm->zstream.zalloc= 0;
+    strm->zstream.zfree= 0;
+    strm->zstream.opaque= 0;
+    strm->zstream.msg= 0;
+    strm->zstream.next_in= strm->zbuf;
+    strm->zstream.avail_in= 10;
+    memcpy(strm->zbuf, prefix, 10);
+
+    if ((zerr= inflateInit2(&strm->zstream, MAX_WBITS + 16)) != Z_OK)
+    {
+      fprintf(stderr, "ERROR: cannot init zlib on image '%s': %d: %s\n",
+              strm->path, zerr, strm->zstream.msg);
+      goto err;
+    }
+    errpos= 30;
+
+    blob.begin= prefix;
+    blob.end= prefix + sizeof(prefix);
+    if (str_read(strm, &blob, blob) != BSTREAM_OK ||
+        blob.begin != blob.end)
+    {
+      /* Error message sent by str_read(). */
+      goto err;
+    }
+    strm->zalgo= "gzip";
+  }
+  else
+#endif
+    strm->zalgo= "none";
+
+  /*
+    Check magic number and image version.
+  */
+  if (memcmp(prefix, backup_magic_bytes, sizeof(backup_magic_bytes)))
+  {
+    fprintf(stderr, "ERROR: not a backup image file: '%s'. "
+            "Magic number mismatch.\n",
+            strm->path);
+    goto err;
+  }
+  version= uint2korr(prefix+8);
+  if (version != 1)
+  {
+    fprintf(stderr, "ERROR: backup image version %u is not supported\n",
+            version);
+    goto err;
+  }
+  *version_p= version;
+
+  /*
+    Set callback functions in struct st_backup_stream.
+  */
+  strm->bupstrm.stream.write=   (as_write_m) NULL;
+  strm->bupstrm.stream.read=    (as_read_m) str_read;
+  strm->bupstrm.stream.forward= (as_forward_m) str_forward;
+
+  /*
+    Open the stream.
+  */
+  DBUG_PRINT("bupstrm", ("opening stream: '%s'  fd: %d", strm->path, strm->fd));
+  rc= bstream_open_rd(&strm->bupstrm, sizeof(prefix));
+  if (rc != BSTREAM_OK)
+  {
+    fprintf(stderr, "ERROR: cannot open stream library on '%s'.\n",
+            strm->path);
+    goto err;
+  }
+  DBUG_PRINT("bupstrm", ("opened  stream: '%s'  fd: %d  rc: %d",
+                         strm->path, strm->fd, rc));
+
+  goto end;
+
+err:
+  switch (errpos) {
+#ifdef HAVE_COMPRESS
+  case 30:
+    (void) inflateEnd(&strm->zstream);
+  case 20:
+    my_free(strm->zbuf, MYF(0));
+    strm->zbuf= NULL;
+#endif
+  case 10:
+    (void) my_close(strm->fd, MYF(0));
+    strm->fd= -1;
+  }
+  rc= BSTREAM_ERROR;
+
+ end:
+  DBUG_RETURN(rc);
+}
+
+
+/**
+  Close the stream/image.
+
+  @param[in]    strm            stream handle
+
+  @return       status
+    @retval     BSTREAM_OK      ok
+    @retval     otherwise       error
+
+  @note The return value is specified as 'int' in stream_v1.h
+  though only values from enum_bstream_ret_codes are expected.
+*/
+
+static int
+str_close(struct st_stream *strm)
+{
+  int rc;
+  DBUG_ENTER("str_close");
+  DBUG_ASSERT(strm && strm->path);
+
+  /* Close the stream. */
+  rc= bstream_close(&strm->bupstrm);
+  if (rc != BSTREAM_OK)
+  {
+    fprintf(stderr, "ERROR: cannot close stream library on '%s'.\n",
+            strm->path);
+  }
+
+#ifdef HAVE_COMPRESS
+  /* Close zlib. */
+  if (strm->zbuf)
+  {
+    int zerr;
+    if ((zerr= inflateEnd(&strm->zstream)) != Z_OK)
+    {
+      fprintf(stderr, "ERROR: cannot close zlib on image '%s': %d: %s\n",
+              strm->path, zerr, strm->zstream.msg);
+      rc= BSTREAM_ERROR;
+    }
+    my_free(strm->zbuf, (MYF(0)));
+    strm->zbuf= NULL;
+  }
+#endif
+
+  /* Close the image file. */
+  if (my_close(strm->fd, MYF(0)))
+  {
+    fprintf(stderr, "ERROR: cannot close image '%s': %s\n",
+            strm->path, strerror(my_errno));
+    rc= BSTREAM_ERROR;
+  }
+  strm->fd= -1;
+
+  DBUG_RETURN(rc);
+}
+
+
+/*
+  ====================================================
+  Backup image item handling.
+  These are callback functions for the stream library.
+  ====================================================
+*/
+
+/*
+  Helper struct for iterators.
+*/
+struct st_backup_iterator
+{
+  DYNAMIC_ARRAY                 *it_array;      /* Array to iterate */
+  int                           it_index;       /* Iterator value */
+  enum enum_bstream_item_type   it_type;        /* Iterator type */
+};
+
+
+/**
+  Clear catalogue and prepare it for populating with items.
+
+  @param[in]    hdr             catalog reference
+
+  @return       status
+    @retval     BSTREAM_OK      ok
+    @retval     otherwise       error
+
+  @note The return value is specified as 'int' in stream_v1.h
+  though only values from enum_bstream_ret_codes are expected.
+
+  @note This is empty because backup_catalog_allocate() initializes
+  the catalog properly.
+*/
+
+int
+bcat_reset(struct st_bstream_image_header *hdr __attribute__((unused)))
+{
+  DBUG_ENTER("bcat_reset");
+  DBUG_RETURN(BSTREAM_OK);
+}
+
+
+/**
+  Close catalogue after all items have been added to it.
+
+  This allows for finalizing operations. It is not meant for
+  deletion of the catalog. There is no "open" action. The
+  approximate counterpart to bcat_close() is bcat_reset().
+
+  @param[in]    hdr             catalog reference
+
+  @return       status
+    @retval     BSTREAM_OK      ok
+    @retval     otherwise       error
+
+  @note The return value is specified as 'int' in stream_v1.h
+  though only values from enum_bstream_ret_codes are expected.
+
+  @note This is empty because there is no finalization required.
+*/
+
+int
+bcat_close(struct st_bstream_image_header *hdr __attribute__((unused)))
+{
+  DBUG_ENTER("bcat_close");
+  DBUG_RETURN(BSTREAM_OK);
+}
+
+
+/**
+  Add item to the catalog.
+
+  For items that belong to a database, the base.db element points
+  to the databases' catalog item. The stream library evaluates
+  that pointer using an iterator provided by bcat_iterator_get().
+
+  The item name is allocated by the stream library and must be freed
+  by the application later.
+
+  @param[in,out]    hdr         catalog ref, updating catalog
+  @param[in]        item        item reference
+
+  @return       status
+    @retval     BSTREAM_OK      ok
+    @retval     otherwise       error
+
+  @note item->pos should be set to indicate position of the item in the
+  catalogue. This is a global position per item type. Items that belong
+  to a database are not numbered relative to the database.
+
+  @note The return value is specified as 'int' in stream_v1.h
+  though only values from enum_bstream_ret_codes are expected.
+
+  @note Global, per-table and per-database items can have independent
+  address spaces. Thus item belonging to a database is identified by its
+  position inside that database's item list. Similar for items belonging
+  to tables.
+*/
+
+int
+bcat_add_item(struct st_bstream_image_header *hdr,
+              struct st_bstream_item_info *item)
+{
+  struct st_backup_catalog      *bup_catalog= (struct st_backup_catalog*) hdr;
+  enum enum_bstream_ret_codes   rc= BSTREAM_OK;
+  DBUG_ENTER("bcat_add_item");
+  DBUG_ASSERT(hdr);
+  DBUG_ASSERT(item);
+  DBUG_PRINT("bupstrm", ("adding item: 0x%lx  pos: %lu  type: %d  name: '%.*s'",
+                         (long) item, item->pos, item->type,
+                         BBLS(&item->name)));
+
+  switch (item->type) {
+  case BSTREAM_IT_CHARSET:
+  {
+    struct st_backup_charset bup_charset;
+
+    /* Copy the item struct into the local struct. */
+    bup_charset.cs_item= *item;
+    /* Check consistency of array position. */
+    DBUG_ASSERT(item->pos == bup_catalog->cat_charsets.elements);
+    /* Insert into the catalog. */
+    if (insert_dynamic(&bup_catalog->cat_charsets, (uchar*) &bup_charset))
+    {
+      /* Error message reported by mysys. */
+      rc= BSTREAM_ERROR;
+      goto end;
+    }
+    DBUG_PRINT("bupstrm",
+               ("added charset: '%.*s'  item: 0x%lx", BBLS(&item->name),
+                (long) dynamic_array_ptr(&bup_catalog->cat_charsets,
+                                         bup_catalog->cat_charsets.elements
+                                         - 1)));
+    break;
+  }
+
+  case BSTREAM_IT_USER:
+  {
+    fprintf(stderr, "ERROR: backup object not yet implemented: user\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: user: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  case BSTREAM_IT_PRIVILEGE:
+  {
+    fprintf(stderr, "ERROR: backup object not yet implemented: privilege\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: privilege: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  case BSTREAM_IT_DB:
+  {
+    struct st_backup_database bup_database;
+
+    /* Copy the item struct into the local struct. */
+    bup_database.db_item= *((struct st_bstream_db_info*) item);
+    /* Initialize other elements. */
+    bzero(&bup_database.db_metadata, sizeof(bup_database.db_metadata));
+    if (my_init_dynamic_array(&bup_database.db_tables,
+                              sizeof(struct st_backup_table), 16, 16))
+    {
+      /* Error message reported by mysys. */
+      rc= BSTREAM_ERROR;
+      goto end;
+    }
+    if (my_init_dynamic_array(&bup_database.db_perdbs,
+                              sizeof(struct st_backup_perdb), 16, 16))
+    {
+      /* Error message reported by mysys. */
+      rc= BSTREAM_ERROR;
+      goto end;
+    }
+    /* Check consistency of array position. */
+    DBUG_ASSERT(item->pos == bup_catalog->cat_databases.elements);
+    /* Insert into the catalog. */
+    if (insert_dynamic(&bup_catalog->cat_databases, (uchar*) &bup_database))
+    {
+      /* Error message reported by mysys. */
+      rc= BSTREAM_ERROR;
+      goto end;
+    }
+    DBUG_PRINT("bupstrm",
+               ("added database: '%.*s'  item: 0x%lx", BBLS(&item->name),
+                (long) dynamic_array_ptr(&bup_catalog->cat_databases,
+                                         bup_catalog->cat_databases.elements
+                                         - 1)));
+    break;
+  }
+
+  case BSTREAM_IT_TABLE:
+  {
+    struct st_backup_table      bup_table;
+    struct st_backup_table      *tbl;
+    struct st_backup_database   *bup_database;
+    struct st_backup_snapshot   *snap;
+    uint                        snap_num;
+
+    /* Copy the item struct into the local struct. */
+    bup_table.tbl_item= *((struct st_bstream_table_info*) item);
+    bup_database= (struct st_backup_database*) bup_table.tbl_item.base.db;
+    DBUG_PRINT("bupstrm",
+               ("referred db item: 0x%lx  pos: %lu  type: %d  name: '%.*s'",
+                (long) bup_database, bup_database->db_item.base.pos,
+                bup_database->db_item.base.type,
+                BBLS(&bup_database->db_item.base.name)));
+    /* Initialize other elements. */
+    bzero(&bup_table.tbl_metadata, sizeof(bup_table.tbl_metadata));
+    bup_table.tbl_data_size= 0;
+    /* Insert into its database's array. */
+    if (insert_dynamic(&bup_database->db_tables, (uchar*) &bup_table))
+    {
+      /* Error message reported by mysys. */
+      rc= BSTREAM_ERROR;
+      goto end;
+    }
+    /* Get a reference to the inserted item. */
+    tbl= (struct st_backup_table*)
+      dynamic_array_ptr(&bup_database->db_tables,
+                        bup_database->db_tables.elements - 1);
+    /* Check plausibility of array position. */
+    snap_num= bup_table.tbl_item.snap_num;
+    DBUG_ASSERT(snap_num == tbl->tbl_item.snap_num);
+    DBUG_ASSERT(snap_num < bup_catalog->cat_snapshots.elements);
+    /* Get a reference to the snapshot information. */
+    snap= (struct st_backup_snapshot*)
+      dynamic_array_ptr(&bup_catalog->cat_snapshots, snap_num);
+    /*
+      Check consistency of array position.
+      Table items are not numbered per database, but per snapshot.
+    */
+    DBUG_ASSERT(item->pos == snap->snap_index_pos_to_table.elements);
+    /* Insert the reference into the snapshot's index array. */
+    if (insert_dynamic(&snap->snap_index_pos_to_table, (uchar*) &tbl))
+    {
+      /* Error message reported by mysys. */
+      rc= BSTREAM_ERROR;
+      goto end;
+    }
+    DBUG_PRINT("bupstrm",
+               ("added table: '%.*s'.'%.*s'  item: 0x%lx  snap_num: %u",
+                BBLS(&bup_database->db_item.base.name), BBLS(&item->name),
+                (long) tbl, tbl->tbl_item.snap_num));
+    break;
+  }
+
+  case BSTREAM_IT_VIEW:
+  {
+    struct st_backup_perdb      bup_perdb;
+    struct st_backup_database   *bup_database;
+
+    /* Copy the item struct into the local struct. */
+    bup_perdb.perdb_item= *((struct st_bstream_dbitem_info*) item);
+    bup_database= (struct st_backup_database*) bup_perdb.perdb_item.db;
+    DBUG_PRINT("bupstrm",
+               ("referred db item: 0x%lx  pos: %lu  type: %d  name: '%.*s'",
+                (long) bup_database, bup_database->db_item.base.pos,
+                bup_database->db_item.base.type,
+                BBLS(&bup_database->db_item.base.name)));
+    /* Initialize other elements. */
+    bzero(&bup_perdb.perdb_metadata, sizeof(bup_perdb.perdb_metadata));
+    /* Check consistency of array position. */
+    DBUG_ASSERT(item->pos == bup_database->db_perdbs.elements);
+    /* Insert into its database's array. */
+    if (insert_dynamic(&bup_database->db_perdbs, (uchar*) &bup_perdb))
+    {
+      /* Error message reported by mysys. */
+      rc= BSTREAM_ERROR;
+      goto end;
+    }
+    DBUG_PRINT("bupstrm",
+               ("added view: '%.*s'.'%.*s'  item: 0x%lx",
+                BBLS(&bup_database->db_item.base.name), BBLS(&item->name),
+                (long) dynamic_array_ptr(&bup_database->db_perdbs,
+                                         bup_database->db_perdbs.elements
+                                         - 1)));
+    break;
+  }
+
+  case BSTREAM_IT_SPROC:
+  {
+    fprintf(stderr, "ERROR: backup object not yet implemented: sproc\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: sproc: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  case BSTREAM_IT_SFUNC:
+  {
+    fprintf(stderr, "ERROR: backup object not yet implemented: sfunc\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: sfunc: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  case BSTREAM_IT_EVENT:
+  {
+    fprintf(stderr, "ERROR: backup object not yet implemented: event\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: event: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  case BSTREAM_IT_TRIGGER:
+  {
+    fprintf(stderr, "ERROR: backup object not yet implemented: trigger\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: trigger: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  case BSTREAM_IT_TABLESPACE:
+  {
+    fprintf(stderr, "ERROR: backup object not yet implemented: tablespace\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: tablespace: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  default:
+  {
+    fprintf(stderr, "ERROR: backup object not yet implemented: unknown type\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: unknown type: '%.*s'",
+                           BBLS(&item->name)));
+    DBUG_ASSERT(0);
+  }
+  }
+
+ end:
+  DBUG_RETURN(rc);
+}
+
+
+/**
+  Create global iterator of a given type.
+
+  Possible iterator types.
+
+  - BSTREAM_IT_CHARSET: all charsets
+  - BSTREAM_IT_USER:    all users
+  - BSTREAM_IT_DB:      all databases
+
+  The following types of iterators iterate only over items for which
+  some meta-data should be saved in the image.
+
+  - BSTREAM_IT_GLOBAL: all global items in create-dependency order
+  - BSTREAM_IT_PERDB: all per-db items except tables which are enumerated by
+                      a table iterator (see below)
+  - BSTREAM_IT_PERTABLE: all per-table items in create-dependency orders.
+
+  @param[in]    hdr             catalog reference
+  @param[in]    it_type         iterator type
+
+  @return       pointer to the iterator
+    @retval     NULL            error
+*/
+
+void*
+bcat_iterator_get(struct st_bstream_image_header *hdr, unsigned int it_type)
+{
+  struct st_backup_catalog      *bup_catalog= (struct st_backup_catalog*) hdr;
+  struct st_backup_iterator     *iter;
+  DBUG_ENTER("bcat_iterator_get");
+  DBUG_ASSERT(hdr);
+  DBUG_PRINT("bupstrm", ("getting iterator for type: %u", it_type));
+
+  if (!(iter= my_malloc(sizeof(struct st_backup_iterator), MYF(MY_WME))))
+  {
+    /* Error message reported by mysys. */
+    goto end;
+  }
+  iter->it_index= -1;
+  iter->it_type= it_type;
+
+  switch (it_type) {
+  case BSTREAM_IT_CHARSET:
+    iter->it_array= &bup_catalog->cat_charsets;
+    DBUG_PRINT("bupstrm", ("charset"));
+    break;
+
+  case BSTREAM_IT_USER:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: user\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: user"));
+    goto err;
+
+  case BSTREAM_IT_PRIVILEGE:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: privilege\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: privilege"));
+    goto err;
+
+  case BSTREAM_IT_DB:
+    iter->it_array= &bup_catalog->cat_databases;
+    DBUG_PRINT("bupstrm", ("database"));
+    break;
+
+  case BSTREAM_IT_TABLE:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: table\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: table"));
+    goto err;
+
+  case BSTREAM_IT_VIEW:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: view\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: view"));
+    goto err;
+
+  case BSTREAM_IT_SPROC:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: sproc\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: sproc"));
+    goto err;
+
+  case BSTREAM_IT_SFUNC:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: sfunc\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: sfunc"));
+    goto err;
+
+  case BSTREAM_IT_EVENT:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: event\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: event"));
+    goto err;
+
+  case BSTREAM_IT_TRIGGER:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: trigger\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: trigger"));
+    goto err;
+
+  case BSTREAM_IT_TABLESPACE:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: tablespace\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: tablespace"));
+    goto err;
+
+  case BSTREAM_IT_GLOBAL:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: global\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: global"));
+    goto err;
+
+  case BSTREAM_IT_PERDB:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: perdb\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: perdb"));
+    goto err;
+
+  case BSTREAM_IT_PERTABLE:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: pertable\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: pertable"));
+    goto err;
+
+  default:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: unknown type\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: unknown type"));
+    DBUG_ASSERT(0);
+    goto err;
+  }
+
+  goto end;
+
+ err:
+  my_free(iter, MYF(0));
+  iter= NULL;
+
+ end:
+  DBUG_PRINT("bupstrm", ("iterator: 0x%lx", (long) iter));
+  DBUG_RETURN((void*) iter);
+}
+
+
+/**
+  Return next item pointed by iterator.
+
+  @param[in]    hdr             catalog reference
+  @param[in]    iter_arg        iterator reference
+
+  @return       pointer to catalog item
+    @retval     NULL            end of items or error
+*/
+
+struct st_bstream_item_info*
+bcat_iterator_next(struct st_bstream_image_header *hdr __attribute__((unused)),
+                   void *iter_arg)
+{
+  struct st_backup_iterator     *iter= (struct st_backup_iterator*) iter_arg;
+  struct st_bstream_item_info   *item= NULL;
+  DBUG_ENTER("bcat_iterator_next");
+  DBUG_PRINT("bupstrm", ("iter: 0x%lx", (long) iter));
+  DBUG_ASSERT(iter);
+  DBUG_ASSERT(iter->it_array);
+
+  /* Check for end of array. */
+  if (++iter->it_index >= (int) iter->it_array->elements)
+  {
+    /* End of array. Return NULL. This is not an error. */
+    goto end;
+  }
+  item= (struct st_bstream_item_info*) dynamic_array_ptr(iter->it_array,
+                                                         iter->it_index);
+
+  DBUG_PRINT("bupstrm", ("next iterator for type: %u", iter->it_type));
+  DBUG_PRINT("bupstrm", ("next item: 0x%lx  pos: %lu  type: %d  name: '%.*s'",
+                         (long) item, item->pos, item->type,
+                         BBLS(&item->name)));
+
+  switch (iter->it_type) {
+  case BSTREAM_IT_CHARSET:
+    DBUG_PRINT("bupstrm", ("charset"));
+    break;
+
+  case BSTREAM_IT_USER:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: user\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: user"));
+    goto err;
+
+  case BSTREAM_IT_PRIVILEGE:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: privilege\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: privilege"));
+    goto err;
+
+  case BSTREAM_IT_DB:
+    DBUG_PRINT("bupstrm", ("database"));
+    break;
+
+  case BSTREAM_IT_TABLE:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: table\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: table"));
+    goto err;
+
+  case BSTREAM_IT_VIEW:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: view\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: view"));
+    goto err;
+
+  case BSTREAM_IT_SPROC:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: sproc\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: sproc"));
+    goto err;
+
+  case BSTREAM_IT_SFUNC:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: sfunc\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: sfunc"));
+    goto err;
+
+  case BSTREAM_IT_EVENT:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: event\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: event"));
+    goto err;
+
+  case BSTREAM_IT_TRIGGER:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: trigger\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: trigger"));
+    goto err;
+
+  case BSTREAM_IT_TABLESPACE:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: tablespace\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: tablespace"));
+    goto err;
+
+  case BSTREAM_IT_GLOBAL:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: global\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: global"));
+    goto err;
+
+  case BSTREAM_IT_PERDB:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: perdb\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: perdb"));
+    goto err;
+
+  case BSTREAM_IT_PERTABLE:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: pertable\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: pertable"));
+    goto err;
+
+  default:
+    fprintf(stderr, "ERROR: iterator type not yet implemented: unknown type\n");
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: unknown type"));
+    DBUG_ASSERT(0);
+    goto err;
+  }
+
+  goto end;
+
+ err:
+  item= NULL;
+
+ end:
+  DBUG_PRINT("bupstrm", ("item: 0x%lx", (long) item));
+  DBUG_RETURN(item);
+}
+
+
+/**
+  Free iterator resources.
+
+  @param[in]    hdr             catalog reference
+  @param[in]    iter_arg        iterator reference
+
+  @note
+  The iterator can not be used after call to this function.
+*/
+
+void
+bcat_iterator_free(struct st_bstream_image_header *hdr __attribute__((unused)),
+                   void *iter_arg)
+{
+  DBUG_ENTER("bcat_iterator_free");
+  my_free(iter_arg, MYF(0));
+  DBUG_VOID_RETURN;
+}
+
+
+/**
+  Create iterator for items belonging to a given database.
+
+  @param[in]    hdr             catalog reference
+  @param[in]    db              database item reference
+
+  @return       pointer to the iterator
+    @retval     NULL            error
+
+  @note Not used when reading a backup stream.
+*/
+
+void*
+bcat_db_iterator_get(struct st_bstream_image_header *hdr
+                     __attribute__((unused)),
+                     struct st_bstream_db_info *db
+                     __attribute__((unused)))
+{
+  DBUG_ENTER("bcat_db_iterator_get");
+  DBUG_ASSERT(0);
+  DBUG_RETURN(NULL);
+}
+
+
+/**
+  Return next item from database items iterator
+
+  @param[in]    hdr             catalog reference
+  @param[in]    db              database item reference
+  @param[in]    iter_arg        iterator reference
+
+  @return       pointer to catalog item
+    @retval     NULL            error
+
+  @note Not used when reading a backup stream.
+*/
+
+struct st_bstream_dbitem_info*
+bcat_db_iterator_next(struct st_bstream_image_header *hdr
+                      __attribute__((unused)),
+                      struct st_bstream_db_info *db
+                      __attribute__((unused)),
+                      void *iter_arg
+                      __attribute__((unused)))
+{
+  DBUG_ENTER("bcat_db_iterator_next");
+  DBUG_ASSERT(0);
+  DBUG_RETURN(NULL);
+}
+
+
+/**
+  Free database items iterator resources
+
+  @param[in]    hdr             catalog reference
+  @param[in]    db              database item reference
+  @param[in]    iter_arg        iterator reference
+
+  @note Not used when reading a backup stream.
+*/
+
+void
+bcat_db_iterator_free(struct st_bstream_image_header *hdr
+                      __attribute__((unused)),
+                      struct st_bstream_db_info *db
+                      __attribute__((unused)),
+                      void *iter_arg
+                      __attribute__((unused)))
+{
+  DBUG_ENTER("bcat_db_iterator_free");
+  DBUG_ASSERT(0);
+  DBUG_VOID_RETURN;
+}
+
+
+/**
+  Produce CREATE statement for a given item.
+
+  Backup stream library calls this function when saving item's
+  meta-data. If function successfully produces the statement, it becomes
+  part of meta-data.
+
+  @param[in]    hdr             catalog reference
+  @param[in]    item            item reference
+  @param[out]   query           query string
+
+  @return       status
+    @retval     BSTREAM_OK      ok
+    @retval     otherwise       error
+
+  @note The return value is specified as 'int' in stream_v1.h
+  though only values from enum_bstream_ret_codes are expected.
+
+  @note Not used when reading a backup stream.
+*/
+
+int
+bcat_get_item_create_query(struct st_bstream_image_header *hdr
+                           __attribute__((unused)),
+                           struct st_bstream_item_info *item
+                           __attribute__((unused)),
+                           bstream_blob *query
+                           __attribute__((unused)))
+{
+  DBUG_ENTER("bcat_get_item_create_query");
+  DBUG_ASSERT(0);
+  DBUG_RETURN(BSTREAM_OK);
+}
+
+
+/**
+  Return meta-data (other than CREATE statement) for a given item.
+
+  Backup stream library calls this function when saving item's
+  meta-data. If function returns successfully, the bytes returned become
+  part of meta-data.
+
+  @param[in]    hdr             catalog reference
+  @param[in]    item            item reference
+  @param[out]   data            data blob
+
+  @return       status
+    @retval     BSTREAM_OK      ok
+    @retval     otherwise       error
+
+  @note The return value is specified as 'int' in stream_v1.h
+  though only values from enum_bstream_ret_codes are expected.
+
+  @note Not used when reading a backup stream.
+*/
+
+int
+bcat_get_item_create_data(struct st_bstream_image_header *hdr
+                          __attribute__((unused)),
+                          struct st_bstream_item_info *item
+                          __attribute__((unused)),
+                          struct st_blob *data
+                          __attribute__((unused)))
+{
+  DBUG_ENTER("bcat_get_item_create_data");
+  DBUG_ASSERT(0);
+  DBUG_RETURN(BSTREAM_ERROR);
+}
+
+
+/**
+  Create database object from its meta-data.
+
+  When the meta-data section of backup image is read, items can be created
+  as their meta-data is read (so that there is no need to store these
+  meta-data). This functions stores them in the catalog instead of
+  creating database objects. So the application can make different use
+  of the data.
+
+  @param[in]    hdr             catalog reference
+  @param[in]    item            item reference
+  @param[in]    query           query string
+  @param[in]    data            data blob
+
+  @note The item has set the 'type' element only. No item name nor
+  a catalog position is provided. Let alone a reference to a database.
+
+  @note Either query or data or both can be empty, depending
+  on what was stored in the image.
+
+  @note The blob provided by query and/or data is not guaranteed to
+  exist after the call. It must be copied to become part of the catalog.
+
+  @return       status
+    @retval     BSTREAM_OK      ok
+    @retval     otherwise       error
+
+  @note The return value is specified as 'int' in stream_v1.h
+  though only values from enum_bstream_ret_codes are expected.
+*/
+
+int
+bcat_create_item(struct st_bstream_image_header *hdr,
+                 struct st_bstream_item_info *item,
+                 struct st_blob query,
+                 struct st_blob data)
+{
+  struct st_backup_catalog      *bup_catalog= (struct st_backup_catalog*) hdr;
+  struct st_backup_metadata     mdata;
+  enum enum_bstream_ret_codes   rc= BSTREAM_OK;
+  DBUG_ENTER("bcat_create_item");
+  DBUG_ASSERT(hdr);
+  DBUG_ASSERT(item);
+  DBUG_PRINT("bupstrm", ("item: 0x%lx  pos: %lu  type: %d  name: '%.*s'",
+                         (long) item, item->pos, item->type,
+                         BBLS(&item->name)));
+  DBUG_PRINT("bupstrm", ("query: '%.*s'", BBLS(&query)));
+  DBUG_PRINT("bupstrm", ("data length: %lu", BBL(&data)));
+
+  /*
+    Create new st_blob structs. The strings from the
+    stream libraray have a short life time.
+  */
+  mdata.md_query.begin= (query.begin ?
+                         my_memdup(query.begin, BBL(&query), MYF(MY_WME)) :
+                         NULL);
+  mdata.md_query.end= (mdata.md_query.begin ?
+                       mdata.md_query.begin + BBL(&query) :
+                       NULL);
+
+  mdata.md_data.begin= (data.begin ?
+                        my_memdup(data.begin, BBL(&data), MYF(MY_WME)) :
+                        NULL);
+  mdata.md_data.end= (mdata.md_data.begin ?
+                      mdata.md_data.begin + BBL(&data) :
+                      NULL);
+
+  DBUG_PRINT("bupstrm", ("query.begin: 0x%lx  data.begin: 0x%lx",
+                         (long) mdata.md_query.begin,
+                         (long) mdata.md_data.begin));
+
+  if ((query.begin && !mdata.md_query.begin) ||
+      (data.begin && !mdata.md_data.begin))
+  {
+    /* Memory allocation failed. Error message reported by mysys. */
+    rc= BSTREAM_ERROR;
+    goto end;
+  }
+
+  switch (item->type) {
+  case BSTREAM_IT_CHARSET:
+  {
+    fprintf(stderr, "ERROR: meta data not yet implemented: charset\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: charset: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  case BSTREAM_IT_USER:
+  {
+    fprintf(stderr, "ERROR: meta data not yet implemented: user\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: user: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  case BSTREAM_IT_PRIVILEGE:
+  {
+    fprintf(stderr, "ERROR: meta data not yet implemented: privilege\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: privilege: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  case BSTREAM_IT_DB:
+  {
+    struct st_bstream_db_info *item_db= (struct st_bstream_db_info*) item;
+    struct st_backup_database *cat_db;
+    DBUG_PRINT("bupstrm", ("database  pos: %lu", item_db->base.pos));
+    cat_db= backup_locate_database(bup_catalog, item_db->base.pos);
+    if (!cat_db)
+    {
+      /* Error reported by function. */
+      rc= BSTREAM_ERROR;
+      goto end;
+    }
+    /* Copy meta data. */
+    cat_db->db_metadata= mdata;
+    break;
+  }
+
+  case BSTREAM_IT_TABLE:
+  {
+    struct st_bstream_table_info *item_tbl=
+      (struct st_bstream_table_info*) item;
+    struct st_backup_table *cat_tbl;
+    DBUG_PRINT("bupstrm", ("table  snap_num: %u  pos: %lu",
+                           item_tbl->snap_num, item_tbl->base.base.pos));
+    cat_tbl= backup_locate_table(bup_catalog, item_tbl->snap_num,
+                                 item_tbl->base.base.pos);
+    if (!cat_tbl)
+    {
+      /* Error reported by function. */
+      rc= BSTREAM_ERROR;
+      goto end;
+    }
+    /* Copy meta data. */
+    cat_tbl->tbl_metadata= mdata;
+    break;
+  }
+
+  case BSTREAM_IT_VIEW:
+  {
+    struct st_bstream_dbitem_info *item_perdb=
+      (struct st_bstream_dbitem_info*) item;
+    struct st_backup_perdb *cat_perdb;
+    DBUG_PRINT("bupstrm", ("view  db_pos: %lu  pos: %lu",
+                           item_perdb->db->base.pos, item_perdb->base.pos));
+    cat_perdb= backup_locate_perdb(bup_catalog, item_perdb->db->base.pos,
+                                   item_perdb->base.pos);
+    if (!cat_perdb)
+    {
+      /* Error reported by function. */
+      rc= BSTREAM_ERROR;
+      goto end;
+    }
+    /* Copy meta data. */
+    cat_perdb->perdb_metadata= mdata;
+    break;
+  }
+
+  case BSTREAM_IT_SPROC:
+  {
+    fprintf(stderr, "ERROR: meta data not yet implemented: sproc\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: sproc: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  case BSTREAM_IT_SFUNC:
+  {
+    fprintf(stderr, "ERROR: meta data not yet implemented: sfunc\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: sfunc: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  case BSTREAM_IT_EVENT:
+  {
+    fprintf(stderr, "ERROR: meta data not yet implemented: event\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: event: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  case BSTREAM_IT_TRIGGER:
+  {
+    fprintf(stderr, "ERROR: meta data not yet implemented: trigger\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: trigger: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  case BSTREAM_IT_TABLESPACE:
+  {
+    fprintf(stderr, "ERROR: meta data not yet implemented: tablespace\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: tablespace: '%.*s'",
+                           BBLS(&item->name)));
+    break;
+  }
+
+  default:
+  {
+    fprintf(stderr, "ERROR: meta data not yet implemented: unknown type\n");
+    rc= BSTREAM_ERROR;
+    DBUG_PRINT("bupstrm", ("NOTYET implemented: unknown type: '%.*s'",
+                           BBLS(&item->name)));
+    DBUG_ASSERT(0);
+  }
+  }
+
+ end:
+  if (rc != BSTREAM_OK)
+  {
+    /* Free what has been allocated. */
+    my_free(mdata.md_data.begin, MYF(MY_ALLOW_ZERO_PTR));
+    my_free(mdata.md_query.begin, MYF(MY_ALLOW_ZERO_PTR));
+  }
+  DBUG_RETURN(rc);
+}
+
+
+/*
+  ========================================
+  Functions for reading of a backup image.
+  ========================================
+*/
+
+/**
+  Allocate a backup catalog.
+
+  @return       catalog reference
+    @retval     NULL            error
+*/
+
+struct st_backup_catalog*
+backup_catalog_allocate(void)
+{
+  struct st_backup_catalog      *bup_catalog;
+  int                           errpos= 0;
+  DBUG_ENTER("backup_catalog_allocate");
+
+  bup_catalog= my_malloc(sizeof(struct st_backup_catalog),
+                         MYF(MY_WME | MY_ZEROFILL));
+  if (!bup_catalog)
+  {
+    /* Error message reported by mysys. */
+    goto err;
+  }
+  errpos= 10;
+
+  if (my_init_dynamic_array(&bup_catalog->cat_charsets,
+                            sizeof(struct st_backup_charset), 16, 16))
+  {
+    /* Error message reported by mysys. */
+    goto err;
+  }
+  errpos= 20;
+
+  if (my_init_dynamic_array(&bup_catalog->cat_databases,
+                            sizeof(struct st_backup_database), 16, 16))
+  {
+    /* Error message reported by mysys. */
+    goto err;
+  }
+  errpos= 30;
+
+  if (my_init_dynamic_array(&bup_catalog->cat_snapshots,
+                            sizeof(struct st_backup_snapshot), 16, 16))
+  {
+    /* Error message reported by mysys. */
+    goto err;
+  }
+  errpos= 40;
+
+  goto end;
+
+ err:
+  switch(errpos) {
+  case 40:
+    delete_dynamic(&bup_catalog->cat_snapshots);
+  case 30:
+    delete_dynamic(&bup_catalog->cat_databases);
+  case 20:
+    delete_dynamic(&bup_catalog->cat_charsets);
+  case 10:
+    my_free(bup_catalog, MYF(0));
+    bup_catalog= NULL;
+  }
+
+ end:
+  DBUG_RETURN(bup_catalog);
+}
+
+
+/**
+  Free a backup catalog.
+
+  @param[in]    bup_catalog             catalog reference
+*/
+
+void
+backup_catalog_free(struct st_backup_catalog *bup_catalog)
+{
+  struct st_bstream_image_header        *hdr= &bup_catalog->cat_header;
+  ulong                                 idx;
+  ulong                                 jdx;
+  DBUG_ENTER("backup_catalog_free");
+  DBUG_ASSERT(bup_catalog);
+
+  /* Snapshots. */
+  DBUG_PRINT("bupstrm", ("freeing snapshots."));
+  for (idx= 0; idx < bup_catalog->cat_snapshots.elements; idx++)
+  {
+    struct st_backup_snapshot   *snap;
+
+    snap= (struct st_backup_snapshot*)
+      dynamic_array_ptr(&bup_catalog->cat_snapshots, idx);
+    delete_dynamic(&snap->snap_index_pos_to_table);
+  }
+  delete_dynamic(&bup_catalog->cat_snapshots);
+
+  /* Databases and contained objects. */
+  DBUG_PRINT("bupstrm", ("freeing databases and contained objects."));
+  for (idx= 0; idx < bup_catalog->cat_databases.elements; idx++)
+  {
+    struct st_backup_database   *dbase;
+    struct st_backup_metadata   *mdata;
+
+    dbase= backup_locate_database(bup_catalog, idx);
+    if (!dbase)
+    {
+      /* Error reported by function. */
+      continue;
+    }
+
+    /* Perdb items. */
+    DBUG_PRINT("bupstrm", ("freeing perdbs."));
+    for (jdx= 0; jdx < dbase->db_perdbs.elements; jdx++)
+    {
+      struct st_backup_perdb    *perdb;
+
+      perdb= (struct st_backup_perdb*)
+        dynamic_array_ptr(&dbase->db_perdbs, jdx);
+      mdata= &perdb->perdb_metadata;
+      my_free(mdata->md_data.begin, MYF(MY_ALLOW_ZERO_PTR));
+      my_free(mdata->md_query.begin, MYF(MY_ALLOW_ZERO_PTR));
+      my_free(perdb->perdb_item.base.name.begin, MYF(MY_ALLOW_ZERO_PTR));
+    }
+    delete_dynamic(&dbase->db_perdbs);
+
+    /* Tables. */
+    DBUG_PRINT("bupstrm", ("freeing tables."));
+    for (jdx= 0; jdx < dbase->db_tables.elements; jdx++)
+    {
+      struct st_backup_table    *tbl;
+
+      tbl= (struct st_backup_table*)
+        dynamic_array_ptr(&dbase->db_tables, jdx);
+      mdata= &tbl->tbl_metadata;
+      my_free(mdata->md_data.begin, MYF(MY_ALLOW_ZERO_PTR));
+      my_free(mdata->md_query.begin, MYF(MY_ALLOW_ZERO_PTR));
+      my_free(tbl->tbl_item.base.base.name.begin, MYF(MY_ALLOW_ZERO_PTR));
+    }
+    delete_dynamic(&dbase->db_tables);
+
+    DBUG_PRINT("bupstrm", ("freeing db meta data."));
+    mdata= &dbase->db_metadata;
+    my_free(mdata->md_data.begin, MYF(MY_ALLOW_ZERO_PTR));
+    my_free(mdata->md_query.begin, MYF(MY_ALLOW_ZERO_PTR));
+    my_free(dbase->db_item.base.name.begin, MYF(MY_ALLOW_ZERO_PTR));
+  }
+  delete_dynamic(&bup_catalog->cat_databases);
+
+  /* Character sets. */
+  DBUG_PRINT("bupstrm", ("freeing charsets."));
+  for (idx= 0; idx < bup_catalog->cat_charsets.elements; idx++)
+  {
+    struct st_backup_charset    *chrset;
+
+    chrset= (struct st_backup_charset*)
+      dynamic_array_ptr(&bup_catalog->cat_charsets, idx);
+
+    my_free(chrset->cs_item.name.begin, MYF(MY_ALLOW_ZERO_PTR));
+  }
+  delete_dynamic(&bup_catalog->cat_charsets);
+
+  /* Header, snapshots. */
+  DBUG_PRINT("bupstrm", ("freeing header, snapshots."));
+  for (idx= 0; idx < hdr->snap_count; ++idx)
+    bstream_free(hdr->snapshot[idx].engine.name.begin);
+
+  /* Header, server version. */
+  DBUG_PRINT("bupstrm", ("freeing header, server version."));
+  if (hdr->server_version.extra.begin)
+    bstream_free(hdr->server_version.extra.begin);
+
+  /* Catalog. */
+  DBUG_PRINT("bupstrm", ("freeing catalog."));
+  my_free(bup_catalog, MYF(0));
+
+  DBUG_VOID_RETURN;
+}
+
+
+/**
+  Open a backup image.
+
+  @param[in]    filename                file name
+  @param[in]    bup_catalog             catalog reference
+
+  @return       image handle reference
+    @retval     NULL                    error
+*/
+
+void*
+backup_image_open(const char *filename, struct st_backup_catalog *bup_catalog)
+{
+  struct st_stream      *strm;
+  int                   rc;
+  int                   errpos= 0;
+  uint                  idx;
+  uint                  version;
+  DBUG_ENTER("backup_image_open");
+  DBUG_ASSERT(filename);
+  DBUG_ASSERT(bup_catalog);
+
+  /* Allocate low-level stream info struct. */
+  strm= my_malloc(sizeof(struct st_stream), MYF(MY_WME));
+  if (!strm)
+  {
+    /* Error message reported by mysys. */
+    goto err;
+  }
+  errpos= 10;
+
+  /*
+    Open stream.
+  */
+  rc= str_open_rd(strm, filename, &version);
+  DBUG_PRINT("bupstrm", ("Opened backup image file (rc=%d)", rc));
+  if (rc != BSTREAM_OK)
+  {
+    /* Error message reported by function. */
+    goto err;
+  }
+  strm->stream_pos= "prefix";
+  errpos= 20;
+
+  /* Add compression algorithm to header. */
+  bup_catalog->cat_zalgo= strm->zalgo;
+
+  /* Add image path to header. */
+  bup_catalog->cat_image_path= strm->path;
+
+  /* Add image size to header. */
+  bup_catalog->cat_image_size= strm->size;
+
+  /*
+    Read backup image stream header.
+  */
+  rc= bstream_rd_header(&strm->bupstrm, &bup_catalog->cat_header);
+  DBUG_PRINT("bupstrm", ("Read archive header (rc=%d)", rc));
+  if ((rc != BSTREAM_OK) && (rc != BSTREAM_EOC))
+  {
+    fprintf(stderr, "ERROR: error on stream library read of header.\n");
+    goto err;
+  }
+  strm->stream_pos= "header";
+  errpos= 30;
+
+  /* Add image version to header. */
+  bup_catalog->cat_header.version= version;
+
+  /*
+    Now that we know, how many snapshots we have, initialize the
+    snapshot pos to table index arrays.
+  */
+  for (idx= 0; idx < bup_catalog->cat_header.snap_count; idx++)
+  {
+    struct st_backup_snapshot bup_snapshot;
+
+    /* Prepare for reuse. */
+    bzero(&bup_snapshot, sizeof(bup_snapshot));
+    /* Initialize a new index array. */
+    if (my_init_dynamic_array(&bup_snapshot.snap_index_pos_to_table,
+                              sizeof(struct st_backup_table*), 16, 16))
+    {
+      /* Error message reported by mysys. */
+      rc= BSTREAM_ERROR;
+      goto err;
+    }
+    /* Check consistency of array position. */
+    DBUG_ASSERT(idx == bup_catalog->cat_snapshots.elements);
+    /* Insert in the catalog. */
+    if (insert_dynamic(&bup_catalog->cat_snapshots, (uchar*) &bup_snapshot))
+    {
+      /* Error message reported by mysys. */
+      /* Delete the locally prepared array. */
+      delete_dynamic(&bup_snapshot.snap_index_pos_to_table);
+      rc= BSTREAM_ERROR;
+      goto err;
+    }
+  }
+
+  goto end;
+
+ err:
+  switch (errpos) {
+  case 30:
+    /* Delete the index arrays that have already been allocated so far. */
+    while (idx)
+    {
+      struct st_backup_snapshot   *snap;
+
+      idx--;
+      snap= (struct st_backup_snapshot*)
+        dynamic_array_ptr(&bup_catalog->cat_snapshots, idx);
+      delete_dynamic(&snap->snap_index_pos_to_table);
+    }
+  case 20:
+    (void) str_close(strm);
+  case 10:
+    my_free(strm, MYF(MY_ALLOW_ZERO_PTR));
+    strm= NULL;
+  }
+
+ end:
+  DBUG_RETURN(strm);
+}
+
+
+/**
+  Close a backup image.
+
+  @param[in]    image_handle            image handle reference
+*/
+
+void
+backup_image_close(void* image_handle)
+{
+  struct st_stream *strm= (struct st_stream*) image_handle;
+  DBUG_ENTER("backup_image_close");
+  DBUG_ASSERT(strm);
+
+  (void) str_close(strm);
+  my_free(strm, MYF(0));
+  DBUG_VOID_RETURN;
+}
+
+
+/**
+  Read backup image catalog.
+
+  @param[in]    image_handle            image handle reference
+  @param[in]    bup_catalog             catalog reference
+
+  @return       status
+    @retval     BSTREAM_OK              ok
+    @retval     != BSTREAM_OK           error
+*/
+
+enum enum_bstream_ret_codes
+backup_read_catalog(void* image_handle, struct st_backup_catalog *bup_catalog)
+{
+  struct st_stream *strm= (struct st_stream*) image_handle;
+  enum enum_bstream_ret_codes rc;
+  DBUG_ENTER("backup_read_catalog");
+  DBUG_ASSERT(strm);
+  DBUG_ASSERT(bup_catalog);
+
+  /*
+    Read catalog requires search of next chunk start.
+  */
+  rc= bstream_next_chunk(&strm->bupstrm);
+  DBUG_PRINT("bupstrm", ("Find next chunk (rc=%d)", rc));
+  if (rc != BSTREAM_OK)
+  {
+    if (rc == BSTREAM_EOS)
+    {
+      fprintf(stderr, "ERROR: end of stream after %s.\n", strm->stream_pos);
+      goto end;
+    }
+    fprintf(stderr, "ERROR: cannot find catalog after %s.\n", strm->stream_pos);
+    goto end;
+  }
+
+  /*
+    Read catalog.
+  */
+  rc= bstream_rd_catalogue(&strm->bupstrm, &bup_catalog->cat_header);
+  DBUG_PRINT("bupstrm", ("Read archive catalogue (rc=%d)", rc));
+  if ((rc != BSTREAM_OK) && (rc != BSTREAM_EOC))
+  {
+    if (rc == BSTREAM_EOS)
+    {
+      fprintf(stderr, "ERROR: end of stream within catalog.\n");
+      goto end;
+    }
+    fprintf(stderr, "ERROR: error on stream library read of catalog.\n");
+    goto end;
+  }
+  strm->stream_pos= "catalog";
+  rc= BSTREAM_OK;
+
+ end:
+  DBUG_RETURN(rc);
+}
+
+
+/**
+  Read backup image meta data.
+
+  @param[in]    image_handle            image handle reference
+  @param[in]    bup_catalog             catalog reference
+
+  @return       status
+    @retval     BSTREAM_OK              ok
+    @retval     != BSTREAM_OK           error
+*/
+
+enum enum_bstream_ret_codes
+backup_read_metadata(void *image_handle, struct st_backup_catalog *bup_catalog)
+{
+  struct st_stream *strm= (struct st_stream*) image_handle;
+  enum enum_bstream_ret_codes rc;
+  DBUG_ENTER("backup_read_metadata");
+  DBUG_ASSERT(strm);
+  DBUG_ASSERT(bup_catalog);
+
+  /*
+    Read meta data requires search of next chunk start.
+  */
+  rc= bstream_next_chunk(&strm->bupstrm);
+  DBUG_PRINT("bupstrm", ("Find next chunk (rc=%d)", rc));
+  if (rc != BSTREAM_OK)
+  {
+    if (rc == BSTREAM_EOS)
+    {
+      fprintf(stderr, "ERROR: end of stream after %s.\n", strm->stream_pos);
+      goto end;
+    }
+    fprintf(stderr, "ERROR: cannot find meta data after %s.\n",
+            strm->stream_pos);
+    goto end;
+  }
+
+  /*
+    Read meta data.
+  */
+  rc= bstream_rd_meta_data(&strm->bupstrm, &bup_catalog->cat_header);
+  DBUG_PRINT("bupstrm", ("Read meta data (rc=%d)", rc));
+  if ((rc != BSTREAM_OK) && (rc != BSTREAM_EOC))
+  {
+    if (rc == BSTREAM_EOS)
+    {
+      fprintf(stderr, "ERROR: end of stream within meta data.\n");
+      goto end;
+    }
+    fprintf(stderr, "ERROR: error on stream library read of meta data.\n");
+    goto end;
+  }
+  strm->stream_pos= "meta data";
+  rc= BSTREAM_OK;
+
+ end:
+  DBUG_RETURN(rc);
+}
+
+
+/**
+  Read backup image table data.
+
+  @param[in]    image_handle            image handle reference
+  @param[in]    bup_catalog             catalog reference
+
+  @return       status
+    @retval     BSTREAM_OK              ok
+    @retval     != BSTREAM_OK           error
+*/
+
+enum enum_bstream_ret_codes
+backup_read_snapshot(void *image_handle,
+                     struct st_backup_catalog *bup_catalog
+                      __attribute__((unused)),
+                     struct st_bstream_data_chunk *snapshot)
+{
+  struct st_stream *strm= (struct st_stream*) image_handle;
+  enum enum_bstream_ret_codes rc;
+  DBUG_ENTER("backup_read_snapshot");
+  DBUG_ASSERT(strm);
+  DBUG_ASSERT(snapshot);
+
+  /*
+    First read data chunk requires search of next chunk start.
+  */
+  if (!strcmp(strm->stream_pos, "meta data"))
+  {
+    rc= bstream_next_chunk(&strm->bupstrm);
+    DBUG_PRINT("bupstrm", ("Find next chunk (rc=%d)", rc));
+    if (rc != BSTREAM_OK)
+    {
+      if (rc == BSTREAM_EOS)
+      {
+        fprintf(stderr, "ERROR: end of stream after %s.\n", strm->stream_pos);
+        goto end;
+      }
+      fprintf(stderr, "ERROR: cannot find next chunk after %s.\n",
+              strm->stream_pos);
+      goto end;
+    }
+  }
+
+  /*
+    Read data chunk.
+  */
+  snapshot->data.begin= NULL;
+  snapshot->data.end= NULL;
+  rc= bstream_rd_data_chunk(&strm->bupstrm, snapshot);
+  DBUG_PRINT("bupstrm", ("Read data chunk (rc=%d)", rc));
+  if ((rc != BSTREAM_OK) && (rc != BSTREAM_EOC))
+  {
+    fprintf(stderr, "ERROR: error on stream library read of snapshot.\n");
+    goto end;
+  }
+  strm->stream_pos= "table data";
+
+ end:
+  DBUG_RETURN(rc);
+}
+
+
+/**
+  Read backup image summary.
+
+  @param[in]    image_handle            image handle reference
+  @param[in]    bup_catalog             catalog reference
+
+  @return       status
+    @retval     BSTREAM_OK              ok
+    @retval     != BSTREAM_OK           error
+*/
+
+enum enum_bstream_ret_codes
+backup_read_summary(void* image_handle, struct st_backup_catalog *bup_catalog)
+{
+  struct st_stream *strm= (struct st_stream*) image_handle;
+  enum enum_bstream_ret_codes rc;
+  DBUG_ENTER("backup_read_summary");
+  DBUG_ASSERT(strm);
+  DBUG_ASSERT(bup_catalog);
+
+  rc= bstream_rd_summary(&strm->bupstrm, &bup_catalog->cat_header);
+  DBUG_PRINT("bupstrm", ("Read summary (rc=%d)", rc));
+  if (rc != BSTREAM_EOS)
+  {
+    if (rc == BSTREAM_ERROR)
+      fprintf(stderr, "ERROR: error on stream library read of summary.\n");
+    else
+      fprintf(stderr, "ERROR: stream not at end after reading summary.\n");
+    rc= BSTREAM_ERROR;
+    goto end;
+  }
+  strm->stream_pos= "summary";
+  rc= BSTREAM_OK;
+
+ end:
+  DBUG_RETURN(rc);
+}
+
+
+/*
+  ===================
+  Catalog navigation.
+  ===================
+*/
+
+/*
+  Catalog items are located by "catalog coordinates". The format of the
+  catalog coordinates depends on the type of item. It is specified as
+  follows:
+
+  [item position (global)]= [db no.]
+  [item position (table)]= [ snap no. ! pos in snapshot's table list ]
+  [item position (other per-db item)]= [ pos in db item list ! db no. ]
+  [item position (per-table item)] = [ pos in table's item list !
+                                       db no. ! table pos ]
+*/
+
+/**
+  Locate a database object by catalog coordinates.
+
+  Catalog coordinates for databases are:
+
+      pos           database position in catalog
+
+  @param[in]    bup_catalog     catalog reference
+  @param[in]    pos             position in catalog's database array
+
+  @return       database reference
+*/
+
+struct st_backup_database*
+backup_locate_database(struct st_backup_catalog *bup_catalog,
+                       ulong pos)
+{
+  static struct st_backup_database *cat_db;
+  DBUG_ENTER("backup_locate_database");
+  DBUG_ASSERT(bup_catalog);
+  DBUG_PRINT("bupstrm", ("pos: %lu", pos));
+
+  /* Check plausibility of array position. */
+  if (pos >= bup_catalog->cat_databases.elements)
+  {
+    fprintf(stderr, "ERROR: non-existent database position: %lu  "
+            "in catalog.\n", pos);
+    cat_db= NULL;
+    goto end;
+  }
+
+  /* Get a reference to the database object. */
+  cat_db= (struct st_backup_database*)
+    dynamic_array_ptr(&bup_catalog->cat_databases, pos);
+  DBUG_PRINT("bupstrm",
+             ("located database: '%.*s'  item: 0x%lx  pos: %lu",
+              BBLS(&cat_db->db_item.base.name), (long) cat_db,
+              cat_db->db_item.base.pos));
+
+  /* Check consistency of array position. */
+  if (cat_db->db_item.base.pos != pos)
+  {
+    fprintf(stderr, "ERROR: position of stored database item: %lu  "
+            "does not match position in catalog: %lu\n",
+            cat_db->db_item.base.pos, pos);
+    cat_db= NULL;
+  }
+
+ end:
+  DBUG_RETURN(cat_db);
+}
+
+
+/**
+  Locate a table object by catalog coordinates.
+
+  Catalog coordinates for tables are:
+
+      snap_num      snapshot position in catalog
+      pos           table position in snapshot
+
+  @param[in]    bup_catalog     catalog reference
+  @param[in]    snap_num        position in catalog's snapshot array
+  @param[in]    pos             position in snapshot's table index array
+
+  @return       table reference
+*/
+
+struct st_backup_table*
+backup_locate_table(struct st_backup_catalog *bup_catalog,
+                    ulong snap_num, ulong pos)
+{
+  static struct st_backup_snapshot      *cat_snap;
+  static struct st_backup_table         *cat_tbl;
+  DBUG_ENTER("backup_locate_table");
+  DBUG_ASSERT(bup_catalog);
+  DBUG_PRINT("bupstrm", ("snap_num: %lu  pos: %lu", snap_num, pos));
+
+  /* Check plausibility of array position. */
+  if (snap_num >= bup_catalog->cat_snapshots.elements)
+  {
+    fprintf(stderr, "ERROR: non-existent snapshot position: %lu  "
+            "in catalog.\n", snap_num);
+    cat_tbl= NULL;
+    goto end;
+  }
+
+  /* Get a reference to the snapshot object. */
+  cat_snap= (struct st_backup_snapshot*)
+    dynamic_array_ptr(&bup_catalog->cat_snapshots, snap_num);
+
+  /* Check plausibility of array position. */
+  if (pos >= cat_snap->snap_index_pos_to_table.elements)
+  {
+    fprintf(stderr, "ERROR: non-existent table position: %lu  "
+            "in table index of snapshot: %lu\n", pos, snap_num);
+    cat_tbl= NULL;
+    goto end;
+  }
+
+  /* Get a reference to the database object. */
+  cat_tbl= *((struct st_backup_table**)
+             dynamic_array_ptr(&cat_snap->snap_index_pos_to_table, pos));
+  DBUG_PRINT("bupstrm",
+             ("located table: '%.*s'.'%.*s'  "
+              "item: 0x%lx  snap_num: %u  pos: %lu",
+              BBLS(&cat_tbl->tbl_item.base.db->base.name),
+              BBLS(&cat_tbl->tbl_item.base.base.name), (long) cat_tbl,
+              cat_tbl->tbl_item.snap_num, cat_tbl->tbl_item.base.base.pos));
+
+  /* Check consistency of array position. */
+  if (cat_tbl->tbl_item.snap_num != snap_num)
+  {
+    fprintf(stderr, "ERROR: snapshot position of stored table item: %u  "
+            "does not match position in catalog: %lu\n",
+            cat_tbl->tbl_item.snap_num, snap_num);
+    cat_tbl= NULL;
+  }
+  if (cat_tbl->tbl_item.base.base.pos != pos)
+  {
+    fprintf(stderr, "ERROR: position of stored table item: %lu  "
+            "does not match position in index of snapshot %lu: %lu\n",
+            cat_tbl->tbl_item.base.base.pos, snap_num, pos);
+    cat_tbl= NULL;
+  }
+
+ end:
+  DBUG_RETURN(cat_tbl);
+}
+
+
+/**
+  Locate a perdb object by catalog coordinates.
+
+  Catalog coordinates for perdb items are:
+
+      db_pos        database position in catalog
+      pos           perdb item position in database
+
+  @param[in]    bup_catalog     catalog reference
+  @param[in]    db_pos          position in catalog's databse array
+  @param[in]    pos             position in databases's perdb array
+
+  @return       perdb item reference
+*/
+
+struct st_backup_perdb*
+backup_locate_perdb(struct st_backup_catalog *bup_catalog,
+                    ulong db_pos, ulong pos)
+{
+  static struct st_backup_database      *cat_db;
+  static struct st_backup_perdb         *cat_perdb;
+  DBUG_ENTER("backup_locate_perdb");
+  DBUG_ASSERT(bup_catalog);
+  DBUG_PRINT("bupstrm", ("db_pos: %lu  pos: %lu", db_pos, pos));
+
+  /* Check plausibility of array position. */
+  if (db_pos >= bup_catalog->cat_databases.elements)
+  {
+    fprintf(stderr, "ERROR: non-existent database position: %lu  "
+            "in catalog.\n", db_pos);
+    cat_perdb= NULL;
+    goto end;
+  }
+
+  /* Get a reference to the snapshot object. */
+  cat_db= (struct st_backup_database*)
+    dynamic_array_ptr(&bup_catalog->cat_databases, db_pos);
+
+  /* Check plausibility of array position. */
+  if (pos >= cat_db->db_perdbs.elements)
+  {
+    fprintf(stderr, "ERROR: non-existent perdb position: %lu  "
+            "in database: '%.*s'\n", pos, BBLS(&cat_db->db_item.base.name));
+    cat_perdb= NULL;
+    goto end;
+  }
+
+  /* Get a reference to the database object. */
+  cat_perdb= (struct st_backup_perdb*)
+    dynamic_array_ptr(&cat_db->db_perdbs, pos);
+  DBUG_PRINT("bupstrm",
+             ("located perdb: '%.*s'.'%.*s'  "
+              "item: 0x%lx  db_pos: %lu  pos: %lu",
+              BBLS(&cat_perdb->perdb_item.db->base.name),
+              BBLS(&cat_perdb->perdb_item.base.name), (long) cat_perdb,
+              cat_perdb->perdb_item.db->base.pos,
+              cat_perdb->perdb_item.base.pos));
+
+  /* Check consistency of array position. */
+  if (cat_perdb->perdb_item.db->base.pos != db_pos)
+  {
+    fprintf(stderr, "ERROR: database position of stored perdb item: %lu  "
+            "does not match position in catalog: %lu\n",
+            cat_db->db_item.base.pos, pos);
+    cat_perdb= NULL;
+  }
+  if (cat_perdb->perdb_item.base.pos != pos)
+  {
+    fprintf(stderr, "ERROR: position of stored perdb item: %lu  "
+            "does not match position in database '%.*s': %lu\n",
+            cat_db->db_item.base.pos, BBLS(&cat_db->db_item.base.name), pos);
+    cat_perdb= NULL;
+  }
+
+ end:
+  DBUG_RETURN(cat_perdb);
+}
+
+

=== added file 'client/backup_stream.h'
--- a/client/backup_stream.h	1970-01-01 00:00:00 +0000
+++ b/client/backup_stream.h	2008-10-29 15:25:00 +0000
@@ -0,0 +1,217 @@
+/* Copyright (C) 2008 Sun Microsystems Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/*
+  MySQL Backup Image Stream reading
+*/
+
+/*
+  Include from mysys functions.
+*/
+#include "my_global.h"
+#include "my_sys.h"
+
+/*
+  Include from the low-level stream access functions.
+*/
+#include "stream_v1.h"
+#include "stream_v1_services.h"
+
+/*
+  =====================
+  Catalog declarations.
+  =====================
+*/
+
+/*
+  The below declarations in C language try to borrow kind of inheritance
+  from C++. By having a sub-structure as the first element of a new
+  structure one can cast to the new structure when a reference to the
+  sub-structure is given.
+*/
+
+/*
+  Catalog.
+
+  The dynamic arrays hold elements of the following types:
+
+  struct st_backup_charset              cat_charsets
+  struct st_backup_database             cat_databases
+  struct st_backup_metadata             cat_metadata_databases
+  struct st_backup_metadata             cat_metadata_tables
+  struct st_backup_snapshot             cat_snapshots
+
+  note: cat_header must be first element in st_backup_catalog.
+*/
+struct st_backup_catalog
+{
+  struct st_bstream_image_header        cat_header;     /* must be 1st */
+  const char                            *cat_zalgo;
+  const char                            *cat_image_path;
+  my_off_t                              cat_image_size;
+  DYNAMIC_ARRAY                         cat_charsets;
+  DYNAMIC_ARRAY                         cat_databases;
+  DYNAMIC_ARRAY                         cat_snapshots;
+};
+
+/*
+  Meta data.
+*/
+struct st_backup_metadata
+{
+  struct st_blob                        md_query;
+  struct st_blob                        md_data;
+};
+
+/*
+  Character set.
+
+  note: cs_item must be first element in st_backup_charset.
+*/
+struct st_backup_charset
+{
+  struct st_bstream_item_info           cs_item;        /* must be 1st */
+};
+
+/*
+  Per database objects, e.g. views.
+
+  note: perdb_item must be first element in st_backup_table.
+*/
+struct st_backup_perdb
+{
+  struct st_bstream_dbitem_info         perdb_item;       /* must be 1st */
+  struct st_backup_metadata             perdb_metadata;
+};
+
+/*
+  Table.
+
+  note: tbl_item must be first element in st_backup_table.
+*/
+struct st_backup_table
+{
+  struct st_bstream_table_info          tbl_item;       /* must be 1st */
+  struct st_backup_metadata             tbl_metadata;
+  ulonglong                             tbl_data_size;
+};
+
+/*
+  Database.
+
+  The dynamic array holds elements of the following type:
+
+  struct st_backup_table                db_tables
+  struct st_backup_perdb                db_perdbs
+
+  note: db_item must be first element in st_backup_database.
+*/
+struct st_backup_database
+{
+  struct st_bstream_db_info             db_item;        /* must be 1st */
+  struct st_backup_metadata             db_metadata;
+  DYNAMIC_ARRAY                         db_tables;
+  DYNAMIC_ARRAY                         db_perdbs;
+};
+
+/*
+  Snapshot.
+
+  Tables belong to databases. But in the table data chunks they are
+  numbered by snapshot number and table number. The table number is
+  relative to the snapshot. To find the table item within its database
+  we need an index from the table number (pos) within the snapshot
+  to the table item.
+
+  For every snapshot there is a struct st_backup_snapshot with an
+  array that has a reference per table of that snapshot.
+
+  The dynamic array holds elements of the following type:
+
+  struct st_backup_table*               snap_index_pos_to_table
+*/
+struct st_backup_snapshot
+{
+  DYNAMIC_ARRAY                         snap_index_pos_to_table;
+};
+
+/*
+  =========================
+  Stream reading functions.
+  =========================
+*/
+
+/* The below shall also be usable by C++. */
+C_MODE_START
+
+struct st_backup_catalog*
+backup_catalog_allocate(void);
+
+void
+backup_catalog_free(struct st_backup_catalog *bup_catalog);
+
+void*
+backup_image_open(const char *filename, struct st_backup_catalog *bup_catalog);
+
+void
+backup_image_close(void* image_handle);
+
+enum enum_bstream_ret_codes
+backup_read_catalog(void* image_handle, struct st_backup_catalog *bup_catalog);
+
+enum enum_bstream_ret_codes
+backup_read_metadata(void* image_handle, struct st_backup_catalog *bup_catalog);
+
+enum enum_bstream_ret_codes
+backup_read_snapshot(void* image_handle, struct st_backup_catalog *bup_catalog,
+                     struct st_bstream_data_chunk *snapshot);
+
+enum enum_bstream_ret_codes
+backup_read_summary(void* image_handle, struct st_backup_catalog *bup_catalog);
+
+struct st_backup_database*
+backup_locate_database(struct st_backup_catalog *bup_catalog,
+                       ulong pos);
+
+struct st_backup_table*
+backup_locate_table(struct st_backup_catalog *bup_catalog,
+                    ulong snap_num, ulong pos);
+
+struct st_backup_perdb*
+backup_locate_perdb(struct st_backup_catalog *bup_catalog,
+                    ulong db_pos, ulong pos);
+
+/*
+  =================================
+  Convenience functions and macros.
+  =================================
+*/
+
+/* Backup blob length. */
+ulong BBL(struct st_blob *blob);
+
+/* Backup blob string. */
+char *BBS(struct st_blob *blob);
+
+/*
+  Backup blob length and string.
+  This is for use with printf format '%.*s'.
+  This must be a macro because it produces two comma separated values!
+*/
+#define BBLS(_b_)       ((uint) BBL(_b_)), BBS(_b_)
+
+/* The above shall also be usable by C++. */
+C_MODE_END
+

=== added file 'client/mysqlbackup.cc'
--- a/client/mysqlbackup.cc	1970-01-01 00:00:00 +0000
+++ b/client/mysqlbackup.cc	2008-10-29 15:25:00 +0000
@@ -0,0 +1,1383 @@
+/* Copyright (C) 2001-2004 MySQL AB
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+
+/*
+  MySQL Backup Utility
+*/
+
+/* Include client related stuff, which includes a lot of common stuff. */
+#include "client_priv.h"
+/* Include special stuff. */
+#include <my_time.h>
+
+/* As long as we don't connect to the server, we are not a MYSQL_CLIENT. */
+#undef MYSQL_CLIENT
+
+/*
+  Include from the stream access functions.
+*/
+#include "backup_stream.h"
+
+/*
+  Include standard stuff.
+*/
+#include <ctype.h>
+
+/*
+  Configuration file.
+*/
+static const char *load_default_groups[]= { "mysqlbackup",
+#ifdef MYSQL_CLIENT
+                                            "client",
+#endif
+                                            NULL };
+
+/*
+  Command line options.
+*/
+
+/* General options. */
+static uint             opt_verbose;
+static ulong            opt_open_files_limit;
+#ifndef DBUG_OFF
+static const char *default_dbug_option = "d:t:o,/tmp/mysqlbackup.trace";
+#endif
+
+#ifdef MYSQL_CLIENT
+/* Options required by a MySQL client (connecting to a server). */
+static const char       *opt_database;
+static const char       *opt_host;
+static char             *opt_pass;
+static int              opt_port;
+static uint             opt_protocol;
+static const char       *opt_sock;
+static const char       *opt_user;
+#endif
+
+/* mysqlbackup specific options. */
+static bool             opt_mysqlbackup_catalog_summary;
+static bool             opt_mysqlbackup_catalog_details;
+static bool             opt_mysqlbackup_metadata_statements;
+static bool             opt_mysqlbackup_metadata_extra;
+static bool             opt_mysqlbackup_snapshots;
+static bool             opt_mysqlbackup_data_chunks;
+static bool             opt_mysqlbackup_data_totals;
+static bool             opt_mysqlbackup_summary;
+static bool             opt_mysqlbackup_exact;
+static const char       *opt_mysqlbackup_search;
+enum options_mysqlbackup
+{
+  OPT_MYSQLBACKUP_CATALOG_SUMMARY=1024,
+  OPT_MYSQLBACKUP_CATALOG_DETAILS,
+  OPT_MYSQLBACKUP_METADATA_STATEMENTS,
+  OPT_MYSQLBACKUP_METADATA_EXTRA,
+  OPT_MYSQLBACKUP_SNAPSHOTS,
+  OPT_MYSQLBACKUP_DATA_CHUNKS,
+  OPT_MYSQLBACKUP_DATA_TOTALS,
+  OPT_MYSQLBACKUP_SUMMARY,
+  OPT_MYSQLBACKUP_ALL,
+  OPT_MYSQLBACKUP_EXACT,
+  OPT_MYSQLBACKUP_SEARCH,
+
+  /* End of options terminator. */
+  OPT_MYSQLBACKUP_LAST
+};
+
+static struct my_option my_long_options[] =
+{
+  /* General options. */
+  {"help", '?', "Display this help and exit.",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+#ifdef __NETWARE__
+  {"autoclose", OPT_AUTO_CLOSE, "Auto close the screen on exit for Netware.",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+#endif
+#ifndef DBUG_OFF
+  {"debug", '#', "Output debug log.", (uchar**) &default_dbug_option,
+   (uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+#endif
+  {"verbose", 'v', "Print verbose information.",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+  {"version", 'V', "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
+   0, 0, 0, 0, 0},
+  {"open_files_limit", OPT_OPEN_FILES_LIMIT,
+   "Used to reserve file descriptors for usage by this program.",
+   (uchar**) &opt_open_files_limit, (uchar**) &opt_open_files_limit,
+   0, GET_ULONG, REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
+
+#ifdef MYSQL_CLIENT
+  /* Options required by a MySQL client (connecting to a server). */
+  {"database", 'd', "Unused.",
+   (uchar**) &opt_database, (uchar**) &opt_database,
+   0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"host", 'h', "Unused.",
+   (uchar**) &opt_host, (uchar**) &opt_host,
+   0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"password", 'p', "Unused.",
+   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+  {"port", 'P', "Unused.",
+   (uchar**) &opt_port, (uchar**) &opt_port, 0, GET_INT, REQUIRED_ARG,
+   0, 0, 0, 0, 0, 0},
+  {"protocol", OPT_MYSQL_PROTOCOL, "Unused.",
+   0, 0, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"socket", 'S', "Unused.",
+   (uchar**) &opt_sock, (uchar**) &opt_sock,
+   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"user", 'u', "Unused.",
+   (uchar**) &opt_user, (uchar**) &opt_user,
+   0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif /*MYSQL_CLIENT*/
+
+  /* mysqlbackup specific options. */
+  {"catalog-summary", OPT_MYSQLBACKUP_CATALOG_SUMMARY,
+   "Print summary from the database objects catalog.",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+
+  {"catalog-details", OPT_MYSQLBACKUP_CATALOG_DETAILS,
+   "Print details from the database objects catalog.",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+
+  {"metadata-statements", OPT_MYSQLBACKUP_METADATA_STATEMENTS,
+   "Print SQL statements to create the database objects.",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+
+  {"metadata-extra", OPT_MYSQLBACKUP_METADATA_EXTRA,
+   "Print extra meta data for the database objects.",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+
+  {"snapshots", OPT_MYSQLBACKUP_SNAPSHOTS,
+   "Print information about snapshots contained in the backup image.",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+
+  {"data-chunks", OPT_MYSQLBACKUP_DATA_CHUNKS,
+   "Print length of every data chunk contained in the backup image.",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+
+  {"data-totals", OPT_MYSQLBACKUP_DATA_TOTALS,
+   "Print length of data contained in the backup image for each object.",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+
+  {"summary", OPT_MYSQLBACKUP_SUMMARY,
+   "Print summary information from end of the backup image.",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+
+  {"all", OPT_MYSQLBACKUP_ALL,
+   "Print everything except snapshots and data-chunks.",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+
+  {"exact", OPT_MYSQLBACKUP_EXACT,
+   "Print exact number of bytes instead of human readable form.",
+   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+
+  {"search", OPT_MYSQLBACKUP_SEARCH,
+   "Search object in the backup image. "
+   "Name can be object or database.object. "
+   "Quoting of database and/or object with \", ', or ` is allowed. "
+   "Wildcards % and _ are available. "
+   "Use with --metadata-* options to see meta data. "
+   "Plain name finds global objects, name1.name2 finds per db objects.",
+   (uchar**) &opt_mysqlbackup_search, (uchar**) &opt_mysqlbackup_search,
+   0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+
+  /* End of options terminator. */
+  {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+
+#include <help_start.h>
+
+static void print_version(void)
+{
+  printf("%s Ver 1.0 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
+  NETWARE_SET_SCREEN_MODE(1);
+}
+
+
+static void usage(void)
+{
+  print_version();
+  puts("By Sun Microsystems, for your professional use\n\
+This software comes with NO WARRANTY:  This is free software,\n\
+and you are welcome to modify and redistribute it under the GPL license\n");
+
+  printf("Displays information from a backup image.\n\n");
+  printf("Usage: %s [options] backup-image-file\n", my_progname);
+  my_print_help(my_long_options);
+  my_print_variables(my_long_options);
+}
+
+#include <help_end.h>
+
+
+/**
+  Treat some options specially.
+
+  Called for each option that appears on the command line.
+*/
+
+extern "C" my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+               char *argument)
+{
+#ifdef MYSQL_CLIENT
+  bool tty_password=0;
+#endif
+
+  switch (optid) {
+  /* General options. */
+#ifdef __NETWARE__
+  case OPT_AUTO_CLOSE:
+    setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
+    break;
+#endif
+#ifndef DBUG_OFF
+  case '#':
+    DBUG_PUSH(argument ? argument : default_dbug_option);
+    break;
+#endif
+  case 'v':
+    if (argument == disabled_my_option)
+      opt_verbose= 0;
+    else
+      opt_verbose++;
+    break;
+  case 'V':
+    print_version();
+    exit(0);
+  case '?':
+    usage();
+    exit(0);
+
+#ifdef MYSQL_CLIENT
+  /* Options required by a MySQL client (connecting to a server). */
+  case 'p':
+    if (argument)
+    {
+      my_free(opt_pass,MYF(MY_ALLOW_ZERO_PTR));
+      char *start=argument;
+      opt_pass= my_strdup(argument,MYF(MY_FAE));
+      while (*argument) *argument++= 'x';		/* Destroy argument */
+      if (*start)
+        start[1]=0;				/* Cut length of argument */
+    }
+    else
+      tty_password=1;
+    break;
+  case OPT_MYSQL_PROTOCOL:
+    opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
+                                    opt->name);
+    break;
+#endif /*MYSQL_CLIENT*/
+
+  /* mysqlbackup specific options. */
+  case OPT_MYSQLBACKUP_CATALOG_SUMMARY:
+    opt_mysqlbackup_catalog_summary= TRUE;
+    break;
+  case OPT_MYSQLBACKUP_CATALOG_DETAILS:
+    opt_mysqlbackup_catalog_details= TRUE;
+    break;
+  case OPT_MYSQLBACKUP_METADATA_STATEMENTS:
+    opt_mysqlbackup_metadata_statements= TRUE;
+    break;
+  case OPT_MYSQLBACKUP_METADATA_EXTRA:
+    opt_mysqlbackup_metadata_extra= TRUE;
+    break;
+  case OPT_MYSQLBACKUP_SNAPSHOTS:
+    opt_mysqlbackup_snapshots= TRUE;
+    break;
+  case OPT_MYSQLBACKUP_DATA_CHUNKS:
+    opt_mysqlbackup_data_chunks= TRUE;
+    break;
+  case OPT_MYSQLBACKUP_DATA_TOTALS:
+    opt_mysqlbackup_data_totals= TRUE;
+    break;
+  case OPT_MYSQLBACKUP_SUMMARY:
+    opt_mysqlbackup_summary= TRUE;
+    break;
+  case OPT_MYSQLBACKUP_ALL:
+    opt_mysqlbackup_catalog_summary= TRUE;
+    opt_mysqlbackup_catalog_details= TRUE;
+    opt_mysqlbackup_metadata_statements= TRUE;
+    opt_mysqlbackup_metadata_extra= TRUE;
+    opt_mysqlbackup_data_totals= TRUE;
+    opt_mysqlbackup_summary= TRUE;
+    break;
+  case OPT_MYSQLBACKUP_EXACT:
+    opt_mysqlbackup_exact= TRUE;
+    break;
+  }
+
+#ifdef MYSQL_CLIENT
+  if (tty_password)
+    opt_pass= get_tty_password(NullS);
+#endif /*MYSQL_CLIENT*/
+
+  return 0;
+}
+
+
+/**
+  Print a formatted time string.
+*/
+
+int print_time(bstream_time_t *time)
+{
+  DBUG_ASSERT(time);
+  return printf("%04d-%02d-%02d %02d:%02d:%02d UTC",
+                time->year + 1900, time->mon + 1, time->mday,
+                time->hour, time->min, time->sec);
+}
+
+
+/**
+  Print a human readable number.
+
+  Numbers are shown as +-0..16384 with a postfix of "bytes",
+  or as +-16..16384 with a postfix of "KB", "MB", "GB", "TB", "PB", or "EB".
+  If one day longlong is > 64 bit, there can be higher numbers with "EB".
+  The range is not +-0..1024 or +-1..1024 because we would lose too much
+  accuracy. Using +-16..16384, we have at least two significant digits.
+  And, by chance, 16384 EB - 1 is exactly the highest possible value in a
+  64-bit value (if used unsigned, which we don't do here).
+*/
+
+static char *llstr_human(longlong value, char *buff)
+{
+  const char *postfixes[]= {"bytes", "KB", "MB", "GB", "TB", "PB", "EB", NULL};
+  const char **postfix_p= postfixes;
+  const char *src;
+  char       *dst;
+  DBUG_ASSERT(buff);
+
+  if (!opt_mysqlbackup_exact)
+  {
+    /* Shrink value while it's > 16K and postfix list is not at end. */
+    while (((value > 16383) || (value < -16384)) && *(++postfix_p))
+      value/= 1024;
+    /* Compensate the loop's ++postfix_p. */
+    if (value >= 16384)
+      --postfix_p;
+  }
+  /* Convert the number into a string. */
+  (void) llstr(value, buff);
+  /* Find end of destination string. */
+  for (dst= buff; *dst; dst++) {}
+  /* Get pointer to the source string. */
+  src= *postfix_p;
+  /* Append postfix, including the terminating '\0'. */
+  *(dst++)= ' ';
+  while ((*(dst++)= *(src++))) {}
+  /* Result is in buff. */
+  return buff;
+}
+
+
+/* Flags for print_item(). */
+#define PRI_NAME        0x0001
+#define PRI_META        0x0002
+
+
+/**
+  Print item information.
+
+  @parameter[in]        indent          indentation spaces
+  @parameter[in]        item_arg        reference to some item
+  @parameter[in]        what            flags describing what to print
+                                        PRI_NAME        item name
+                                        PRI_META        meta data
+*/
+
+void print_item(uint indent, void *item_arg, uint what)
+{
+  struct st_bstream_item_info   *item= (struct st_bstream_item_info*) item_arg;
+  struct st_blob                *db_name= NULL;
+  struct st_blob                *name;
+  struct st_backup_metadata     *mdata= NULL;
+  const char                    *type_s;
+  DBUG_ENTER("print_item");
+  DBUG_ASSERT(item);
+
+  name= &item->name;
+
+  switch (item->type) {
+  case BSTREAM_IT_CHARSET:
+  {
+    DBUG_PRINT("bupstrm", ("charset"));
+    type_s= "Character set";
+    break;
+  }
+
+  case BSTREAM_IT_USER:
+  {
+    DBUG_PRINT("bupstrm", ("user"));
+    type_s= "User";
+    break;
+  }
+
+  case BSTREAM_IT_PRIVILEGE:
+  {
+    DBUG_PRINT("bupstrm", ("privilege"));
+    type_s= "Privilege";
+    break;
+  }
+
+  case BSTREAM_IT_DB:
+  {
+    struct st_backup_database *dbase= (struct st_backup_database*) item;
+    DBUG_PRINT("bupstrm", ("database"));
+    type_s= "Database";
+    mdata= &dbase->db_metadata;
+    break;
+  }
+
+  case BSTREAM_IT_TABLE:
+  {
+    struct st_backup_table *tbl= (struct st_backup_table*) item;
+    DBUG_PRINT("bupstrm", ("table"));
+    type_s= "Table";
+    db_name= &tbl->tbl_item.base.db->base.name;
+    mdata= &tbl->tbl_metadata;
+    break;
+  }
+
+  case BSTREAM_IT_VIEW:
+  {
+    struct st_backup_perdb *perdb= (struct st_backup_perdb*) item;
+    DBUG_PRINT("bupstrm", ("view"));
+    type_s= "View";
+    db_name= &perdb->perdb_item.db->base.name;
+    mdata= &perdb->perdb_metadata;
+    break;
+  }
+
+  default:
+  {
+    DBUG_PRINT("bupstrm", ("unknown item type"));
+    type_s= "Unknown item type";
+    break;
+  }
+  }
+
+  if (what & PRI_NAME)
+  {
+    if (db_name)
+      printf("%*s%-6s '%.*s'.'%.*s'\n",
+             indent, "", type_s,
+             BBLS(db_name), BBLS(name));
+    else
+      printf("%*s%-6s '%.*s'\n",
+             indent, "", type_s,
+             BBLS(name));
+  }
+
+  if ((what & PRI_META) && mdata)
+  {
+    if (opt_mysqlbackup_metadata_statements)
+    {
+      if (db_name)
+        printf("%*s%s '%.*s'.'%.*s' statement: '%.*s'\n",
+               indent, "", type_s,
+               BBLS(db_name), BBLS(name), BBLS(&mdata->md_query));
+      else
+        printf("%*s%s '%.*s' statement: '%.*s'\n",
+               indent, "", type_s,
+               BBLS(name), BBLS(&mdata->md_query));
+    }
+
+    if (opt_mysqlbackup_metadata_extra)
+    {
+      if (db_name)
+        printf("%*s%s '%.*s'.'%.*s' extra data length: %lu\n",
+               indent, "", type_s,
+               BBLS(db_name), BBLS(name), BBL(&mdata->md_data));
+      else
+        printf("%*s%s '%.*s' extra data length: %lu\n",
+               indent, "", type_s,
+               BBLS(name), BBL(&mdata->md_data));
+    }
+  }
+
+  DBUG_VOID_RETURN;
+}
+
+
+/**
+  Print error from parsing the search name.
+
+  @param[in]    format          printf-style format string
+  @param[in]    args            list of arguments for the format string
+*/
+
+static void error_parse_search_name(const char *format, ...)
+  ATTRIBUTE_FORMAT(printf, 1, 2);
+static void error_parse_search_name(const char *format, ...)
+{
+  va_list args;
+  DBUG_ASSERT(format);
+
+  fprintf(stderr, "\nERROR: Cannot parse search name.\n");
+  va_start(args, format);
+  vfprintf(stderr, format, args);
+  va_end(args);
+  fprintf(stderr, "\n");
+}
+
+
+/**
+  Parse the search name.
+
+  Split search name into database name, if present, and object name.
+
+  @param[in]    search_name             search name
+  @param[out]   search_database_name_p  database name
+  @param[out]   search_object_name_p    object name
+
+  @return       status
+    @retval     0                       ok
+    @retval     != 0                    error
+*/
+
+static int parse_search_name(const char *search_name,
+                             char **search_database_name_p,
+                             char **search_object_name_p)
+{
+  char          *database= NULL;
+  char          *object;
+  const char    *token;
+  const char    *tend;
+  int           rc= 1; /* Assume error. */
+  char          quote;
+  DBUG_ENTER("parse_search_name");
+  DBUG_ASSERT(search_name);
+  DBUG_ASSERT(search_database_name_p);
+  DBUG_ASSERT(search_object_name_p);
+  DBUG_PRINT("mysqlbackup", ("searching '%s'\n", search_name));
+
+  /* Skip leading space. */
+  for (token= search_name; isspace(*token); token++) {}
+  /*
+    Check for quoted search string.
+    If unquoted, terminate by dot or space.
+  */
+  quote= '.';
+  switch (*token) {
+  case '\'':
+  case '\"':
+  case '`':
+    quote= *(token++);
+  }
+  /* Find end of token. */
+  if (quote == '.')
+    for (tend= token; *tend && (*tend != quote) && !isspace(*tend); tend++) {}
+  else
+    for (tend= token; *tend && (*tend != quote); tend++) {}
+  /* Copy token into object name. */
+  object= (char*) my_memdup(token, (size_t) (tend - token + 1),
+                            MYF(MY_WME));
+  object[tend - token]= '\0';
+  if (*tend)
+  {
+    /* Found quote or dot or space. */
+    if (quote != '.')
+    {
+      /* Found quote. Skip it. */
+      tend++;
+    }
+    /* Skip trailing space. */
+    for (; isspace(*tend); tend++) {}
+    if (*tend == '.')
+    {
+      /* Object name was a database name. */
+      database= object;
+      object= NULL;
+      /* Skip dot. */
+      tend++;
+      /* We need an object name. Skip space. */
+      for (token= tend; isspace(*token); token++) {}
+      /* Check for quoted search string. If unquoted, search for end. */
+      quote= '\0';
+      switch (*token) {
+      case '\'':
+      case '\"':
+      case '`':
+        quote= *(token++);
+      }
+      /* Find end of token. */
+      if (quote == '\0')
+        for (tend= token; *tend && !isspace(*tend); tend++) {}
+      else
+        for (tend= token; *tend && (*tend != quote); tend++) {}
+      /* Copy token into object name. */
+      object= (char*) my_memdup(token, (size_t) (tend - token + 1),
+                                MYF(MY_WME));
+      object[tend - token]= '\0';
+      /* Check for correct syntax. */
+      if (*tend)
+      {
+        /* Found quote or space. */
+        if (quote != '\0')
+        {
+          /* Found quote. Skip it. */
+          tend++;
+        }
+        /* Skip trailing space. */
+        for (; isspace(*tend); tend++) {}
+        /* Now we must be at string end. */
+        if (*tend)
+        {
+          error_parse_search_name("Unrecognized stuff at '%s'\n", tend);
+          goto end;
+        }
+      }
+      else
+      {
+        /* End of string. */
+        if (quote != '\0')
+        {
+          error_parse_search_name("Search name improperly quoted.\n");
+          goto end;
+        }
+      }
+    }
+    else
+    {
+      if (*tend)
+      {
+        error_parse_search_name("Unrecognized stuff at '%s'\n", tend);
+        goto end;
+      }
+    }
+  }
+  else
+  {
+    /* End of string. */
+    if (quote != '.')
+    {
+      error_parse_search_name("Search name improperly quoted.\n");
+      goto end;
+    }
+  }
+
+  /* Everything looks fine. */
+  *search_database_name_p= database;
+  *search_object_name_p= object;
+  rc= 0;
+
+ end:
+  DBUG_RETURN(rc);
+}
+
+
+/**
+  Search backup object.
+
+  @param[in]    search_name             search name
+  @param[out]   search_database_name    database name, may be NULL
+  @param[out]   search_object_name      object name
+
+  @return       status
+    @retval     0                       ok
+    @retval     != 0                    error
+*/
+
+void
+search_object(struct st_backup_catalog *bup_catalog,
+              char *search_database_name,
+              char *search_object_name)
+{
+  struct st_backup_charset    *chrset;
+  struct st_backup_database   *dbase;
+  struct st_blob              *name;
+  uint                        search_database_name_len;
+  uint                        search_object_name_len;
+  uint                        idx;
+  DBUG_ENTER("search_object");
+  DBUG_ASSERT(bup_catalog);
+  /* search_database_name may be NULL. */
+  DBUG_ASSERT(search_object_name);
+
+  printf("\n");
+  if (search_database_name)
+    printf("Searching '%s'.'%s'\n", search_database_name, search_object_name);
+  else
+    printf("Searching '%s'\n", search_object_name);
+
+  if (search_database_name)
+    search_database_name_len= strlen(search_database_name);
+  search_object_name_len= strlen(search_object_name);
+
+  if (!search_database_name)
+  {
+    /* Search character set. */
+    for (idx= 0; idx < bup_catalog->cat_charsets.elements; idx++)
+    {
+      chrset= (struct st_backup_charset*)
+        dynamic_array_ptr(&bup_catalog->cat_charsets, idx);
+      name= &chrset->cs_item.name;
+      if (!my_wildcmp(&my_charset_latin1, (char*) name->begin,
+                      (char*) name->end, (char*) search_object_name,
+                      (char*) search_object_name + search_object_name_len,
+                      '\\', '_', '%'))
+      {
+        print_item(2, chrset, PRI_NAME);
+      }
+    }
+
+    /* Search database. */
+    for (idx= 0; idx < bup_catalog->cat_databases.elements; idx++)
+    {
+      dbase= (struct st_backup_database*)
+        dynamic_array_ptr(&bup_catalog->cat_databases, idx);
+      name= &dbase->db_item.base.name;
+      if (!my_wildcmp(&my_charset_latin1, (char*) name->begin,
+                      (char*) name->end, (char*) search_object_name,
+                      (char*) search_object_name + search_object_name_len,
+                      '\\', '_', '%'))
+      {
+        print_item(2, dbase, PRI_NAME | PRI_META);
+      }
+    }
+    goto end;
+  }
+
+  /* Search object within databases. */
+  for (idx= 0; idx < bup_catalog->cat_databases.elements; idx++)
+  {
+    struct st_backup_database   *dbase;
+
+    dbase= (struct st_backup_database*)
+      dynamic_array_ptr(&bup_catalog->cat_databases, idx);
+    name= &dbase->db_item.base.name;
+    if (!my_wildcmp(&my_charset_latin1, (char*) name->begin,
+                    (char*) name->end, (char*) search_database_name,
+                    (char*) search_database_name + search_database_name_len,
+                    '\\', '_', '%'))
+    {
+      struct st_backup_table  *tbl;
+      struct st_backup_perdb  *perdb;
+      uint                    jdx;
+
+      /* Tables. */
+      for (jdx= 0; jdx < dbase->db_tables.elements; jdx++)
+      {
+        tbl= (struct st_backup_table*)
+          dynamic_array_ptr(&dbase->db_tables, jdx);
+        name= &tbl->tbl_item.base.base.name;
+        if (!my_wildcmp(&my_charset_latin1, (char*) name->begin,
+                        (char*) name->end, (char*) search_object_name,
+                        (char*) search_object_name + search_object_name_len,
+                        '\\', '_', '%'))
+        {
+          print_item(4, tbl, PRI_NAME | PRI_META);
+        }
+      }
+
+      /* Perdb items. */
+      for (jdx= 0; jdx < dbase->db_perdbs.elements; jdx++)
+      {
+        perdb= (struct st_backup_perdb*)
+          dynamic_array_ptr(&dbase->db_perdbs, jdx);
+        name= &perdb->perdb_item.base.name;
+        if (!my_wildcmp(&my_charset_latin1, (char*) name->begin,
+                        (char*) name->end, (char*) search_object_name,
+                        (char*) search_object_name + search_object_name_len,
+                        '\\', '_', '%'))
+        {
+          print_item(4, perdb, PRI_NAME | PRI_META);
+        }
+      }
+    }
+  }
+
+ end:
+  DBUG_VOID_RETURN;
+}
+
+
+/**
+  Read and print summary.
+
+  The summary section may be inside the image header or at image end.
+
+  @param[in]    image_handle            image handle reference
+  @param[in]    bup_catalog             catalog reference
+
+  @return       status
+    @retval     BSTREAM_OK              ok
+    @retval     != BSTREAM_OK           error
+*/
+
+enum enum_bstream_ret_codes
+read_and_print_summary(void *image_handle,
+                       struct st_backup_catalog *bup_catalog)
+{
+  struct st_bstream_image_header        *hdr= &bup_catalog->cat_header;
+  enum enum_bstream_ret_codes           brc;
+  DBUG_ENTER("read_and_print_summary");
+  DBUG_ASSERT(image_handle);
+  DBUG_ASSERT(bup_catalog);
+
+  /*
+    Read summary.
+  */
+  brc= backup_read_summary(image_handle, bup_catalog);
+  if (brc != BSTREAM_OK)
+  {
+    goto end;
+  }
+
+  /*
+    Print summary.
+  */
+  if (opt_mysqlbackup_summary)
+  {
+    printf("\n");
+    printf("Summary:\n");
+    printf("\n");
+    printf("Creation time:       ");
+    print_time(&hdr->start_time);
+    printf("\n");
+    printf("Validity time:       ");
+    print_time(&hdr->vp_time);
+    printf("\n");
+    printf("Finish   time:       ");
+    print_time(&hdr->end_time);
+    printf("\n");
+
+    /*
+      Binlog coordinates are present, if the BSTREAM_FLAG_BINLOG flag is
+      set in the header *and* table data are in the image.
+      DBUG_ASSERT(!(hdr->flags & BSTREAM_FLAG_BINLOG) ||
+                  hdr->binlog_pos.file || hdr->binlog_group.file);
+    */
+    if ((hdr->flags & BSTREAM_FLAG_BINLOG) &&
+        (hdr->binlog_pos.file || hdr->binlog_group.file))
+    {
+      printf("Binlog coordinates:  %s:%lu\n",
+             hdr->binlog_pos.file ? hdr->binlog_pos.file : "[NULL]",
+             hdr->binlog_pos.pos);
+      printf("Binlog group coords: %s:%lu\n",
+             hdr->binlog_group.file ? hdr->binlog_group.file : "[NULL]",
+             hdr->binlog_group.pos);
+    }
+    else
+    {
+      printf("No binlog information\n");
+    }
+  }
+
+ end:
+  DBUG_RETURN(brc);
+}
+
+
+/*
+  =============
+  Main program.
+  =============
+*/
+
+/**
+  Main
+
+  @parameter[in]        argc            argument count
+  @parameter[in]        argv            argument vector
+
+  @return               status
+    @retval             0               ok
+    @retval             != 0            error
+*/
+
+int main(int argc, char** argv)
+{
+  char                                  **defaults_argv;
+  void                                  *image_handle;
+  char                                  *search_database_name;
+  char                                  *search_object_name;
+  struct st_backup_catalog              *bup_catalog= NULL;
+  struct st_bstream_image_header        *hdr;
+  enum enum_bstream_ret_codes           brc;
+  int                                   rc;
+  uint                                  idx;
+  int                                   errpos= 0;
+  char                                  llbuff[22];
+
+  /* Preparations */
+  MY_INIT(argv[0]);
+  DBUG_ENTER("main");
+  DBUG_PROCESS(argv[0]);
+  my_init_time(); // for time functions
+  load_defaults("my", load_default_groups, &argc, &argv);
+  defaults_argv= argv;
+  errpos= 10;
+  rc= handle_options(&argc, &argv, my_long_options, get_one_option);
+  if (rc)
+    goto end;
+  errpos= 20;
+  if (argc != 1)
+  {
+    fprintf(stderr, "\nERROR: incorrect number of arguments.\n\n");
+    rc= 1;
+    goto use_err;
+  }
+  if (opt_mysqlbackup_search)
+  {
+    if (parse_search_name(opt_mysqlbackup_search, &search_database_name,
+                          &search_object_name))
+    {
+      rc= 1;
+      goto use_err;
+    }
+  }
+  my_set_max_open_files(opt_open_files_limit);
+
+  /*
+    Allocate catalog.
+  */
+  bup_catalog= backup_catalog_allocate();
+  if (!bup_catalog)
+  {
+    rc= 2;
+    goto end;
+  }
+  errpos= 30;
+
+  /*
+    Open backup image stream.
+  */
+  image_handle= backup_image_open(argv[0], bup_catalog);
+  if (!image_handle)
+  {
+    rc= 2;
+    goto end;
+  }
+  errpos= 40;
+
+  /*
+    Print backup image stream header.
+  */
+  hdr= &bup_catalog->cat_header;
+  printf("\n");
+  printf("Image path:          '%s'\n",
+         bup_catalog->cat_image_path);
+  printf("Image size:          %s\n",
+         llstr_human(bup_catalog->cat_image_size, llbuff));
+  printf("Image compression:   %s\n", bup_catalog->cat_zalgo);
+  printf("Image version:       %u\n", hdr->version);
+  printf("Creation time:       ");
+  print_time(&hdr->start_time);
+  printf("\n");
+  printf("Server version:      %d.%d.%d (%.*s)\n",
+         hdr->server_version.major, hdr->server_version.minor,
+         hdr->server_version.release, BBLS(&hdr->server_version.extra));
+  if (hdr->flags && opt_verbose)
+  {
+    const char  *separators[]= {"", ", "};
+    int         separator= 0;
+
+    printf("Image options:       ");
+    if (hdr->flags & BSTREAM_FLAG_INLINE_SUMMARY)
+    {
+      printf("%sINLINE_SUMMARY", separators[separator]);
+      separator= 1;
+    }
+    if (hdr->flags & BSTREAM_FLAG_BIG_ENDIAN)
+    {
+      printf("%sBIG_ENDIAN", separators[separator]);
+      separator= 1;
+    }
+    if (hdr->flags & BSTREAM_FLAG_BINLOG)
+    {
+      printf("%sBINLOG", separators[separator]);
+      separator= 1;
+    }
+    printf("\n");
+  }
+  if (opt_mysqlbackup_snapshots)
+    printf("Snapshot count:      %u\n", hdr->snap_count);
+
+  if (opt_mysqlbackup_snapshots)
+  {
+    printf("\n");
+    printf("Snapshots:\n");
+    printf("\n");
+    for (idx= 0; idx < hdr->snap_count; idx++)
+    {
+      struct st_bstream_snapshot_info     *snapshot= hdr->snapshot + idx;
+      const char                          *snap_type;
+
+      switch (snapshot->type) {
+      case BI_NATIVE:     snap_type= "native from";
+        break;
+      case BI_DEFAULT:    snap_type= "logical from locked tables";
+        break;
+      case BI_CS:         snap_type= "logical from consistent snapshot";
+        break;
+      case BI_NODATA:     snap_type= "nodata";
+        break;
+      default:            snap_type= "unknown/illegal";
+        break;
+      }
+      if (snapshot->type == BI_NATIVE)
+        printf("  Snapshot %u type    %s '%.*s'  version %u.%u\n",
+               idx, snap_type,
+               BBLS(&snapshot->engine.name),
+               snapshot->engine.major, snapshot->engine.minor);
+      else
+        printf("  Snapshot %u type    %s\n", idx, snap_type);
+      printf("  Snapshot %u version %u\n", idx, snapshot->version);
+      if (snapshot->options)
+        printf("  Snapshot %u options %u\n", idx, snapshot->options);
+      printf("  Snapshot %u tables  %lu\n", idx, snapshot->table_count);
+    }
+  }
+
+  if (hdr->flags & BSTREAM_FLAG_INLINE_SUMMARY)
+  {
+    brc= read_and_print_summary(image_handle, bup_catalog);
+    if (brc != BSTREAM_OK)
+    {
+      rc= 2;
+      goto end;
+    }
+  }
+
+  /* Save image reading time if the rest is not wanted. */
+  if (!opt_mysqlbackup_search &&
+      !opt_mysqlbackup_catalog_summary &&
+      !opt_mysqlbackup_catalog_details &&
+      !opt_mysqlbackup_metadata_statements &&
+      !opt_mysqlbackup_metadata_extra &&
+      !opt_mysqlbackup_data_chunks &&
+      !opt_mysqlbackup_data_totals &&
+      (!opt_mysqlbackup_summary || (hdr->flags & BSTREAM_FLAG_INLINE_SUMMARY)))
+    goto end;
+
+  /*
+    Read catalog.
+  */
+  brc= backup_read_catalog(image_handle, bup_catalog);
+  if (brc != BSTREAM_OK)
+  {
+    rc= 2;
+    goto end;
+  }
+
+  /*
+    Print catalog.
+  */
+  if (opt_mysqlbackup_catalog_summary)
+  {
+    ulong sum_tbl;
+    ulong sum_perdb;
+
+    printf("\n");
+    printf("Catalog summary:\n");
+    printf("\n");
+    printf("  Character sets:         %u\n",
+           bup_catalog->cat_charsets.elements);
+    printf("  Databases:              %u\n",
+           bup_catalog->cat_databases.elements);
+    sum_tbl= 0;
+    sum_perdb= 0;
+    for (idx= 0; idx < bup_catalog->cat_databases.elements; idx++)
+    {
+      struct st_backup_database   *dbase;
+
+      dbase= (struct st_backup_database*)
+        dynamic_array_ptr(&bup_catalog->cat_databases, idx);
+      sum_tbl+= dbase->db_tables.elements;
+      sum_perdb+= dbase->db_perdbs.elements;
+    }
+    printf("  Tables:                 %lu\n", sum_tbl);
+    printf("  Other per db objects:   %lu\n", sum_perdb);
+  }
+  if (opt_mysqlbackup_catalog_details)
+  {
+    struct st_backup_charset    *chrset;
+    struct st_backup_database   *dbase;
+
+    printf("\n");
+    printf("Catalog details:\n");
+    printf("\n");
+
+    /* Charsets. */
+    for (idx= 0; idx < bup_catalog->cat_charsets.elements; idx++)
+    {
+      chrset= (struct st_backup_charset*)
+        dynamic_array_ptr(&bup_catalog->cat_charsets, idx);
+      print_item(2, chrset, PRI_NAME);
+    }
+
+    /* Databases. */
+    for (idx= 0; idx < bup_catalog->cat_databases.elements; idx++)
+    {
+      dbase= (struct st_backup_database*)
+        dynamic_array_ptr(&bup_catalog->cat_databases, idx);
+      print_item(2, dbase, PRI_NAME);
+
+      /* Tables. */
+      {
+        struct st_backup_table  *tbl;
+        uint                    jdx;
+
+        for (jdx= 0; jdx < dbase->db_tables.elements; jdx++)
+        {
+          tbl= (struct st_backup_table*)
+            dynamic_array_ptr(&dbase->db_tables, jdx);
+          print_item(4, tbl, PRI_NAME);
+        }
+      }
+
+      /* Perdbs. */
+      {
+        struct st_backup_perdb  *perdb;
+        uint                    jdx;
+
+        for (jdx= 0; jdx < dbase->db_perdbs.elements; jdx++)
+        {
+          perdb= (struct st_backup_perdb*)
+            dynamic_array_ptr(&dbase->db_perdbs, jdx);
+          print_item(4, perdb, PRI_NAME);
+        }
+      }
+    }
+  }
+
+  /*
+    If user wants to search in catalog, but is not interested in meta
+    data, we can do the search now, before reading the meta data.
+  */
+  if (opt_mysqlbackup_search &&
+      !opt_mysqlbackup_metadata_statements &&
+      !opt_mysqlbackup_metadata_extra)
+  {
+    search_object(bup_catalog, search_database_name, search_object_name);
+    goto end;
+  }
+
+  /* Save image reading time if the rest is not wanted. */
+  if (!opt_mysqlbackup_search &&
+      !opt_mysqlbackup_metadata_statements &&
+      !opt_mysqlbackup_metadata_extra &&
+      !opt_mysqlbackup_data_chunks &&
+      !opt_mysqlbackup_data_totals &&
+      (!opt_mysqlbackup_summary || (hdr->flags & BSTREAM_FLAG_INLINE_SUMMARY)))
+    goto end;
+
+  /*
+    Read meta data.
+  */
+  brc= backup_read_metadata(image_handle, bup_catalog);
+  if (brc != BSTREAM_OK)
+  {
+    rc= 2;
+    goto end;
+  }
+
+  if (opt_mysqlbackup_search)
+  {
+    search_object(bup_catalog, search_database_name, search_object_name);
+    goto end;
+  }
+
+  /*
+    Print meta data.
+  */
+  if (opt_mysqlbackup_metadata_statements || opt_mysqlbackup_metadata_extra)
+  {
+    printf("\n");
+    printf("Meta data:\n");
+
+    for (idx= 0; idx < bup_catalog->cat_databases.elements; idx++)
+    {
+      struct st_backup_database *dbase;
+
+      dbase= (struct st_backup_database*)
+        dynamic_array_ptr(&bup_catalog->cat_databases, idx);
+      printf("\n");
+      print_item(2, dbase, PRI_META);
+
+      /* Tables. */
+      {
+        struct st_backup_table  *tbl;
+        uint                    jdx;
+
+        for (jdx= 0; jdx < dbase->db_tables.elements; jdx++)
+        {
+          tbl= (struct st_backup_table*)
+            dynamic_array_ptr(&dbase->db_tables, jdx);
+          printf("\n");
+          print_item(4, tbl, PRI_META);
+        }
+      }
+
+      /* Perdb items. */
+      {
+        struct st_backup_perdb  *perdb;
+        uint                    jdx;
+
+        for (jdx= 0; jdx < dbase->db_perdbs.elements; jdx++)
+        {
+          perdb= (struct st_backup_perdb*)
+            dynamic_array_ptr(&dbase->db_perdbs, jdx);
+          printf("\n");
+          print_item(4, perdb, PRI_META);
+        }
+      }
+    }
+  }
+
+  /* Save image reading time if the rest is not wanted. */
+  if (!opt_mysqlbackup_data_chunks &&
+      !opt_mysqlbackup_data_totals &&
+      (!opt_mysqlbackup_summary || (hdr->flags & BSTREAM_FLAG_INLINE_SUMMARY)))
+    goto end;
+
+  /*
+    Read table data.
+  */
+  if (opt_mysqlbackup_data_chunks)
+  {
+    printf("\n");
+    printf("Data chunks:\n");
+  }
+  do
+  {
+    struct st_bstream_data_chunk        snapshot;
+    struct st_backup_table              *tbl;
+    struct st_blob                      *tbl_name;
+    struct st_blob                      *db_name;
+
+    brc= backup_read_snapshot(image_handle, bup_catalog, &snapshot);
+    if (brc != BSTREAM_OK)
+      break;
+
+    /*
+      There can be a special "table" with number 0.
+      Normal tables start at number 1.
+    */
+    if (snapshot.table_num)
+    {
+      tbl= backup_locate_table(bup_catalog,
+                               snapshot.snap_num, snapshot.table_num - 1);
+      /* Accumulate data size. */
+      DBUG_ASSERT(!tbl->tbl_data_size ||
+                  (tbl->tbl_item.snap_num == snapshot.snap_num));
+      tbl->tbl_data_size+= BBL(&snapshot.data);
+      /* Get pointers to the names. */
+      tbl_name= &tbl->tbl_item.base.base.name;
+      db_name= &tbl->tbl_item.base.db->base.name;
+
+      if (opt_mysqlbackup_data_chunks)
+      {
+        if (opt_mysqlbackup_snapshots)
+          printf("  Snapshot %d has %lu bytes for table '%.*s'.'%.*s'\n",
+                 snapshot.snap_num, BBL(&snapshot.data),
+                 BBLS(db_name), BBLS(tbl_name));
+        else
+          printf("  Chunk has %lu bytes for table '%.*s'.'%.*s'\n",
+                 BBL(&snapshot.data), BBLS(db_name), BBLS(tbl_name));
+      }
+    }
+    else
+    {
+      if (opt_mysqlbackup_data_chunks)
+      {
+        if (opt_mysqlbackup_snapshots)
+          printf("  Snapshot %d has %lu bytes for special data\n",
+                 snapshot.snap_num, BBL(&snapshot.data));
+        else
+          printf("  Chunk has %lu bytes for special data\n",
+                 BBL(&snapshot.data));
+      }
+    }
+  } while (1);
+
+  if (opt_mysqlbackup_data_totals)
+  {
+    struct st_backup_database   *dbase;
+    struct st_backup_table      *tbl;
+    struct st_blob              *db_name;
+    struct st_blob              *tbl_name;
+    uint                        idx;
+    uint                        jdx;
+
+    printf("\n");
+    printf("Data totals:\n");
+    printf("\n");
+    for (idx= 0; idx < bup_catalog->cat_databases.elements; idx++)
+    {
+      dbase= (struct st_backup_database*)
+        dynamic_array_ptr(&bup_catalog->cat_databases, idx);
+      db_name= &dbase->db_item.base.name;
+
+      for (jdx= 0; jdx < dbase->db_tables.elements; jdx++)
+      {
+        tbl= (struct st_backup_table*)
+          dynamic_array_ptr(&dbase->db_tables, jdx);
+        tbl_name= &tbl->tbl_item.base.base.name;
+        if (opt_mysqlbackup_snapshots)
+          printf("  Snapshot %d has %s for table '%.*s'.'%.*s'\n",
+                 tbl->tbl_item.snap_num,
+                 llstr_human(tbl->tbl_data_size, llbuff),
+                 BBLS(db_name), BBLS(tbl_name));
+        else
+          printf("  Backup has %s for table '%.*s'.'%.*s'\n",
+                 llstr_human(tbl->tbl_data_size, llbuff),
+                 BBLS(db_name), BBLS(tbl_name));
+      }
+    }
+  }
+
+  if (!(hdr->flags & BSTREAM_FLAG_INLINE_SUMMARY))
+  {
+    brc= read_and_print_summary(image_handle, bup_catalog);
+    if (brc != BSTREAM_OK)
+    {
+      rc= 2;
+      goto end;
+    }
+  }
+
+  goto end;
+
+ use_err:
+  usage();
+  rc= 1;
+
+ end:
+  /* Cleanup. */
+  switch (errpos) {
+  default:
+  case 40:
+    backup_image_close(image_handle);
+  case 30:
+    backup_catalog_free(bup_catalog);
+  case 20:
+#ifdef MYSQL_CLIENT
+    my_free((char*) opt_database, MYF(MY_ALLOW_ZERO_PTR));
+    my_free((char*) opt_host, MYF(MY_ALLOW_ZERO_PTR));
+    my_free((char*) opt_pass, MYF(MY_ALLOW_ZERO_PTR));
+    my_free((char*) opt_user, MYF(MY_ALLOW_ZERO_PTR));
+#endif
+  case 10:
+    free_defaults(defaults_argv);
+  }
+  my_free_open_file_info();
+  /* We cannot free DBUG, it is used in global destructors after exit(). */
+  my_end(MY_DONT_FREE_DBUG);
+  DBUG_RETURN(rc);
+}
+

=== modified file 'mysql-test/mysql-test-run.pl'
--- a/mysql-test/mysql-test-run.pl	2008-10-07 17:04:28 +0000
+++ b/mysql-test/mysql-test-run.pl	2008-10-29 15:25:00 +0000
@@ -141,6 +141,7 @@ our $exe_master_mysqld;
 our $exe_mysql;
 our $exe_mysqladmin;
 our $exe_mysql_upgrade;
+our $exe_mysqlbackup;
 our $exe_mysqlbinlog;
 our $exe_myisamlog;
 our $exe_mysql_client_test;
@@ -1537,6 +1538,7 @@ sub executable_setup () {
   $exe_mysqldump=      mtr_exe_exists("$path_client_bindir/mysqldump");
   $exe_mysqlimport=    mtr_exe_exists("$path_client_bindir/mysqlimport");
   $exe_mysqlshow=      mtr_exe_exists("$path_client_bindir/mysqlshow");
+  $exe_mysqlbackup=    mtr_exe_exists("$path_client_bindir/mysqlbackup");
   $exe_mysqlbinlog=    mtr_exe_exists("$path_client_bindir/mysqlbinlog");
   $exe_mysqladmin=     mtr_exe_exists("$path_client_bindir/mysqladmin");
   $exe_mysql=          mtr_exe_exists("$path_client_bindir/mysql");
@@ -1953,6 +1955,20 @@ sub environment_setup () {
   $ENV{'MYSQL_SHOW'}= $cmdline_mysqlshow;
 
   # ----------------------------------------------------
+  # Setup env so childs can execute mysqlbackup
+  # ----------------------------------------------------
+  my $cmdline_mysqlbackup=
+    mtr_native_path($exe_mysqlbackup) .
+      " --no-defaults";
+
+  if ( $opt_debug )
+  {
+    $cmdline_mysqlbackup .=
+      " --debug=d:t:A,$path_vardir_trace/log/mysqlbackup.trace";
+  }
+  $ENV{'MYSQL_BACKUP'}= $cmdline_mysqlbackup;
+
+  # ----------------------------------------------------
   # Setup env so childs can execute mysqlbinlog
   # ----------------------------------------------------
   my $cmdline_mysqlbinlog=

=== added file 'mysql-test/suite/backup/r/backup_client.result'
--- a/mysql-test/suite/backup/r/backup_client.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/r/backup_client.result	2008-10-29 15:25:00 +0000
@@ -0,0 +1,2073 @@
+SET SESSION max_heap_table_size=67108864;
+DROP DATABASE IF EXISTS mysqltest1;
+DROP DATABASE IF EXISTS mysqltest2;
+DROP DATABASE IF EXISTS mysqltest3;
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+CREATE DATABASE mysqltest3;
+CREATE TABLE mysqltest1.t1 (
+c1 INT PRIMARY KEY AUTO_INCREMENT,
+c2 VARCHAR(30000)) ENGINE=MyISAM;
+INSERT INTO mysqltest1.t1 VALUES(NULL, REPEAT('A', 30000));
+INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+CREATE TABLE mysqltest1.t2 ENGINE=InnoDB AS SELECT * FROM mysqltest1.t1;
+CREATE TABLE mysqltest1.t3 ENGINE=MEMORY AS SELECT * FROM mysqltest1.t1;
+CREATE TABLE mysqltest2.t1 ENGINE=InnoDB AS SELECT * FROM mysqltest1.t1;
+CREATE TABLE mysqltest2.t2 ENGINE=MEMORY AS SELECT * FROM mysqltest1.t1;
+CREATE TABLE mysqltest2.t3 ENGINE=MyISAM AS SELECT * FROM mysqltest1.t1;
+CREATE TABLE mysqltest3.t1 ENGINE=MEMORY AS SELECT * FROM mysqltest1.t1;
+CREATE TABLE mysqltest3.t2 ENGINE=MyISAM AS SELECT * FROM mysqltest1.t1;
+CREATE TABLE mysqltest3.t3 ENGINE=InnoDB AS SELECT * FROM mysqltest1.t1;
+CREATE VIEW mysqltest1.v1 (c1, c2, c3, c4) AS
+SELECT c1, c2, c1 IN (SELECT c1+2 FROM mysqltest1.t1),
+c1 = ALL (SELECT c1 FROM mysqltest1.t1) FROM mysqltest1.t1;
+SHOW CREATE VIEW mysqltest1.v1;
+View	Create View	character_set_client	collation_connection
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v1` AS select `mysqltest1`.`t1`.`c1` AS `c1`,`mysqltest1`.`t1`.`c2` AS `c2`,`mysqltest1`.`t1`.`c1` in (select (`mysqltest1`.`t1`.`c1` + 2) AS `c1+2` from `mysqltest1`.`t1`) AS `c3`,`mysqltest1`.`t1`.`c1` = all (select `mysqltest1`.`t1`.`c1` AS `c1` from `mysqltest1`.`t1`) AS `c4` from `mysqltest1`.`t1`	latin1	latin1_swedish_ci
+CREATE VIEW mysqltest1.v2 AS SELECT c2, c3 FROM mysqltest1.v1;
+SHOW CREATE VIEW mysqltest1.v2;
+View	Create View	character_set_client	collation_connection
+v2	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v2` AS select `v1`.`c2` AS `c2`,`v1`.`c3` AS `c3` from `mysqltest1`.`v1`	latin1	latin1_swedish_ci
+CREATE VIEW mysqltest2.v1 (c1, c2, c3, c4) AS
+SELECT connection_id(), pi(), current_user(), version();
+SHOW CREATE VIEW mysqltest2.v1;
+View	Create View	character_set_client	collation_connection
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v1` AS select connection_id() AS `c1`,pi() AS `c2`,current_user() AS `c3`,version() AS `c4`	latin1	latin1_swedish_ci
+CREATE VIEW mysqltest2.v2 AS
+SELECT mysqltest2.t2.c1 AS c1, mysqltest2.t2.c2 AS c2
+FROM mysqltest2.t2, mysqltest2.t3 UNION ALL
+SELECT mysqltest2.t2.c1 AS c3, mysqltest2.t2.c2 AS c4
+FROM mysqltest2.t2, mysqltest2.t3;
+SHOW CREATE VIEW mysqltest2.v2;
+View	Create View	character_set_client	collation_connection
+v2	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v2` AS select `mysqltest2`.`t2`.`c1` AS `c1`,`mysqltest2`.`t2`.`c2` AS `c2` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`) union all select `mysqltest2`.`t2`.`c1` AS `c3`,`mysqltest2`.`t2`.`c2` AS `c4` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`)	latin1	latin1_swedish_ci
+CREATE VIEW mysqltest3.v1 (c1, c2) AS
+SELECT mysqltest1.v1.c1 AS c1, mysqltest2.v2.c1 AS c2
+FROM mysqltest1.v1, mysqltest2.v2
+WHERE mysqltest1.v1.c1 = mysqltest2.v2.c1;
+SHOW CREATE VIEW mysqltest3.v1;
+View	Create View	character_set_client	collation_connection
+v1	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v1` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` join `mysqltest2`.`v2`) where (`v1`.`c1` = `v2`.`c1`)	latin1	latin1_swedish_ci
+CREATE VIEW mysqltest3.v2 (c1, c2) AS
+SELECT mysqltest1.v1.c1 AS c1, mysqltest2.v2.c1 AS c2
+FROM mysqltest1.v1 LEFT JOIN mysqltest2.v2
+ON (mysqltest1.v1.c1 = mysqltest2.v2.c1);
+SHOW CREATE VIEW mysqltest3.v2;
+View	Create View	character_set_client	collation_connection
+v2	CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v2` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` left join `mysqltest2`.`v2` on((`v1`.`c1` = `v2`.`c1`)))	latin1	latin1_swedish_ci
+BACKUP DATABASE mysqltest1, mysqltest2, mysqltest3 TO 'mysqltest.bak';
+backup_id
+#
+
+Show help output:
+========
+mysqlbackup Ver # for # at #
+By Sun Microsystems, for your professional use
+This software comes with NO WARRANTY:  This is free software,
+and you are welcome to modify and redistribute it under the GPL license
+
+Displays information from a backup image.
+
+Usage: mysqlbackup [options] backup-image-file
+  -?, --help          Display this help and exit.
+  -#, --debug[=name]  Output debug log.
+  -v, --verbose       Print verbose information.
+  -V, --version       Print version and exit.
+  --open_files_limit=# 
+                      Used to reserve file descriptors for usage by this
+                      program.
+  --catalog-summary   Print summary from the database objects catalog.
+  --catalog-details   Print details from the database objects catalog.
+  --metadata-statements 
+                      Print SQL statements to create the database objects.
+  --metadata-extra    Print extra meta data for the database objects.
+  --snapshots         Print information about snapshots contained in the backup
+                      image.
+  --data-chunks       Print length of every data chunk contained in the backup
+                      image.
+  --data-totals       Print length of data contained in the backup image for
+                      each object.
+  --summary           Print summary information from end of the backup image.
+  --all               Print everything except snapshots and data-chunks.
+  --exact             Print exact number of bytes instead of human readable
+                      form.
+  --search=name       Search object in the backup image. Name can be object or
+                      database.object. Quoting of database and/or object with
+                      ", ', or ` is allowed. Wildcards % and _ are available.
+                      Use with --metadata-* options to see meta data. Plain
+                      name finds global objects, name1.name2 finds per db
+                      objects.
+
+Variables (--variable-name=value)
+and boolean options {FALSE|TRUE}  Value (after reading options)
+--------------------------------- -----------------------------
+debug                             d:t:o,/tmp/mysqlbackup.trace
+open_files_limit                  64
+search                            (No default value)
+========
+
+Minimal output without options:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+========
+
+Full set of most relevant information:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+
+Catalog summary:
+
+  Character sets:         2
+  Databases:              3
+  Tables:                 9
+  Other per db objects:   6
+
+Catalog details:
+
+  Character set 'utf8'
+  Character set 'utf8'
+  Database 'mysqltest1'
+    Table  'mysqltest1'.'t1'
+    Table  'mysqltest1'.'t2'
+    Table  'mysqltest1'.'t3'
+    View   'mysqltest1'.'v1'
+    View   'mysqltest1'.'v2'
+  Database 'mysqltest2'
+    Table  'mysqltest2'.'t1'
+    Table  'mysqltest2'.'t2'
+    Table  'mysqltest2'.'t3'
+    View   'mysqltest2'.'v1'
+    View   'mysqltest2'.'v2'
+  Database 'mysqltest3'
+    Table  'mysqltest3'.'t1'
+    Table  'mysqltest3'.'t2'
+    Table  'mysqltest3'.'t3'
+    View   'mysqltest3'.'v1'
+    View   'mysqltest3'.'v2'
+
+Meta data:
+
+  Database 'mysqltest1' statement: 'CREATE DATABASE `mysqltest1` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest1' extra data length: 0
+
+    Table 'mysqltest1'.'t1' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  `c2` varchar(30000) DEFAULT NULL,
+  PRIMARY KEY (`c1`)
+) ENGINE=MyISAM AUTO_INCREMENT=33 DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t1' extra data length: 0
+
+    Table 'mysqltest1'.'t2' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t2' extra data length: 0
+
+    Table 'mysqltest1'.'t3' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t3' extra data length: 0
+
+    View 'mysqltest1'.'v1' statement: 'USE `mysqltest1`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v1` AS select `mysqltest1`.`t1`.`c1` AS `c1`,`mysqltest1`.`t1`.`c2` AS `c2`,`mysqltest1`.`t1`.`c1` in (select (`mysqltest1`.`t1`.`c1` + 2) AS `c1+2` from `mysqltest1`.`t1`) AS `c3`,`mysqltest1`.`t1`.`c1` = all (select `mysqltest1`.`t1`.`c1` AS `c1` from `mysqltest1`.`t1`) AS `c4` from `mysqltest1`.`t1`'
+    View 'mysqltest1'.'v1' extra data length: 0
+
+    View 'mysqltest1'.'v2' statement: 'USE `mysqltest1`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v2` AS select `v1`.`c2` AS `c2`,`v1`.`c3` AS `c3` from `mysqltest1`.`v1`'
+    View 'mysqltest1'.'v2' extra data length: 0
+
+  Database 'mysqltest2' statement: 'CREATE DATABASE `mysqltest2` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest2' extra data length: 0
+
+    Table 'mysqltest2'.'t1' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t1` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t1' extra data length: 0
+
+    Table 'mysqltest2'.'t2' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t2' extra data length: 0
+
+    Table 'mysqltest2'.'t3' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t3' extra data length: 0
+
+    View 'mysqltest2'.'v1' statement: 'USE `mysqltest2`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v1` AS select connection_id() AS `c1`,pi() AS `c2`,current_user() AS `c3`,version() AS `c4`'
+    View 'mysqltest2'.'v1' extra data length: 0
+
+    View 'mysqltest2'.'v2' statement: 'USE `mysqltest2`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v2` AS select `mysqltest2`.`t2`.`c1` AS `c1`,`mysqltest2`.`t2`.`c2` AS `c2` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`) union all select `mysqltest2`.`t2`.`c1` AS `c3`,`mysqltest2`.`t2`.`c2` AS `c4` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`)'
+    View 'mysqltest2'.'v2' extra data length: 0
+
+  Database 'mysqltest3' statement: 'CREATE DATABASE `mysqltest3` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest3' extra data length: 0
+
+    Table 'mysqltest3'.'t1' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t1` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t1' extra data length: 0
+
+    Table 'mysqltest3'.'t2' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t2' extra data length: 0
+
+    Table 'mysqltest3'.'t3' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t3' extra data length: 0
+
+    View 'mysqltest3'.'v1' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v1` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` join `mysqltest2`.`v2`) where (`v1`.`c1` = `v2`.`c1`)'
+    View 'mysqltest3'.'v1' extra data length: 0
+
+    View 'mysqltest3'.'v2' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v2` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` left join `mysqltest2`.`v2` on((`v1`.`c1` = `v2`.`c1`)))'
+    View 'mysqltest3'.'v2' extra data length: 0
+
+Data totals:
+
+  Backup has 939 KB for table 'mysqltest1'.'t1'
+  Backup has 937 KB for table 'mysqltest1'.'t2'
+  Backup has 937 KB for table 'mysqltest1'.'t3'
+  Backup has 937 KB for table 'mysqltest2'.'t1'
+  Backup has 937 KB for table 'mysqltest2'.'t2'
+  Backup has 938 KB for table 'mysqltest2'.'t3'
+  Backup has 937 KB for table 'mysqltest3'.'t1'
+  Backup has 938 KB for table 'mysqltest3'.'t2'
+  Backup has 937 KB for table 'mysqltest3'.'t3'
+
+Summary:
+
+Creation time: #
+Validity time: #
+Finish   time: #
+No binlog information
+========
+
+Full set of most relevant information, verbosely:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+
+Catalog summary:
+
+  Character sets:         2
+  Databases:              3
+  Tables:                 9
+  Other per db objects:   6
+
+Catalog details:
+
+  Character set 'utf8'
+  Character set 'utf8'
+  Database 'mysqltest1'
+    Table  'mysqltest1'.'t1'
+    Table  'mysqltest1'.'t2'
+    Table  'mysqltest1'.'t3'
+    View   'mysqltest1'.'v1'
+    View   'mysqltest1'.'v2'
+  Database 'mysqltest2'
+    Table  'mysqltest2'.'t1'
+    Table  'mysqltest2'.'t2'
+    Table  'mysqltest2'.'t3'
+    View   'mysqltest2'.'v1'
+    View   'mysqltest2'.'v2'
+  Database 'mysqltest3'
+    Table  'mysqltest3'.'t1'
+    Table  'mysqltest3'.'t2'
+    Table  'mysqltest3'.'t3'
+    View   'mysqltest3'.'v1'
+    View   'mysqltest3'.'v2'
+
+Meta data:
+
+  Database 'mysqltest1' statement: 'CREATE DATABASE `mysqltest1` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest1' extra data length: 0
+
+    Table 'mysqltest1'.'t1' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  `c2` varchar(30000) DEFAULT NULL,
+  PRIMARY KEY (`c1`)
+) ENGINE=MyISAM AUTO_INCREMENT=33 DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t1' extra data length: 0
+
+    Table 'mysqltest1'.'t2' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t2' extra data length: 0
+
+    Table 'mysqltest1'.'t3' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t3' extra data length: 0
+
+    View 'mysqltest1'.'v1' statement: 'USE `mysqltest1`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v1` AS select `mysqltest1`.`t1`.`c1` AS `c1`,`mysqltest1`.`t1`.`c2` AS `c2`,`mysqltest1`.`t1`.`c1` in (select (`mysqltest1`.`t1`.`c1` + 2) AS `c1+2` from `mysqltest1`.`t1`) AS `c3`,`mysqltest1`.`t1`.`c1` = all (select `mysqltest1`.`t1`.`c1` AS `c1` from `mysqltest1`.`t1`) AS `c4` from `mysqltest1`.`t1`'
+    View 'mysqltest1'.'v1' extra data length: 0
+
+    View 'mysqltest1'.'v2' statement: 'USE `mysqltest1`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v2` AS select `v1`.`c2` AS `c2`,`v1`.`c3` AS `c3` from `mysqltest1`.`v1`'
+    View 'mysqltest1'.'v2' extra data length: 0
+
+  Database 'mysqltest2' statement: 'CREATE DATABASE `mysqltest2` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest2' extra data length: 0
+
+    Table 'mysqltest2'.'t1' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t1` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t1' extra data length: 0
+
+    Table 'mysqltest2'.'t2' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t2' extra data length: 0
+
+    Table 'mysqltest2'.'t3' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t3' extra data length: 0
+
+    View 'mysqltest2'.'v1' statement: 'USE `mysqltest2`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v1` AS select connection_id() AS `c1`,pi() AS `c2`,current_user() AS `c3`,version() AS `c4`'
+    View 'mysqltest2'.'v1' extra data length: 0
+
+    View 'mysqltest2'.'v2' statement: 'USE `mysqltest2`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v2` AS select `mysqltest2`.`t2`.`c1` AS `c1`,`mysqltest2`.`t2`.`c2` AS `c2` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`) union all select `mysqltest2`.`t2`.`c1` AS `c3`,`mysqltest2`.`t2`.`c2` AS `c4` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`)'
+    View 'mysqltest2'.'v2' extra data length: 0
+
+  Database 'mysqltest3' statement: 'CREATE DATABASE `mysqltest3` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest3' extra data length: 0
+
+    Table 'mysqltest3'.'t1' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t1` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t1' extra data length: 0
+
+    Table 'mysqltest3'.'t2' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t2' extra data length: 0
+
+    Table 'mysqltest3'.'t3' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t3' extra data length: 0
+
+    View 'mysqltest3'.'v1' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v1` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` join `mysqltest2`.`v2`) where (`v1`.`c1` = `v2`.`c1`)'
+    View 'mysqltest3'.'v1' extra data length: 0
+
+    View 'mysqltest3'.'v2' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v2` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` left join `mysqltest2`.`v2` on((`v1`.`c1` = `v2`.`c1`)))'
+    View 'mysqltest3'.'v2' extra data length: 0
+
+Data totals:
+
+  Backup has 939 KB for table 'mysqltest1'.'t1'
+  Backup has 937 KB for table 'mysqltest1'.'t2'
+  Backup has 937 KB for table 'mysqltest1'.'t3'
+  Backup has 937 KB for table 'mysqltest2'.'t1'
+  Backup has 937 KB for table 'mysqltest2'.'t2'
+  Backup has 938 KB for table 'mysqltest2'.'t3'
+  Backup has 937 KB for table 'mysqltest3'.'t1'
+  Backup has 938 KB for table 'mysqltest3'.'t2'
+  Backup has 937 KB for table 'mysqltest3'.'t3'
+
+Summary:
+
+Creation time: #
+Validity time: #
+Finish   time: #
+No binlog information
+========
+
+Full set of most relevant information plus snapshots:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+Snapshot count:      3
+
+Snapshots:
+
+  Snapshot 0 type    native from 'MyISAM'  version 1.0
+  Snapshot 0 version 1
+  Snapshot 0 tables  1
+  Snapshot 1 type    logical from consistent snapshot
+  Snapshot 1 version 1
+  Snapshot 1 tables  1
+  Snapshot 2 type    logical from locked tables
+  Snapshot 2 version 1
+  Snapshot 2 tables  1
+
+Catalog summary:
+
+  Character sets:         2
+  Databases:              3
+  Tables:                 9
+  Other per db objects:   6
+
+Catalog details:
+
+  Character set 'utf8'
+  Character set 'utf8'
+  Database 'mysqltest1'
+    Table  'mysqltest1'.'t1'
+    Table  'mysqltest1'.'t2'
+    Table  'mysqltest1'.'t3'
+    View   'mysqltest1'.'v1'
+    View   'mysqltest1'.'v2'
+  Database 'mysqltest2'
+    Table  'mysqltest2'.'t1'
+    Table  'mysqltest2'.'t2'
+    Table  'mysqltest2'.'t3'
+    View   'mysqltest2'.'v1'
+    View   'mysqltest2'.'v2'
+  Database 'mysqltest3'
+    Table  'mysqltest3'.'t1'
+    Table  'mysqltest3'.'t2'
+    Table  'mysqltest3'.'t3'
+    View   'mysqltest3'.'v1'
+    View   'mysqltest3'.'v2'
+
+Meta data:
+
+  Database 'mysqltest1' statement: 'CREATE DATABASE `mysqltest1` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest1' extra data length: 0
+
+    Table 'mysqltest1'.'t1' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  `c2` varchar(30000) DEFAULT NULL,
+  PRIMARY KEY (`c1`)
+) ENGINE=MyISAM AUTO_INCREMENT=33 DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t1' extra data length: 0
+
+    Table 'mysqltest1'.'t2' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t2' extra data length: 0
+
+    Table 'mysqltest1'.'t3' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t3' extra data length: 0
+
+    View 'mysqltest1'.'v1' statement: 'USE `mysqltest1`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v1` AS select `mysqltest1`.`t1`.`c1` AS `c1`,`mysqltest1`.`t1`.`c2` AS `c2`,`mysqltest1`.`t1`.`c1` in (select (`mysqltest1`.`t1`.`c1` + 2) AS `c1+2` from `mysqltest1`.`t1`) AS `c3`,`mysqltest1`.`t1`.`c1` = all (select `mysqltest1`.`t1`.`c1` AS `c1` from `mysqltest1`.`t1`) AS `c4` from `mysqltest1`.`t1`'
+    View 'mysqltest1'.'v1' extra data length: 0
+
+    View 'mysqltest1'.'v2' statement: 'USE `mysqltest1`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v2` AS select `v1`.`c2` AS `c2`,`v1`.`c3` AS `c3` from `mysqltest1`.`v1`'
+    View 'mysqltest1'.'v2' extra data length: 0
+
+  Database 'mysqltest2' statement: 'CREATE DATABASE `mysqltest2` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest2' extra data length: 0
+
+    Table 'mysqltest2'.'t1' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t1` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t1' extra data length: 0
+
+    Table 'mysqltest2'.'t2' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t2' extra data length: 0
+
+    Table 'mysqltest2'.'t3' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t3' extra data length: 0
+
+    View 'mysqltest2'.'v1' statement: 'USE `mysqltest2`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v1` AS select connection_id() AS `c1`,pi() AS `c2`,current_user() AS `c3`,version() AS `c4`'
+    View 'mysqltest2'.'v1' extra data length: 0
+
+    View 'mysqltest2'.'v2' statement: 'USE `mysqltest2`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v2` AS select `mysqltest2`.`t2`.`c1` AS `c1`,`mysqltest2`.`t2`.`c2` AS `c2` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`) union all select `mysqltest2`.`t2`.`c1` AS `c3`,`mysqltest2`.`t2`.`c2` AS `c4` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`)'
+    View 'mysqltest2'.'v2' extra data length: 0
+
+  Database 'mysqltest3' statement: 'CREATE DATABASE `mysqltest3` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest3' extra data length: 0
+
+    Table 'mysqltest3'.'t1' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t1` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t1' extra data length: 0
+
+    Table 'mysqltest3'.'t2' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t2' extra data length: 0
+
+    Table 'mysqltest3'.'t3' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t3' extra data length: 0
+
+    View 'mysqltest3'.'v1' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v1` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` join `mysqltest2`.`v2`) where (`v1`.`c1` = `v2`.`c1`)'
+    View 'mysqltest3'.'v1' extra data length: 0
+
+    View 'mysqltest3'.'v2' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v2` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` left join `mysqltest2`.`v2` on((`v1`.`c1` = `v2`.`c1`)))'
+    View 'mysqltest3'.'v2' extra data length: 0
+
+Data totals:
+
+  Snapshot 0 has 939 KB for table 'mysqltest1'.'t1'
+  Snapshot 1 has 937 KB for table 'mysqltest1'.'t2'
+  Snapshot 2 has 937 KB for table 'mysqltest1'.'t3'
+  Snapshot 1 has 937 KB for table 'mysqltest2'.'t1'
+  Snapshot 2 has 937 KB for table 'mysqltest2'.'t2'
+  Snapshot 0 has 938 KB for table 'mysqltest2'.'t3'
+  Snapshot 2 has 937 KB for table 'mysqltest3'.'t1'
+  Snapshot 0 has 938 KB for table 'mysqltest3'.'t2'
+  Snapshot 1 has 937 KB for table 'mysqltest3'.'t3'
+
+Summary:
+
+Creation time: #
+Validity time: #
+Finish   time: #
+No binlog information
+========
+
+Full set of most relevant information plus snapshots, verbosely:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+Snapshot count:      3
+
+Snapshots:
+
+  Snapshot 0 type    native from 'MyISAM'  version 1.0
+  Snapshot 0 version 1
+  Snapshot 0 tables  1
+  Snapshot 1 type    logical from consistent snapshot
+  Snapshot 1 version 1
+  Snapshot 1 tables  1
+  Snapshot 2 type    logical from locked tables
+  Snapshot 2 version 1
+  Snapshot 2 tables  1
+
+Catalog summary:
+
+  Character sets:         2
+  Databases:              3
+  Tables:                 9
+  Other per db objects:   6
+
+Catalog details:
+
+  Character set 'utf8'
+  Character set 'utf8'
+  Database 'mysqltest1'
+    Table  'mysqltest1'.'t1'
+    Table  'mysqltest1'.'t2'
+    Table  'mysqltest1'.'t3'
+    View   'mysqltest1'.'v1'
+    View   'mysqltest1'.'v2'
+  Database 'mysqltest2'
+    Table  'mysqltest2'.'t1'
+    Table  'mysqltest2'.'t2'
+    Table  'mysqltest2'.'t3'
+    View   'mysqltest2'.'v1'
+    View   'mysqltest2'.'v2'
+  Database 'mysqltest3'
+    Table  'mysqltest3'.'t1'
+    Table  'mysqltest3'.'t2'
+    Table  'mysqltest3'.'t3'
+    View   'mysqltest3'.'v1'
+    View   'mysqltest3'.'v2'
+
+Meta data:
+
+  Database 'mysqltest1' statement: 'CREATE DATABASE `mysqltest1` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest1' extra data length: 0
+
+    Table 'mysqltest1'.'t1' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  `c2` varchar(30000) DEFAULT NULL,
+  PRIMARY KEY (`c1`)
+) ENGINE=MyISAM AUTO_INCREMENT=33 DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t1' extra data length: 0
+
+    Table 'mysqltest1'.'t2' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t2' extra data length: 0
+
+    Table 'mysqltest1'.'t3' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t3' extra data length: 0
+
+    View 'mysqltest1'.'v1' statement: 'USE `mysqltest1`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v1` AS select `mysqltest1`.`t1`.`c1` AS `c1`,`mysqltest1`.`t1`.`c2` AS `c2`,`mysqltest1`.`t1`.`c1` in (select (`mysqltest1`.`t1`.`c1` + 2) AS `c1+2` from `mysqltest1`.`t1`) AS `c3`,`mysqltest1`.`t1`.`c1` = all (select `mysqltest1`.`t1`.`c1` AS `c1` from `mysqltest1`.`t1`) AS `c4` from `mysqltest1`.`t1`'
+    View 'mysqltest1'.'v1' extra data length: 0
+
+    View 'mysqltest1'.'v2' statement: 'USE `mysqltest1`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v2` AS select `v1`.`c2` AS `c2`,`v1`.`c3` AS `c3` from `mysqltest1`.`v1`'
+    View 'mysqltest1'.'v2' extra data length: 0
+
+  Database 'mysqltest2' statement: 'CREATE DATABASE `mysqltest2` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest2' extra data length: 0
+
+    Table 'mysqltest2'.'t1' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t1` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t1' extra data length: 0
+
+    Table 'mysqltest2'.'t2' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t2' extra data length: 0
+
+    Table 'mysqltest2'.'t3' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t3' extra data length: 0
+
+    View 'mysqltest2'.'v1' statement: 'USE `mysqltest2`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v1` AS select connection_id() AS `c1`,pi() AS `c2`,current_user() AS `c3`,version() AS `c4`'
+    View 'mysqltest2'.'v1' extra data length: 0
+
+    View 'mysqltest2'.'v2' statement: 'USE `mysqltest2`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v2` AS select `mysqltest2`.`t2`.`c1` AS `c1`,`mysqltest2`.`t2`.`c2` AS `c2` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`) union all select `mysqltest2`.`t2`.`c1` AS `c3`,`mysqltest2`.`t2`.`c2` AS `c4` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`)'
+    View 'mysqltest2'.'v2' extra data length: 0
+
+  Database 'mysqltest3' statement: 'CREATE DATABASE `mysqltest3` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest3' extra data length: 0
+
+    Table 'mysqltest3'.'t1' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t1` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t1' extra data length: 0
+
+    Table 'mysqltest3'.'t2' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t2' extra data length: 0
+
+    Table 'mysqltest3'.'t3' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t3' extra data length: 0
+
+    View 'mysqltest3'.'v1' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v1` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` join `mysqltest2`.`v2`) where (`v1`.`c1` = `v2`.`c1`)'
+    View 'mysqltest3'.'v1' extra data length: 0
+
+    View 'mysqltest3'.'v2' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v2` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` left join `mysqltest2`.`v2` on((`v1`.`c1` = `v2`.`c1`)))'
+    View 'mysqltest3'.'v2' extra data length: 0
+
+Data totals:
+
+  Snapshot 0 has 939 KB for table 'mysqltest1'.'t1'
+  Snapshot 1 has 937 KB for table 'mysqltest1'.'t2'
+  Snapshot 2 has 937 KB for table 'mysqltest1'.'t3'
+  Snapshot 1 has 937 KB for table 'mysqltest2'.'t1'
+  Snapshot 2 has 937 KB for table 'mysqltest2'.'t2'
+  Snapshot 0 has 938 KB for table 'mysqltest2'.'t3'
+  Snapshot 2 has 937 KB for table 'mysqltest3'.'t1'
+  Snapshot 0 has 938 KB for table 'mysqltest3'.'t2'
+  Snapshot 1 has 937 KB for table 'mysqltest3'.'t3'
+
+Summary:
+
+Creation time: #
+Validity time: #
+Finish   time: #
+No binlog information
+========
+
+Full set of most relevant information plus data chunks:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+
+Catalog summary:
+
+  Character sets:         2
+  Databases:              3
+  Tables:                 9
+  Other per db objects:   6
+
+Catalog details:
+
+  Character set 'utf8'
+  Character set 'utf8'
+  Database 'mysqltest1'
+    Table  'mysqltest1'.'t1'
+    Table  'mysqltest1'.'t2'
+    Table  'mysqltest1'.'t3'
+    View   'mysqltest1'.'v1'
+    View   'mysqltest1'.'v2'
+  Database 'mysqltest2'
+    Table  'mysqltest2'.'t1'
+    Table  'mysqltest2'.'t2'
+    Table  'mysqltest2'.'t3'
+    View   'mysqltest2'.'v1'
+    View   'mysqltest2'.'v2'
+  Database 'mysqltest3'
+    Table  'mysqltest3'.'t1'
+    Table  'mysqltest3'.'t2'
+    Table  'mysqltest3'.'t3'
+    View   'mysqltest3'.'v1'
+    View   'mysqltest3'.'v2'
+
+Meta data:
+
+  Database 'mysqltest1' statement: 'CREATE DATABASE `mysqltest1` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest1' extra data length: 0
+
+    Table 'mysqltest1'.'t1' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  `c2` varchar(30000) DEFAULT NULL,
+  PRIMARY KEY (`c1`)
+) ENGINE=MyISAM AUTO_INCREMENT=33 DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t1' extra data length: 0
+
+    Table 'mysqltest1'.'t2' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t2' extra data length: 0
+
+    Table 'mysqltest1'.'t3' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t3' extra data length: 0
+
+    View 'mysqltest1'.'v1' statement: 'USE `mysqltest1`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v1` AS select `mysqltest1`.`t1`.`c1` AS `c1`,`mysqltest1`.`t1`.`c2` AS `c2`,`mysqltest1`.`t1`.`c1` in (select (`mysqltest1`.`t1`.`c1` + 2) AS `c1+2` from `mysqltest1`.`t1`) AS `c3`,`mysqltest1`.`t1`.`c1` = all (select `mysqltest1`.`t1`.`c1` AS `c1` from `mysqltest1`.`t1`) AS `c4` from `mysqltest1`.`t1`'
+    View 'mysqltest1'.'v1' extra data length: 0
+
+    View 'mysqltest1'.'v2' statement: 'USE `mysqltest1`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v2` AS select `v1`.`c2` AS `c2`,`v1`.`c3` AS `c3` from `mysqltest1`.`v1`'
+    View 'mysqltest1'.'v2' extra data length: 0
+
+  Database 'mysqltest2' statement: 'CREATE DATABASE `mysqltest2` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest2' extra data length: 0
+
+    Table 'mysqltest2'.'t1' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t1` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t1' extra data length: 0
+
+    Table 'mysqltest2'.'t2' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t2' extra data length: 0
+
+    Table 'mysqltest2'.'t3' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t3' extra data length: 0
+
+    View 'mysqltest2'.'v1' statement: 'USE `mysqltest2`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v1` AS select connection_id() AS `c1`,pi() AS `c2`,current_user() AS `c3`,version() AS `c4`'
+    View 'mysqltest2'.'v1' extra data length: 0
+
+    View 'mysqltest2'.'v2' statement: 'USE `mysqltest2`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v2` AS select `mysqltest2`.`t2`.`c1` AS `c1`,`mysqltest2`.`t2`.`c2` AS `c2` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`) union all select `mysqltest2`.`t2`.`c1` AS `c3`,`mysqltest2`.`t2`.`c2` AS `c4` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`)'
+    View 'mysqltest2'.'v2' extra data length: 0
+
+  Database 'mysqltest3' statement: 'CREATE DATABASE `mysqltest3` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest3' extra data length: 0
+
+    Table 'mysqltest3'.'t1' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t1` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t1' extra data length: 0
+
+    Table 'mysqltest3'.'t2' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t2' extra data length: 0
+
+    Table 'mysqltest3'.'t3' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t3' extra data length: 0
+
+    View 'mysqltest3'.'v1' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v1` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` join `mysqltest2`.`v2`) where (`v1`.`c1` = `v2`.`c1`)'
+    View 'mysqltest3'.'v1' extra data length: 0
+
+    View 'mysqltest3'.'v2' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v2` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` left join `mysqltest2`.`v2` on((`v1`.`c1` = `v2`.`c1`)))'
+    View 'mysqltest3'.'v2' extra data length: 0
+
+Data chunks:
+  Chunk has 960385 bytes for table 'mysqltest1'.'t1'
+  Chunk has 2049 bytes for table 'mysqltest1'.'t1'
+  Chunk has 960385 bytes for table 'mysqltest2'.'t3'
+  Chunk has 1025 bytes for table 'mysqltest2'.'t3'
+  Chunk has 960385 bytes for table 'mysqltest3'.'t2'
+  Chunk has 1025 bytes for table 'mysqltest3'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest1'.'t2'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest2'.'t1'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+  Chunk has 30008 bytes for table 'mysqltest3'.'t3'
+
+Data totals:
+
+  Backup has 939 KB for table 'mysqltest1'.'t1'
+  Backup has 937 KB for table 'mysqltest1'.'t2'
+  Backup has 937 KB for table 'mysqltest1'.'t3'
+  Backup has 937 KB for table 'mysqltest2'.'t1'
+  Backup has 937 KB for table 'mysqltest2'.'t2'
+  Backup has 938 KB for table 'mysqltest2'.'t3'
+  Backup has 937 KB for table 'mysqltest3'.'t1'
+  Backup has 938 KB for table 'mysqltest3'.'t2'
+  Backup has 937 KB for table 'mysqltest3'.'t3'
+
+Summary:
+
+Creation time: #
+Validity time: #
+Finish   time: #
+No binlog information
+========
+
+Full set of most relevant information plus snapshots and data chunks:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+Snapshot count:      3
+
+Snapshots:
+
+  Snapshot 0 type    native from 'MyISAM'  version 1.0
+  Snapshot 0 version 1
+  Snapshot 0 tables  1
+  Snapshot 1 type    logical from consistent snapshot
+  Snapshot 1 version 1
+  Snapshot 1 tables  1
+  Snapshot 2 type    logical from locked tables
+  Snapshot 2 version 1
+  Snapshot 2 tables  1
+
+Catalog summary:
+
+  Character sets:         2
+  Databases:              3
+  Tables:                 9
+  Other per db objects:   6
+
+Catalog details:
+
+  Character set 'utf8'
+  Character set 'utf8'
+  Database 'mysqltest1'
+    Table  'mysqltest1'.'t1'
+    Table  'mysqltest1'.'t2'
+    Table  'mysqltest1'.'t3'
+    View   'mysqltest1'.'v1'
+    View   'mysqltest1'.'v2'
+  Database 'mysqltest2'
+    Table  'mysqltest2'.'t1'
+    Table  'mysqltest2'.'t2'
+    Table  'mysqltest2'.'t3'
+    View   'mysqltest2'.'v1'
+    View   'mysqltest2'.'v2'
+  Database 'mysqltest3'
+    Table  'mysqltest3'.'t1'
+    Table  'mysqltest3'.'t2'
+    Table  'mysqltest3'.'t3'
+    View   'mysqltest3'.'v1'
+    View   'mysqltest3'.'v2'
+
+Meta data:
+
+  Database 'mysqltest1' statement: 'CREATE DATABASE `mysqltest1` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest1' extra data length: 0
+
+    Table 'mysqltest1'.'t1' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  `c2` varchar(30000) DEFAULT NULL,
+  PRIMARY KEY (`c1`)
+) ENGINE=MyISAM AUTO_INCREMENT=33 DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t1' extra data length: 0
+
+    Table 'mysqltest1'.'t2' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t2' extra data length: 0
+
+    Table 'mysqltest1'.'t3' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t3' extra data length: 0
+
+    View 'mysqltest1'.'v1' statement: 'USE `mysqltest1`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v1` AS select `mysqltest1`.`t1`.`c1` AS `c1`,`mysqltest1`.`t1`.`c2` AS `c2`,`mysqltest1`.`t1`.`c1` in (select (`mysqltest1`.`t1`.`c1` + 2) AS `c1+2` from `mysqltest1`.`t1`) AS `c3`,`mysqltest1`.`t1`.`c1` = all (select `mysqltest1`.`t1`.`c1` AS `c1` from `mysqltest1`.`t1`) AS `c4` from `mysqltest1`.`t1`'
+    View 'mysqltest1'.'v1' extra data length: 0
+
+    View 'mysqltest1'.'v2' statement: 'USE `mysqltest1`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v2` AS select `v1`.`c2` AS `c2`,`v1`.`c3` AS `c3` from `mysqltest1`.`v1`'
+    View 'mysqltest1'.'v2' extra data length: 0
+
+  Database 'mysqltest2' statement: 'CREATE DATABASE `mysqltest2` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest2' extra data length: 0
+
+    Table 'mysqltest2'.'t1' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t1` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t1' extra data length: 0
+
+    Table 'mysqltest2'.'t2' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t2' extra data length: 0
+
+    Table 'mysqltest2'.'t3' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t3' extra data length: 0
+
+    View 'mysqltest2'.'v1' statement: 'USE `mysqltest2`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v1` AS select connection_id() AS `c1`,pi() AS `c2`,current_user() AS `c3`,version() AS `c4`'
+    View 'mysqltest2'.'v1' extra data length: 0
+
+    View 'mysqltest2'.'v2' statement: 'USE `mysqltest2`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v2` AS select `mysqltest2`.`t2`.`c1` AS `c1`,`mysqltest2`.`t2`.`c2` AS `c2` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`) union all select `mysqltest2`.`t2`.`c1` AS `c3`,`mysqltest2`.`t2`.`c2` AS `c4` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`)'
+    View 'mysqltest2'.'v2' extra data length: 0
+
+  Database 'mysqltest3' statement: 'CREATE DATABASE `mysqltest3` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest3' extra data length: 0
+
+    Table 'mysqltest3'.'t1' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t1` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t1' extra data length: 0
+
+    Table 'mysqltest3'.'t2' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t2' extra data length: 0
+
+    Table 'mysqltest3'.'t3' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t3' extra data length: 0
+
+    View 'mysqltest3'.'v1' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v1` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` join `mysqltest2`.`v2`) where (`v1`.`c1` = `v2`.`c1`)'
+    View 'mysqltest3'.'v1' extra data length: 0
+
+    View 'mysqltest3'.'v2' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v2` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` left join `mysqltest2`.`v2` on((`v1`.`c1` = `v2`.`c1`)))'
+    View 'mysqltest3'.'v2' extra data length: 0
+
+Data chunks:
+  Snapshot 0 has 960385 bytes for table 'mysqltest1'.'t1'
+  Snapshot 0 has 2049 bytes for table 'mysqltest1'.'t1'
+  Snapshot 0 has 960385 bytes for table 'mysqltest2'.'t3'
+  Snapshot 0 has 1025 bytes for table 'mysqltest2'.'t3'
+  Snapshot 0 has 960385 bytes for table 'mysqltest3'.'t2'
+  Snapshot 0 has 1025 bytes for table 'mysqltest3'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest1'.'t3'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest2'.'t2'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 2 has 30008 bytes for table 'mysqltest3'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+  Snapshot 1 has 30008 bytes for table 'mysqltest3'.'t3'
+
+Data totals:
+
+  Snapshot 0 has 939 KB for table 'mysqltest1'.'t1'
+  Snapshot 1 has 937 KB for table 'mysqltest1'.'t2'
+  Snapshot 2 has 937 KB for table 'mysqltest1'.'t3'
+  Snapshot 1 has 937 KB for table 'mysqltest2'.'t1'
+  Snapshot 2 has 937 KB for table 'mysqltest2'.'t2'
+  Snapshot 0 has 938 KB for table 'mysqltest2'.'t3'
+  Snapshot 2 has 937 KB for table 'mysqltest3'.'t1'
+  Snapshot 0 has 938 KB for table 'mysqltest3'.'t2'
+  Snapshot 1 has 937 KB for table 'mysqltest3'.'t3'
+
+Summary:
+
+Creation time: #
+Validity time: #
+Finish   time: #
+No binlog information
+========
+
+Search for an object:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+
+Searching 'utf8'
+  Character set 'utf8'
+  Character set 'utf8'
+========
+
+Search for an object in databases:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+
+Searching '%'.'t2'
+    Table  'mysqltest1'.'t2'
+    Table  'mysqltest2'.'t2'
+    Table  'mysqltest3'.'t2'
+
+Search for an object in databases and show create statement:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+
+Searching '%'.'t2'
+    Table  'mysqltest1'.'t2'
+    Table 'mysqltest1'.'t2' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table  'mysqltest2'.'t2'
+    Table 'mysqltest2'.'t2' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table  'mysqltest3'.'t2'
+    Table 'mysqltest3'.'t2' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+========
+BACKUP DATABASE mysqltest1, mysqltest2, mysqltest3 TO 'mysqltest.bak'
+  WITH COMPRESSION;
+backup_id
+#
+
+Full set of most relevant information plus snapshots, verbosely:
+========
+
+Image path: #
+Image size: #
+Image compression:   gzip
+Image version:       1
+Creation time: #
+Server version: #
+Snapshot count:      3
+
+Snapshots:
+
+  Snapshot 0 type    native from 'MyISAM'  version 1.0
+  Snapshot 0 version 1
+  Snapshot 0 tables  1
+  Snapshot 1 type    logical from consistent snapshot
+  Snapshot 1 version 1
+  Snapshot 1 tables  1
+  Snapshot 2 type    logical from locked tables
+  Snapshot 2 version 1
+  Snapshot 2 tables  1
+
+Catalog summary:
+
+  Character sets:         2
+  Databases:              3
+  Tables:                 9
+  Other per db objects:   6
+
+Catalog details:
+
+  Character set 'utf8'
+  Character set 'utf8'
+  Database 'mysqltest1'
+    Table  'mysqltest1'.'t1'
+    Table  'mysqltest1'.'t2'
+    Table  'mysqltest1'.'t3'
+    View   'mysqltest1'.'v1'
+    View   'mysqltest1'.'v2'
+  Database 'mysqltest2'
+    Table  'mysqltest2'.'t1'
+    Table  'mysqltest2'.'t2'
+    Table  'mysqltest2'.'t3'
+    View   'mysqltest2'.'v1'
+    View   'mysqltest2'.'v2'
+  Database 'mysqltest3'
+    Table  'mysqltest3'.'t1'
+    Table  'mysqltest3'.'t2'
+    Table  'mysqltest3'.'t3'
+    View   'mysqltest3'.'v1'
+    View   'mysqltest3'.'v2'
+
+Meta data:
+
+  Database 'mysqltest1' statement: 'CREATE DATABASE `mysqltest1` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest1' extra data length: 0
+
+    Table 'mysqltest1'.'t1' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  `c2` varchar(30000) DEFAULT NULL,
+  PRIMARY KEY (`c1`)
+) ENGINE=MyISAM AUTO_INCREMENT=33 DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t1' extra data length: 0
+
+    Table 'mysqltest1'.'t2' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t2' extra data length: 0
+
+    Table 'mysqltest1'.'t3' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t3' extra data length: 0
+
+    View 'mysqltest1'.'v1' statement: 'USE `mysqltest1`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v1` AS select `mysqltest1`.`t1`.`c1` AS `c1`,`mysqltest1`.`t1`.`c2` AS `c2`,`mysqltest1`.`t1`.`c1` in (select (`mysqltest1`.`t1`.`c1` + 2) AS `c1+2` from `mysqltest1`.`t1`) AS `c3`,`mysqltest1`.`t1`.`c1` = all (select `mysqltest1`.`t1`.`c1` AS `c1` from `mysqltest1`.`t1`) AS `c4` from `mysqltest1`.`t1`'
+    View 'mysqltest1'.'v1' extra data length: 0
+
+    View 'mysqltest1'.'v2' statement: 'USE `mysqltest1`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest1`.`v2` AS select `v1`.`c2` AS `c2`,`v1`.`c3` AS `c3` from `mysqltest1`.`v1`'
+    View 'mysqltest1'.'v2' extra data length: 0
+
+  Database 'mysqltest2' statement: 'CREATE DATABASE `mysqltest2` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest2' extra data length: 0
+
+    Table 'mysqltest2'.'t1' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t1` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t1' extra data length: 0
+
+    Table 'mysqltest2'.'t2' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t2' extra data length: 0
+
+    Table 'mysqltest2'.'t3' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t3' extra data length: 0
+
+    View 'mysqltest2'.'v1' statement: 'USE `mysqltest2`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v1` AS select connection_id() AS `c1`,pi() AS `c2`,current_user() AS `c3`,version() AS `c4`'
+    View 'mysqltest2'.'v1' extra data length: 0
+
+    View 'mysqltest2'.'v2' statement: 'USE `mysqltest2`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest2`.`v2` AS select `mysqltest2`.`t2`.`c1` AS `c1`,`mysqltest2`.`t2`.`c2` AS `c2` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`) union all select `mysqltest2`.`t2`.`c1` AS `c3`,`mysqltest2`.`t2`.`c2` AS `c4` from (`mysqltest2`.`t2` join `mysqltest2`.`t3`)'
+    View 'mysqltest2'.'v2' extra data length: 0
+
+  Database 'mysqltest3' statement: 'CREATE DATABASE `mysqltest3` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest3' extra data length: 0
+
+    Table 'mysqltest3'.'t1' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t1` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MEMORY DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t1' extra data length: 0
+
+    Table 'mysqltest3'.'t2' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t2` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t2' extra data length: 0
+
+    Table 'mysqltest3'.'t3' statement: 'USE `mysqltest3`; CREATE TABLE `mysqltest3`.`t3` (
+  `c1` int(11) NOT NULL DEFAULT '0',
+  `c2` varchar(30000) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest3'.'t3' extra data length: 0
+
+    View 'mysqltest3'.'v1' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v1` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` join `mysqltest2`.`v2`) where (`v1`.`c1` = `v2`.`c1`)'
+    View 'mysqltest3'.'v1' extra data length: 0
+
+    View 'mysqltest3'.'v2' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v2` AS select `v1`.`c1` AS `c1`,`v2`.`c1` AS `c2` from (`mysqltest1`.`v1` left join `mysqltest2`.`v2` on((`v1`.`c1` = `v2`.`c1`)))'
+    View 'mysqltest3'.'v2' extra data length: 0
+
+Data totals:
+
+  Snapshot 0 has 939 KB for table 'mysqltest1'.'t1'
+  Snapshot 1 has 937 KB for table 'mysqltest1'.'t2'
+  Snapshot 2 has 937 KB for table 'mysqltest1'.'t3'
+  Snapshot 1 has 937 KB for table 'mysqltest2'.'t1'
+  Snapshot 2 has 937 KB for table 'mysqltest2'.'t2'
+  Snapshot 0 has 938 KB for table 'mysqltest2'.'t3'
+  Snapshot 2 has 937 KB for table 'mysqltest3'.'t1'
+  Snapshot 0 has 938 KB for table 'mysqltest3'.'t2'
+  Snapshot 1 has 937 KB for table 'mysqltest3'.'t3'
+
+Summary:
+
+Creation time: #
+Validity time: #
+Finish   time: #
+No binlog information
+========
+DROP DATABASE mysqltest1;
+DROP DATABASE mysqltest2;
+DROP DATABASE mysqltest3;
+CREATE DATABASE mysqltest1;
+BACKUP DATABASE mysqltest1 TO 'mysqltest.bak';
+backup_id
+#
+
+Full set of most relevant information plus snapshots and data chunks:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+Snapshot count:      0
+
+Snapshots:
+
+
+Catalog summary:
+
+  Character sets:         2
+  Databases:              1
+  Tables:                 0
+  Other per db objects:   0
+
+Catalog details:
+
+  Character set 'utf8'
+  Character set 'utf8'
+  Database 'mysqltest1'
+
+Meta data:
+
+  Database 'mysqltest1' statement: 'CREATE DATABASE `mysqltest1` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest1' extra data length: 0
+
+Data chunks:
+
+Data totals:
+
+
+Summary:
+
+Creation time: #
+Validity time: #
+Finish   time: #
+No binlog information
+========
+DROP DATABASE mysqltest1;
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+BACKUP DATABASE mysqltest1, mysqltest2 TO 'mysqltest.bak';
+backup_id
+#
+
+Full set of most relevant information plus snapshots and data chunks:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+Snapshot count:      0
+
+Snapshots:
+
+
+Catalog summary:
+
+  Character sets:         2
+  Databases:              2
+  Tables:                 0
+  Other per db objects:   0
+
+Catalog details:
+
+  Character set 'utf8'
+  Character set 'utf8'
+  Database 'mysqltest1'
+  Database 'mysqltest2'
+
+Meta data:
+
+  Database 'mysqltest1' statement: 'CREATE DATABASE `mysqltest1` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest1' extra data length: 0
+
+  Database 'mysqltest2' statement: 'CREATE DATABASE `mysqltest2` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest2' extra data length: 0
+
+Data chunks:
+
+Data totals:
+
+
+Summary:
+
+Creation time: #
+Validity time: #
+Finish   time: #
+No binlog information
+========
+DROP DATABASE mysqltest1;
+DROP DATABASE mysqltest2;
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+CREATE DATABASE mysqltest3;
+BACKUP DATABASE mysqltest1, mysqltest2, mysqltest3 TO 'mysqltest.bak';
+backup_id
+#
+
+Full set of most relevant information plus snapshots and data chunks:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+Snapshot count:      0
+
+Snapshots:
+
+
+Catalog summary:
+
+  Character sets:         2
+  Databases:              3
+  Tables:                 0
+  Other per db objects:   0
+
+Catalog details:
+
+  Character set 'utf8'
+  Character set 'utf8'
+  Database 'mysqltest1'
+  Database 'mysqltest2'
+  Database 'mysqltest3'
+
+Meta data:
+
+  Database 'mysqltest1' statement: 'CREATE DATABASE `mysqltest1` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest1' extra data length: 0
+
+  Database 'mysqltest2' statement: 'CREATE DATABASE `mysqltest2` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest2' extra data length: 0
+
+  Database 'mysqltest3' statement: 'CREATE DATABASE `mysqltest3` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest3' extra data length: 0
+
+Data chunks:
+
+Data totals:
+
+
+Summary:
+
+Creation time: #
+Validity time: #
+Finish   time: #
+No binlog information
+========
+DROP DATABASE mysqltest1;
+DROP DATABASE mysqltest2;
+DROP DATABASE mysqltest3;
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+CREATE DATABASE mysqltest3;
+CREATE TABLE mysqltest1.t1 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE mysqltest2.t1 (c1 INT) ENGINE=InnoDB;
+CREATE VIEW  mysqltest3.v1 AS
+SELECT mysqltest1.t1.c1 + mysqltest2.t1.c1 AS c1
+FROM mysqltest1.t1, mysqltest2.t1;
+BACKUP DATABASE mysqltest1, mysqltest2, mysqltest3 TO 'mysqltest.bak';
+backup_id
+#
+
+Full set of most relevant information plus snapshots and data chunks:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+Snapshot count:      2
+
+Snapshots:
+
+  Snapshot 0 type    native from 'MyISAM'  version 1.0
+  Snapshot 0 version 1
+  Snapshot 0 tables  1
+  Snapshot 1 type    logical from consistent snapshot
+  Snapshot 1 version 1
+  Snapshot 1 tables  1
+
+Catalog summary:
+
+  Character sets:         2
+  Databases:              3
+  Tables:                 2
+  Other per db objects:   1
+
+Catalog details:
+
+  Character set 'utf8'
+  Character set 'utf8'
+  Database 'mysqltest1'
+    Table  'mysqltest1'.'t1'
+  Database 'mysqltest2'
+    Table  'mysqltest2'.'t1'
+  Database 'mysqltest3'
+    View   'mysqltest3'.'v1'
+
+Meta data:
+
+  Database 'mysqltest1' statement: 'CREATE DATABASE `mysqltest1` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest1' extra data length: 0
+
+    Table 'mysqltest1'.'t1' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t1` (
+  `c1` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t1' extra data length: 0
+
+  Database 'mysqltest2' statement: 'CREATE DATABASE `mysqltest2` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest2' extra data length: 0
+
+    Table 'mysqltest2'.'t1' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t1` (
+  `c1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t1' extra data length: 0
+
+  Database 'mysqltest3' statement: 'CREATE DATABASE `mysqltest3` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest3' extra data length: 0
+
+    View 'mysqltest3'.'v1' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v1` AS select (`mysqltest1`.`t1`.`c1` + `mysqltest2`.`t1`.`c1`) AS `c1` from (`mysqltest1`.`t1` join `mysqltest2`.`t1`)'
+    View 'mysqltest3'.'v1' extra data length: 0
+
+Data chunks:
+  Snapshot 0 has 1025 bytes for table 'mysqltest1'.'t1'
+
+Data totals:
+
+  Snapshot 0 has 1025 bytes for table 'mysqltest1'.'t1'
+  Snapshot 1 has 0 bytes for table 'mysqltest2'.'t1'
+
+Summary:
+
+Creation time: #
+Validity time: #
+Finish   time: #
+No binlog information
+========
+DROP DATABASE mysqltest1;
+DROP DATABASE mysqltest2;
+DROP DATABASE mysqltest3;
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+CREATE DATABASE mysqltest3;
+CREATE TABLE mysqltest1.t1 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE mysqltest1.t2 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE mysqltest2.t1 (c1 INT) ENGINE=InnoDB;
+CREATE TABLE mysqltest2.t2 (c1 INT) ENGINE=InnoDB;
+CREATE VIEW  mysqltest3.v1 AS
+SELECT mysqltest1.t1.c1 + mysqltest2.t1.c1 AS c1
+FROM mysqltest1.t1, mysqltest2.t1;
+CREATE VIEW  mysqltest3.v2 AS
+SELECT mysqltest1.t2.c1 + mysqltest2.t2.c1 AS c1
+FROM mysqltest1.t2, mysqltest2.t2;
+BACKUP DATABASE mysqltest1, mysqltest2, mysqltest3 TO 'mysqltest.bak';
+backup_id
+#
+
+Full set of most relevant information plus snapshots and data chunks:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+Snapshot count:      2
+
+Snapshots:
+
+  Snapshot 0 type    native from 'MyISAM'  version 1.0
+  Snapshot 0 version 1
+  Snapshot 0 tables  1
+  Snapshot 1 type    logical from consistent snapshot
+  Snapshot 1 version 1
+  Snapshot 1 tables  1
+
+Catalog summary:
+
+  Character sets:         2
+  Databases:              3
+  Tables:                 4
+  Other per db objects:   2
+
+Catalog details:
+
+  Character set 'utf8'
+  Character set 'utf8'
+  Database 'mysqltest1'
+    Table  'mysqltest1'.'t1'
+    Table  'mysqltest1'.'t2'
+  Database 'mysqltest2'
+    Table  'mysqltest2'.'t1'
+    Table  'mysqltest2'.'t2'
+  Database 'mysqltest3'
+    View   'mysqltest3'.'v1'
+    View   'mysqltest3'.'v2'
+
+Meta data:
+
+  Database 'mysqltest1' statement: 'CREATE DATABASE `mysqltest1` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest1' extra data length: 0
+
+    Table 'mysqltest1'.'t1' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t1` (
+  `c1` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t1' extra data length: 0
+
+    Table 'mysqltest1'.'t2' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t2` (
+  `c1` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t2' extra data length: 0
+
+  Database 'mysqltest2' statement: 'CREATE DATABASE `mysqltest2` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest2' extra data length: 0
+
+    Table 'mysqltest2'.'t1' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t1` (
+  `c1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t1' extra data length: 0
+
+    Table 'mysqltest2'.'t2' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t2` (
+  `c1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t2' extra data length: 0
+
+  Database 'mysqltest3' statement: 'CREATE DATABASE `mysqltest3` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest3' extra data length: 0
+
+    View 'mysqltest3'.'v1' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v1` AS select (`mysqltest1`.`t1`.`c1` + `mysqltest2`.`t1`.`c1`) AS `c1` from (`mysqltest1`.`t1` join `mysqltest2`.`t1`)'
+    View 'mysqltest3'.'v1' extra data length: 0
+
+    View 'mysqltest3'.'v2' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v2` AS select (`mysqltest1`.`t2`.`c1` + `mysqltest2`.`t2`.`c1`) AS `c1` from (`mysqltest1`.`t2` join `mysqltest2`.`t2`)'
+    View 'mysqltest3'.'v2' extra data length: 0
+
+Data chunks:
+  Snapshot 0 has 1025 bytes for table 'mysqltest1'.'t1'
+  Snapshot 0 has 1025 bytes for table 'mysqltest1'.'t2'
+
+Data totals:
+
+  Snapshot 0 has 1025 bytes for table 'mysqltest1'.'t1'
+  Snapshot 0 has 1025 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 0 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 0 bytes for table 'mysqltest2'.'t2'
+
+Summary:
+
+Creation time: #
+Validity time: #
+Finish   time: #
+No binlog information
+========
+DROP DATABASE mysqltest1;
+DROP DATABASE mysqltest2;
+DROP DATABASE mysqltest3;
+CREATE DATABASE mysqltest1;
+BACKUP DATABASE mysqltest1 TO 'mysqltest.bak' WITH COMPRESSION;
+backup_id
+#
+
+Full set of most relevant information plus snapshots and data chunks:
+========
+
+Image path: #
+Image size: #
+Image compression:   gzip
+Image version:       1
+Creation time: #
+Server version: #
+Snapshot count:      0
+
+Snapshots:
+
+
+Catalog summary:
+
+  Character sets:         2
+  Databases:              1
+  Tables:                 0
+  Other per db objects:   0
+
+Catalog details:
+
+  Character set 'utf8'
+  Character set 'utf8'
+  Database 'mysqltest1'
+
+Meta data:
+
+  Database 'mysqltest1' statement: 'CREATE DATABASE `mysqltest1` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest1' extra data length: 0
+
+Data chunks:
+
+Data totals:
+
+
+Summary:
+
+Creation time: #
+Validity time: #
+Finish   time: #
+No binlog information
+========
+DROP DATABASE mysqltest1;

=== added file 'mysql-test/suite/backup/r/backup_client_binlog.result'
--- a/mysql-test/suite/backup/r/backup_client_binlog.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/r/backup_client_binlog.result	2008-10-29 15:25:00 +0000
@@ -0,0 +1,122 @@
+SET SESSION max_heap_table_size=67108864;
+DROP DATABASE IF EXISTS mysqltest1;
+DROP DATABASE IF EXISTS mysqltest2;
+DROP DATABASE IF EXISTS mysqltest3;
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+CREATE DATABASE mysqltest3;
+CREATE TABLE mysqltest1.t1 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE mysqltest1.t2 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE mysqltest2.t1 (c1 INT) ENGINE=InnoDB;
+CREATE TABLE mysqltest2.t2 (c1 INT) ENGINE=InnoDB;
+CREATE VIEW  mysqltest3.v1 AS
+SELECT mysqltest1.t1.c1 + mysqltest2.t1.c1 AS c1
+FROM mysqltest1.t1, mysqltest2.t1;
+CREATE VIEW  mysqltest3.v2 AS
+SELECT mysqltest1.t2.c1 + mysqltest2.t2.c1 AS c1
+FROM mysqltest1.t2, mysqltest2.t2;
+BACKUP DATABASE mysqltest1, mysqltest2, mysqltest3 TO 'mysqltest.bak';
+backup_id
+#
+
+Full set of most relevant information plus snapshots and data chunks:
+========
+
+Image path: #
+Image size: #
+Image compression:   none
+Image version:       1
+Creation time: #
+Server version: #
+Image options:       BINLOG
+Snapshot count:      2
+
+Snapshots:
+
+  Snapshot 0 type    native from 'MyISAM'  version 1.0
+  Snapshot 0 version 1
+  Snapshot 0 tables  1
+  Snapshot 1 type    logical from consistent snapshot
+  Snapshot 1 version 1
+  Snapshot 1 tables  1
+
+Catalog summary:
+
+  Character sets:         2
+  Databases:              3
+  Tables:                 4
+  Other per db objects:   2
+
+Catalog details:
+
+  Character set 'utf8'
+  Character set 'utf8'
+  Database 'mysqltest1'
+    Table  'mysqltest1'.'t1'
+    Table  'mysqltest1'.'t2'
+  Database 'mysqltest2'
+    Table  'mysqltest2'.'t1'
+    Table  'mysqltest2'.'t2'
+  Database 'mysqltest3'
+    View   'mysqltest3'.'v1'
+    View   'mysqltest3'.'v2'
+
+Meta data:
+
+  Database 'mysqltest1' statement: 'CREATE DATABASE `mysqltest1` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest1' extra data length: 0
+
+    Table 'mysqltest1'.'t1' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t1` (
+  `c1` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t1' extra data length: 0
+
+    Table 'mysqltest1'.'t2' statement: 'USE `mysqltest1`; CREATE TABLE `mysqltest1`.`t2` (
+  `c1` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1'
+    Table 'mysqltest1'.'t2' extra data length: 0
+
+  Database 'mysqltest2' statement: 'CREATE DATABASE `mysqltest2` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest2' extra data length: 0
+
+    Table 'mysqltest2'.'t1' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t1` (
+  `c1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t1' extra data length: 0
+
+    Table 'mysqltest2'.'t2' statement: 'USE `mysqltest2`; CREATE TABLE `mysqltest2`.`t2` (
+  `c1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1'
+    Table 'mysqltest2'.'t2' extra data length: 0
+
+  Database 'mysqltest3' statement: 'CREATE DATABASE `mysqltest3` DEFAULT CHARACTER SET latin1'
+  Database 'mysqltest3' extra data length: 0
+
+    View 'mysqltest3'.'v1' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v1` AS select (`mysqltest1`.`t1`.`c1` + `mysqltest2`.`t1`.`c1`) AS `c1` from (`mysqltest1`.`t1` join `mysqltest2`.`t1`)'
+    View 'mysqltest3'.'v1' extra data length: 0
+
+    View 'mysqltest3'.'v2' statement: 'USE `mysqltest3`; SET CHARACTER_SET_CLIENT = 'latin1'; SET COLLATION_CONNECTION = 'latin1_swedish_ci'; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest3`.`v2` AS select (`mysqltest1`.`t2`.`c1` + `mysqltest2`.`t2`.`c1`) AS `c1` from (`mysqltest1`.`t2` join `mysqltest2`.`t2`)'
+    View 'mysqltest3'.'v2' extra data length: 0
+
+Data chunks:
+  Snapshot 0 has 1025 bytes for table 'mysqltest1'.'t1'
+  Snapshot 0 has 1025 bytes for table 'mysqltest1'.'t2'
+
+Data totals:
+
+  Snapshot 0 has 1025 bytes for table 'mysqltest1'.'t1'
+  Snapshot 0 has 1025 bytes for table 'mysqltest1'.'t2'
+  Snapshot 1 has 0 bytes for table 'mysqltest2'.'t1'
+  Snapshot 1 has 0 bytes for table 'mysqltest2'.'t2'
+
+Summary:
+
+Creation time: #
+Validity time: #
+Finish   time: #
+Binlog coordinates:  master-bin.000001:1641
+Binlog group coords: [NULL]:0
+========
+DROP DATABASE mysqltest1;
+DROP DATABASE mysqltest2;
+DROP DATABASE mysqltest3;

=== added file 'mysql-test/suite/backup/t/backup_client.test'
--- a/mysql-test/suite/backup/t/backup_client.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_client.test	2008-10-29 15:25:00 +0000
@@ -0,0 +1,364 @@
+#
+# WL#4534 - Backup client program
+#
+# Tests with no binlog turned on.
+#
+--source include/not_embedded.inc
+--source include/have_innodb.inc
+SET SESSION max_heap_table_size=67108864;
+#
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest1;
+DROP DATABASE IF EXISTS mysqltest2;
+DROP DATABASE IF EXISTS mysqltest3;
+--enable_warnings
+#
+# Create some databases.
+#
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+CREATE DATABASE mysqltest3;
+#
+# Create a table.
+#
+CREATE TABLE mysqltest1.t1 (
+  c1 INT PRIMARY KEY AUTO_INCREMENT,
+  c2 VARCHAR(30000)) ENGINE=MyISAM;
+INSERT INTO mysqltest1.t1 VALUES(NULL, REPEAT('A', 30000));
+INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+#INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+#INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+#INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+#INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+#INSERT INTO mysqltest1.t1 SELECT NULL, c2 FROM mysqltest1.t1;
+#SELECT COUNT(*) FROM mysqltest1.t1;
+#SELECT c1, SUBSTR(c2 FROM 1 FOR 30) FROM mysqltest1.t1;
+#
+# Create more tables.
+#
+CREATE TABLE mysqltest1.t2 ENGINE=InnoDB AS SELECT * FROM mysqltest1.t1;
+#SELECT COUNT(*) FROM mysqltest1.t2;
+#SELECT c1, SUBSTR(c2 FROM 1 FOR 30) FROM mysqltest1.t2;
+CREATE TABLE mysqltest1.t3 ENGINE=MEMORY AS SELECT * FROM mysqltest1.t1;
+#
+CREATE TABLE mysqltest2.t1 ENGINE=InnoDB AS SELECT * FROM mysqltest1.t1;
+CREATE TABLE mysqltest2.t2 ENGINE=MEMORY AS SELECT * FROM mysqltest1.t1;
+CREATE TABLE mysqltest2.t3 ENGINE=MyISAM AS SELECT * FROM mysqltest1.t1;
+#
+CREATE TABLE mysqltest3.t1 ENGINE=MEMORY AS SELECT * FROM mysqltest1.t1;
+CREATE TABLE mysqltest3.t2 ENGINE=MyISAM AS SELECT * FROM mysqltest1.t1;
+CREATE TABLE mysqltest3.t3 ENGINE=InnoDB AS SELECT * FROM mysqltest1.t1;
+#
+# Create views.
+#
+CREATE VIEW mysqltest1.v1 (c1, c2, c3, c4) AS
+  SELECT c1, c2, c1 IN (SELECT c1+2 FROM mysqltest1.t1),
+  c1 = ALL (SELECT c1 FROM mysqltest1.t1) FROM mysqltest1.t1;
+SHOW CREATE VIEW mysqltest1.v1;
+CREATE VIEW mysqltest1.v2 AS SELECT c2, c3 FROM mysqltest1.v1;
+SHOW CREATE VIEW mysqltest1.v2;
+#
+CREATE VIEW mysqltest2.v1 (c1, c2, c3, c4) AS
+  SELECT connection_id(), pi(), current_user(), version();
+SHOW CREATE VIEW mysqltest2.v1;
+CREATE VIEW mysqltest2.v2 AS
+  SELECT mysqltest2.t2.c1 AS c1, mysqltest2.t2.c2 AS c2
+    FROM mysqltest2.t2, mysqltest2.t3 UNION ALL
+  SELECT mysqltest2.t2.c1 AS c3, mysqltest2.t2.c2 AS c4
+    FROM mysqltest2.t2, mysqltest2.t3;
+SHOW CREATE VIEW mysqltest2.v2;
+#
+CREATE VIEW mysqltest3.v1 (c1, c2) AS
+  SELECT mysqltest1.v1.c1 AS c1, mysqltest2.v2.c1 AS c2
+  FROM mysqltest1.v1, mysqltest2.v2
+  WHERE mysqltest1.v1.c1 = mysqltest2.v2.c1;
+SHOW CREATE VIEW mysqltest3.v1;
+CREATE VIEW mysqltest3.v2 (c1, c2) AS
+  SELECT mysqltest1.v1.c1 AS c1, mysqltest2.v2.c1 AS c2
+  FROM mysqltest1.v1 LEFT JOIN mysqltest2.v2
+  ON (mysqltest1.v1.c1 = mysqltest2.v2.c1);
+SHOW CREATE VIEW mysqltest3.v2;
+#
+# Backup.
+#
+--replace_column 1 #
+BACKUP DATABASE mysqltest1, mysqltest2, mysqltest3 TO 'mysqltest.bak';
+#
+#--echo
+#--exec ls -l $MYSQLTEST_VARDIR/master-data
+#--echo
+#--exec ls -l $MYSQLTEST_VARDIR/master-data/mysqltest[123]
+#--echo
+--error 0, 1
+--remove_file /tmp/wl4534-test-1.bak
+--copy_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak /tmp/wl4534-test-1.bak
+#
+--echo
+--echo Show help output:
+--echo ========
+--replace_regex /.*mysqlbackup Ver .* for .* at .*[^[:space:]]/mysqlbackup Ver # for # at #/ /Usage: .*mysqlbackup /Usage: mysqlbackup /
+exec $MYSQL_BACKUP --help;
+--echo ========
+--echo
+--echo Minimal output without options:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--echo
+--echo Full set of most relevant information:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP --all \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--echo
+--echo Full set of most relevant information, verbosely:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP -v --all \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--echo
+--echo Full set of most relevant information plus snapshots:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP --all --snapshots \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--echo
+--echo Full set of most relevant information plus snapshots, verbosely:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP -v --all --snapshots \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--echo
+--echo Full set of most relevant information plus data chunks:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP --all --data-chunks \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--echo
+--echo Full set of most relevant information plus snapshots and data chunks:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP --all --snapshots --data-chunks \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--echo
+--echo Search for an object:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP --search=utf8 \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--echo
+--echo Search for an object in databases:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP --search=%.t2 \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo
+--echo Search for an object in databases and show create statement:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP --search=%.t2 --metadata-statements \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+#
+# Backup with compression.
+#
+--remove_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak
+--replace_column 1 #
+BACKUP DATABASE mysqltest1, mysqltest2, mysqltest3 TO 'mysqltest.bak'
+  WITH COMPRESSION;
+#
+--error 0, 1
+--remove_file /tmp/wl4534-test-2.bak
+--copy_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak /tmp/wl4534-test-2.bak
+#
+--echo
+--echo Full set of most relevant information plus snapshots, verbosely:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP -v --all --snapshots \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+#
+--remove_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak
+DROP DATABASE mysqltest1;
+DROP DATABASE mysqltest2;
+DROP DATABASE mysqltest3;
+#
+# Create one empty database.
+#
+CREATE DATABASE mysqltest1;
+#
+# Backup.
+#
+--replace_column 1 #
+BACKUP DATABASE mysqltest1 TO 'mysqltest.bak';
+#
+--error 0, 1
+--remove_file /tmp/wl4534-test-3.bak
+--copy_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak /tmp/wl4534-test-3.bak
+#
+--echo
+--echo Full set of most relevant information plus snapshots and data chunks:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP -v --all --snapshots --data-chunks \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--remove_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak
+DROP DATABASE mysqltest1;
+#
+# Create two empty databases.
+#
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+#
+# Backup.
+#
+--replace_column 1 #
+BACKUP DATABASE mysqltest1, mysqltest2 TO 'mysqltest.bak';
+#
+--error 0, 1
+--remove_file /tmp/wl4534-test-4.bak
+--copy_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak /tmp/wl4534-test-4.bak
+#
+--echo
+--echo Full set of most relevant information plus snapshots and data chunks:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP -v --all --snapshots --data-chunks \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--remove_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak
+DROP DATABASE mysqltest1;
+DROP DATABASE mysqltest2;
+#
+# Create three empty databases.
+#
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+CREATE DATABASE mysqltest3;
+#
+# Backup.
+#
+--replace_column 1 #
+BACKUP DATABASE mysqltest1, mysqltest2, mysqltest3 TO 'mysqltest.bak';
+#
+--error 0, 1
+--remove_file /tmp/wl4534-test-5.bak
+--copy_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak /tmp/wl4534-test-5.bak
+#
+--echo
+--echo Full set of most relevant information plus snapshots and data chunks:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP -v --all --snapshots --data-chunks \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--remove_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak
+DROP DATABASE mysqltest1;
+DROP DATABASE mysqltest2;
+DROP DATABASE mysqltest3;
+#
+# Create three databases with one element each.
+#
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+CREATE DATABASE mysqltest3;
+CREATE TABLE mysqltest1.t1 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE mysqltest2.t1 (c1 INT) ENGINE=InnoDB;
+CREATE VIEW  mysqltest3.v1 AS
+  SELECT mysqltest1.t1.c1 + mysqltest2.t1.c1 AS c1
+    FROM mysqltest1.t1, mysqltest2.t1;
+#
+# Backup.
+#
+--replace_column 1 #
+BACKUP DATABASE mysqltest1, mysqltest2, mysqltest3 TO 'mysqltest.bak';
+#
+--error 0, 1
+--remove_file /tmp/wl4534-test-6.bak
+--copy_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak /tmp/wl4534-test-6.bak
+#
+--echo
+--echo Full set of most relevant information plus snapshots and data chunks:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP -v --all --snapshots --data-chunks \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--remove_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak
+DROP DATABASE mysqltest1;
+DROP DATABASE mysqltest2;
+DROP DATABASE mysqltest3;
+#
+# Create three databases with two elements each.
+#
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+CREATE DATABASE mysqltest3;
+CREATE TABLE mysqltest1.t1 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE mysqltest1.t2 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE mysqltest2.t1 (c1 INT) ENGINE=InnoDB;
+CREATE TABLE mysqltest2.t2 (c1 INT) ENGINE=InnoDB;
+CREATE VIEW  mysqltest3.v1 AS
+  SELECT mysqltest1.t1.c1 + mysqltest2.t1.c1 AS c1
+    FROM mysqltest1.t1, mysqltest2.t1;
+CREATE VIEW  mysqltest3.v2 AS
+  SELECT mysqltest1.t2.c1 + mysqltest2.t2.c1 AS c1
+    FROM mysqltest1.t2, mysqltest2.t2;
+#
+# Backup.
+#
+--replace_column 1 #
+BACKUP DATABASE mysqltest1, mysqltest2, mysqltest3 TO 'mysqltest.bak';
+#
+--error 0, 1
+--remove_file /tmp/wl4534-test-7.bak
+--copy_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak /tmp/wl4534-test-7.bak
+#
+--echo
+--echo Full set of most relevant information plus snapshots and data chunks:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP -v --all --snapshots --data-chunks \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--remove_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak
+DROP DATABASE mysqltest1;
+DROP DATABASE mysqltest2;
+DROP DATABASE mysqltest3;
+#
+# Create one empty database.
+#
+CREATE DATABASE mysqltest1;
+#
+# Backup with compression.
+#
+--replace_column 1 #
+BACKUP DATABASE mysqltest1 TO 'mysqltest.bak' WITH COMPRESSION;
+#
+--error 0, 1
+--remove_file /tmp/wl4534-test-8.bak
+--copy_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak /tmp/wl4534-test-8.bak
+#
+--echo
+--echo Full set of most relevant information plus snapshots and data chunks:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP -v --all --snapshots --data-chunks \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--remove_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak
+DROP DATABASE mysqltest1;

=== added file 'mysql-test/suite/backup/t/backup_client_binlog.test'
--- a/mysql-test/suite/backup/t/backup_client_binlog.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/backup/t/backup_client_binlog.test	2008-10-29 15:25:00 +0000
@@ -0,0 +1,52 @@
+#
+# WL#4534 - Backup client program
+#
+# Tests with binlog turned on.
+#
+--source include/not_embedded.inc
+--source include/have_binlog_format_mixed.inc
+--source include/have_innodb.inc
+SET SESSION max_heap_table_size=67108864;
+#
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest1;
+DROP DATABASE IF EXISTS mysqltest2;
+DROP DATABASE IF EXISTS mysqltest3;
+--enable_warnings
+#
+# Create three databases with two elements each.
+#
+CREATE DATABASE mysqltest1;
+CREATE DATABASE mysqltest2;
+CREATE DATABASE mysqltest3;
+CREATE TABLE mysqltest1.t1 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE mysqltest1.t2 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE mysqltest2.t1 (c1 INT) ENGINE=InnoDB;
+CREATE TABLE mysqltest2.t2 (c1 INT) ENGINE=InnoDB;
+CREATE VIEW  mysqltest3.v1 AS
+  SELECT mysqltest1.t1.c1 + mysqltest2.t1.c1 AS c1
+    FROM mysqltest1.t1, mysqltest2.t1;
+CREATE VIEW  mysqltest3.v2 AS
+  SELECT mysqltest1.t2.c1 + mysqltest2.t2.c1 AS c1
+    FROM mysqltest1.t2, mysqltest2.t2;
+#
+# Backup.
+#
+--replace_column 1 #
+BACKUP DATABASE mysqltest1, mysqltest2, mysqltest3 TO 'mysqltest.bak';
+#
+--error 0, 1
+--remove_file /tmp/wl4534-test-101.bak
+--copy_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak /tmp/wl4534-test-101.bak
+#
+--echo
+--echo Full set of most relevant information plus snapshots and data chunks:
+--echo ========
+--replace_regex /Image path: .*'/Image path: #/ /Image size: .*[Bs]/Image size: #/ / time: .*UTC/ time: #/ /Server version: .*\)/Server version: #/
+exec $MYSQL_BACKUP -v --all --snapshots --data-chunks \
+     $MYSQLTEST_VARDIR/master-data/mysqltest.bak;
+--echo ========
+--remove_file $MYSQLTEST_VARDIR/master-data/mysqltest.bak
+DROP DATABASE mysqltest1;
+DROP DATABASE mysqltest2;
+DROP DATABASE mysqltest3;

Thread
bzr commit into mysql-6.0 branch (ingo.struewing:2717) WL#4534Ingo Struewing29 Oct