diff --git a/bin/pt-archiver b/bin/pt-archiver index bfe5b2fd..9ff4b638 100755 --- a/bin/pt-archiver +++ b/bin/pt-archiver @@ -3962,18 +3962,30 @@ sub main { # Open the file and print the header to it. if ( $archive_file ) { my $need_hdr = $o->get('header') && !-f $archive_file; - my $charset = lc $o->get('charset'); - if ( $charset ) { - $archive_fh = IO::File->new($archive_file, ">>:$charset") - or die "Cannot open $charset $archive_file: $OS_ERROR\n"; - } - else { - $archive_fh = IO::File->new($archive_file, ">>") - or die "Cannot open $archive_file: $OS_ERROR\n"; - } + my $charset = $o->get('charset') || ''; + if ($charset eq 'utf8') { + $charset = ":$charset"; + } + elsif ($charset) { + eval { require Encode } + or (PTDEBUG && + _d("Couldn't load Encode: ", $EVAL_ERROR, + "Going to try using the charset ", + "passed in without checking it.")); + # No need to punish a user if they did their + # homework and passed in an official charset, + # rather than an alias. + $charset = ":encoding(" + . (defined &Encode::resolve_alias + ? Encode::resolve_alias($charset) || $charset + : $charset) + . ")"; + } + $archive_fh = IO::File->new($archive_file, ">>$charset") + or die "Cannot open $charset $archive_file: $OS_ERROR\n"; $archive_fh->autoflush(1) unless $o->get('buffer'); if ( $need_hdr ) { - print $archive_fh '', escape(\@sel_cols), "\n" + print { $archive_fh } '', escape(\@sel_cols), "\n" or die "Cannot write to $archive_file: $OS_ERROR\n"; } } diff --git a/t/pt-archiver/file.t b/t/pt-archiver/file.t index 0bde28fe..8a2605da 100644 --- a/t/pt-archiver/file.t +++ b/t/pt-archiver/file.t @@ -23,7 +23,7 @@ if ( !$dbh ) { plan skip_all => 'Cannot connect to sandbox master'; } else { - plan tests => 5; + plan tests => 11; } my $output; @@ -71,6 +71,47 @@ EOF , 'File has the right stuff with only some columns'); `rm -f archive.test.table_1`; +# ############################################################################# +# Bug #903379: --file & --charset could cause warnings and exceptions +# ############################################################################# + +sub test_charset { + my ($charset) = @_; + + $sb->load_file('master', 't/pt-archiver/samples/table1.sql'); + local $@; + eval { + pt_archiver::main("-c", "b,c", qw(--where 1=1 --header), + "--source", "D=test,t=table_1,F=$cnf", + '--file', '/tmp/%Y-%m-%d-%D_%H:%i:%s.%t', + '--no-check-charset', + '--charset', $charset, + ); + }; + + ok !$@, "--charset $charset works"; +} + +for my $charset (qw(latin1 iso-8859-1 utf8 UTF-8 )) { + test_charset($charset); +} + +my $warning; +local $SIG{__WARN__} = sub { $warning .= shift }; +my $out = output( sub { + $sb->load_file('master', 't/pt-archiver/samples/table1.sql'); + pt_archiver::main("-c", "b,c", qw(--where 1=1 --header), + "--source", "D=test,t=table_1,F=$cnf", + '--file', '/tmp/%Y-%m-%d-%D_%H:%i:%s.%t', + '--no-check-charset', + '--charset', "some_charset_that_doesn't_exist", + ); + }, +); + +like($out, qr/\QCannot open :encoding(some_chars/, "..but an unknown charset fails"); +like($warning, qr/Cannot find encoding/, "..and throws a useful warning"); + # ############################################################################# # Done. # #############################################################################