LOAD DATA LOCAL INFILE: The hopefully final fix.

This introduces a L option to the DSNs of pt-upgrade and pt-archiver,
which turns on mysql_local_infile.
This commit is contained in:
Brian Fraser fraserb@gmail.com
2012-10-17 19:19:44 -03:00
parent a433fa7d1c
commit 9e832790f8
11 changed files with 91 additions and 23 deletions

View File

@@ -2142,7 +2142,8 @@ sub get_cxn_params {
. join(';', map { "$opts{$_}->{dsn}=$info->{$_}" }
grep { defined $info->{$_} }
qw(F h P S A))
. ';mysql_read_default_group=client;mysql_local_infile=1';
. ';mysql_read_default_group=client'
. ($info->{L} ? ';mysql_local_infile=1' : '');
}
PTDEBUG && _d($dsn);
return ($dsn, $info->{u}, $info->{p});
@@ -2171,6 +2172,9 @@ sub get_dbh {
mysql_enable_utf8 => ($cxn_string =~ m/charset=utf8/i ? 1 : 0),
};
@{$defaults}{ keys %$opts } = values %$opts;
if (delete $defaults->{L}) { # L for LOAD DATA LOCAL INFILE, our own extension
$defaults->{mysql_local_infile} = 1;
}
if ( $opts->{mysql_use_result} ) {
$defaults->{mysql_use_result} = 1;
@@ -6198,6 +6202,10 @@ waits until the insertion is successful.
The L<"--low-priority-insert">, L<"--replace">, and L<"--ignore"> options work
with this option, but L<"--delayed-insert"> does not.
If C<LOAD DATA LOCAL INFILE> throws an error in the lines of C<The used
command is not allowed with this MySQL version>, refer to the documentation
for the C<L> DSN option.
=item --charset
short form: -A; type: string
@@ -6921,6 +6929,26 @@ copy: yes
Index to use.
=item * L
copy: yes
Explicitly enable LOAD DATA LOCAL INFILE.
For some reason, some vendors compile libmysql without the
--enable-local-infile option, which disables the statement. This can
lead to weird situations, like the server allowing LOCAL INFILE, but
the client throwing exceptions if it's used.
However, as long as the server allows LOAD DATA, clients can easily
reenable it; See L<https://dev.mysql.com/doc/refman/5.0/en/load-data-local.html>
and L<http://search.cpan.org/~capttofu/DBD-mysql/lib/DBD/mysql.pm>.
This option does exactly that.
Although we've not found a case where turning this option leads to errors or
differing behavior, to be on the safe side, this option is not
on by default.
=item * m
copy: no

View File

@@ -245,7 +245,8 @@ sub get_cxn_params {
. join(';', map { "$opts{$_}->{dsn}=$info->{$_}" }
grep { defined $info->{$_} }
qw(F h P S A))
. ';mysql_read_default_group=client;mysql_local_infile=1';
. ';mysql_read_default_group=client'
. ($info->{L} ? ';mysql_local_infile=1' : '');
}
PTDEBUG && _d($dsn);
return ($dsn, $info->{u}, $info->{p});
@@ -274,6 +275,9 @@ sub get_dbh {
mysql_enable_utf8 => ($cxn_string =~ m/charset=utf8/i ? 1 : 0),
};
@{$defaults}{ keys %$opts } = values %$opts;
if (delete $defaults->{L}) { # L for LOAD DATA LOCAL INFILE, our own extension
$defaults->{mysql_local_infile} = 1;
}
if ( $opts->{mysql_use_result} ) {
$defaults->{mysql_use_result} = 1;
@@ -12687,6 +12691,26 @@ dsn: host; copy: yes
Connect to host.
=item * L
copy: yes
Explicitly enable LOAD DATA LOCAL INFILE.
For some reason, some vendors compile libmysql without the
--enable-local-infile option, which disables the statement. This can
lead to weird situations, like the server allowing LOCAL INFILE, but
the client throwing exceptions if it's used.
However, as long as the server allows LOAD DATA, clients can easily
reenable it; See L<https://dev.mysql.com/doc/refman/5.0/en/load-data-local.html>
and L<http://search.cpan.org/~capttofu/DBD-mysql/lib/DBD/mysql.pm>.
This option does exactly that.
Although we've not found a case where turning this option leads to errors or
differing behavior, to be on the safe side, this option is not
on by default.
=item * p
dsn: password; copy: yes

View File

@@ -244,7 +244,8 @@ sub get_cxn_params {
. join(';', map { "$opts{$_}->{dsn}=$info->{$_}" }
grep { defined $info->{$_} }
qw(F h P S A))
. ';mysql_read_default_group=client;mysql_local_infile=1';
. ';mysql_read_default_group=client'
. ($info->{L} ? ';mysql_local_infile=1' : '');
}
PTDEBUG && _d($dsn);
return ($dsn, $info->{u}, $info->{p});
@@ -277,6 +278,9 @@ sub get_dbh {
mysql_enable_utf8 => ($cxn_string =~ m/charset=utf8/i ? 1 : 0),
};
@{$defaults}{ keys %$opts } = values %$opts;
if (delete $defaults->{L}) { # L for LOAD DATA LOCAL INFILE, our own extension
$defaults->{mysql_local_infile} = 1;
}
# Only add this if explicitly set because we're not sure if
# mysql_use_result=0 would leave default mysql_store_result

View File

@@ -138,6 +138,12 @@ our $dsn_opts = [
dsn => 'user',
copy => 1,
},
{
key => 'L',
desc => 'Pass mysql_local_infile to DBD::mysql',
dsn => 'mysql_local_infile',
copy => 1,
},
];
# Runs code, captures and returns its output.
@@ -788,7 +794,7 @@ sub tables_used {
sub can_load_data {
my $output = `/tmp/12345/use -e "SELECT * FROM percona_test.load_data" 2>/dev/null`;
return ($output || '') =~ /42/;
return ($output || '') =~ /1/;
}
1;

View File

@@ -118,6 +118,10 @@ sub get_dbh_for {
my $dp = $self->{DSNParser};
my $dsn = $dp->parse('h=127.0.0.1,u=msandbox,p=msandbox,P=' . $port_for{$server});
my $dbh;
# This is primarily for the benefit of CompareResults, but it's
# also quite convenient when using an affected OS
$cxn_ops->{L} = 1 if !exists $cxn_ops->{L}
&& !$self->can_load_data('master');
eval { $dbh = $dp->get_dbh($dp->get_cxn_params($dsn), $cxn_ops) };
if ( $EVAL_ERROR ) {
PTDEBUG && _d('Failed to get dbh for', $server, ':', $EVAL_ERROR);
@@ -396,6 +400,12 @@ sub clear_genlogs {
return;
}
sub can_load_data {
my ($self, $server) = @_;
my $output = $self->use($server, q{-e "SELECT * FROM percona_test.load_data"});
return ($output || '') =~ /1/;
}
1;
}
# ###########################################################################

View File

@@ -307,7 +307,7 @@ case $opt in
# LOAD DATA is disabled or broken on some boxes.
# PerconaTest exports $can_load_data which is true
# if percona_test.load_data has the 42 row,
# if percona_test.load_data has a row with 1,
# signaling that LOAD DATA LOCAL INFILE worked.
../util/check-load-data

View File

@@ -38,7 +38,7 @@ $dbh->do('INSERT INTO `test`.`table_5_copy` SELECT * FROM `test`.`table_5`');
$output = output(
sub { pt_archiver::main(qw(--no-ascend --limit 50 --bulk-insert),
qw(--bulk-delete --where 1=1 --statistics),
'--source', "D=test,t=table_5,F=$cnf",
'--source', "L=1,D=test,t=table_5,F=$cnf",
'--dest', "t=table_5_dest") },
);
like($output, qr/SELECT 105/, 'Fetched 105 rows');
@@ -63,7 +63,7 @@ $output = output(
sub { pt_archiver::main(
'--where', "id < 8", qw(--limit 100000 --txn-size 1000),
qw(--why-quit --statistics --bulk-insert),
'--source', "D=bri,t=t,F=$cnf",
'--source', "L=1,D=bri,t=t,F=$cnf",
'--dest', "t=t_arch") },
);
$rows = $dbh->selectall_arrayref('select id from bri.t order by id');

View File

@@ -36,7 +36,7 @@ $sb->load_file('master', "t/pt-archiver/samples/bulk_regular_insert.sql");
$dbh->do('use bri');
output(
sub { pt_archiver::main("--source", "F=$cnf,D=bri,t=t", qw(--dest t=t_arch --where 1=1 --bulk-insert --limit 3)) },
sub { pt_archiver::main("--source", "F=$cnf,D=bri,t=t,L=1", qw(--dest t=t_arch --where 1=1 --bulk-insert --limit 3)) },
);
my $t_rows = $dbh->selectall_arrayref('select * from t order by id');
@@ -70,7 +70,7 @@ is_deeply(
$sb->load_file('master', "t/pt-archiver/samples/bulk_regular_insert.sql");
$dbh->do('use bri');
`$cmd --source F=$cnf,D=bri,t=t --dest t=t_arch,m=bulk_regular_insert --where "1=1" --bulk-insert --limit 3`;
`$cmd --source F=$cnf,D=bri,t=t,L=1 --dest t=t_arch,m=bulk_regular_insert --where "1=1" --bulk-insert --limit 3`;
my $bri_t_rows = $dbh->selectall_arrayref('select * from t order by id');
my $bri_t_arch_rows = $dbh->selectall_arrayref('select * from t_arch order by id');

View File

@@ -30,7 +30,7 @@ elsif ( !$dbh2 ) {
plan skip_all => 'Cannot connect to second sandbox master';
}
my @host_args = ('h=127.1,P=12345', 'P=12348');
my @host_args = ('h=127.1,P=12345,L=1', 'P=12348');
my @op_args = (qw(-u msandbox -p msandbox),
'--compare', 'results,warnings',
'--zero-query-times',
@@ -104,9 +104,6 @@ $sb->wipe_clean($dbh2);
# Issue 951: mk-upgrade "I need a db argument" error with
# compare-results-method=rows
# #############################################################################
SKIP: {
skip "LOAD DATA LOCAL INFILE is disabled", 4 unless $can_load_data;
$sb->load_file('master', "$sample/002/tables.sql");
$sb->load_file('master1', "$sample/002/tables.sql");
@@ -116,7 +113,7 @@ SKIP: {
ok(
no_diff(
sub { pt_upgrade::main(@op_args, "$log/002/no-db.log",
'h=127.1,P=12345,D=test', 'P=12348,D=test',
'h=127.1,P=12345,D=test,L=1', 'P=12348,D=test',
qw(--compare-results-method rows --temp-database test)) },
"$sample/002/report-01.txt",
),
@@ -130,7 +127,7 @@ SKIP: {
ok(
no_diff(
sub { pt_upgrade::main(@op_args, "$log/002/no-db.log",
'h=127.1,P=12345,D=test', 'P=12348,D=test',
'h=127.1,P=12345,D=test,L=1', 'P=12348,D=test',
qw(--compare-results-method rows --temp-database tmp_db)) },
"$sample/002/report-01.txt",
),
@@ -151,15 +148,11 @@ SKIP: {
$sb->wipe_clean($dbh1);
$sb->wipe_clean($dbh2);
}
# #############################################################################
# Bug 926598: DBD::mysql bug causes pt-upgrade to use wrong
# precision (M) and scale (D)
# #############################################################################
SKIP: {
skip "LOAD DATA LOCAL INFILE is disabled", 2 unless $can_load_data;
$sb->load_file('master', "$sample/003/tables.sql");
$sb->load_file('master1', "$sample/003/tables.sql");
@@ -181,7 +174,6 @@ SKIP: {
qr/[`"]SUM\(total\)[`"]\s+double\sDEFAULT/i,
"No M,D in table def (bug 926598)"
);
}
# #############################################################################
# Done.

View File

@@ -36,7 +36,7 @@ $sb->load_file('master', 't/pt-upgrade/samples/001/tables.sql');
$sb->load_file('master1', 't/pt-upgrade/samples/001/tables.sql');
my $output;
my $cmd = "$trunk/bin/pt-upgrade h=127.1,P=12345,u=msandbox,p=msandbox P=12348 --compare results,warnings --zero-query-times --compare-results-method rows --limit 10";
my $cmd = "$trunk/bin/pt-upgrade h=127.1,P=12345,u=msandbox,p=msandbox,L=1 P=12348 --compare results,warnings --zero-query-times --compare-results-method rows --limit 10";
# This test really deals with,
# http://code.google.com/p/maatkit/issues/detail?id=754

View File

@@ -41,17 +41,21 @@ my $dbh = DBI->connect(
$dbh->do("CREATE TABLE IF NOT EXISTS percona_test.load_data (i int)");
`echo 42 > /tmp/load_data_test.$$`;
`echo 1 > /tmp/load_data_test.$$`;
eval {
$dbh->do("LOAD DATA LOCAL INFILE '/tmp/load_data_test.$$' INTO TABLE percona_test.load_data");
};
if ( $EVAL_ERROR ) {
$dbh->do("INSERT INTO percona_test.load_data (i) VALUES (0)");
}
unlink "/tmp/load_data_test.$$";
my ($val) = $dbh->selectrow_array("SELECT i FROM percona_test.load_data");
if ( ($val || 0) == 42 ) {
if ( ($val || 0) == 1 ) {
print "LOAD DATA LOCAL INFILE is enabled\n";
}
else {