#!/usr/bin/env perl
# See the NOTICE file distributed with this work for additional information
# regarding copyright ownership.
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#      http://www.apache.org/licenses/LICENSE-2.0
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


############################################
## A script which replaces using cp on MySQL data files to do a quick
## database rename. This also does some post modification to the VIEW
## frm files to complete the move.
############################################

use strict;
use warnings;

use Pod::Usage;
use File::Basename qw/basename/;
use File::Spec;
use Tie::File;

my $DEBUG = 1;

if(@ARGV == 1) {
  pod2usage(-exitval => 0, -verbose => 1) if $ARGV[0] =~ '^-?-h(?:elp)?$';
  pod2usage(-exitval => 0, -verbose => 2) if $ARGV[0] =~ '^-?-m(?:an)?$';
  pod2usage(-msg => 'Bad arguments. Did you mean -help or -man?', -exitval => 1, -verbose => 1);
}

if(@ARGV != 2) {
  pod2usage(-msg => 'Incorrect number of args. Invocation should be mv_mysqldb src trg', -exitval => 1, -verbose => 1);
}

my ($source_location, $target_location) = @ARGV;

if(! -d $source_location) {
  pod2usage(-msg => "The source location '${source_location}' does not exist or is not a directory", -exitval => 1, -verbose => 1);
}

if($source_location eq '.') {
  pod2usage(-msg => "The source location cannot be the current directory. cd .. and then re-run", -exitval => 1, -verbose => 1);
}
if($target_location eq '.') {
  pod2usage(-msg => "The target location cannot be the current directory. cd .. and then re-run", -exitval => 1, -verbose => 1);
}


my $cmd = "cp -r $source_location $target_location"; 
system($cmd) and die "Could not perform the copy";

my $source_db = basename($source_location);
my $target_db = basename($target_location);

opendir my $dh, $target_location or die "Cannot open the target directory $target_location: $!";
my @files = grep { $_ =~ /\.frm$/ } readdir($dh);
closedir $dh or die "Cannot close the target dir handle for $target_location: $!";

my $ok = 1;

foreach my $frm (@files) {
  my $myd = $frm;
  $myd =~ s/\.frm$/.MYD/;
  if( -f File::Spec->catfile($target_location, $myd)) {
    next;
  }
  
  my $frm_loc = File::Spec->catfile($target_location, $frm);
  tie my @frm_array, 'Tie::File', $frm_loc or die "Cannot open $frm_loc and tie it for IO access: $!";
  my $first_line = $frm_array[0];
  
  if(defined $first_line && $first_line =~ /TYPE=VIEW/) {
    for (@frm_array) {
      s/`$source_db`/`$target_db`/g;
    }
  }
  else {
    warn "ERROR! $frm was not a view. Move this DB back & check if it was an InnoDB table";
    $ok = 0;
  }
  
  untie @frm_array;
}

die "Errors were detected during the view fixing stage" if !$ok;

__END__

=pod

=head1 NAME

cp_mysqldb

=head1 SYNOPSIS

  cp_mysqldb /path/to/source_db /path/to/target_db

=head1 DESCRIPTION

This script acts like a recursive cp command except it has a post processing
section where we scan for frm files which lack a MYI/MYD file. This 
normally indicates we have a view which allows us to rename the internally
referenced tables to the new correct name.

You must still flush the database to ensure the new db is picked up on.

=cut
