Merged fix-821715-enable-local-infile-in-dsn

This commit is contained in:
Brian Fraser
2012-10-30 22:12:57 -03:00
14 changed files with 130 additions and 45 deletions

View File

@@ -2112,7 +2112,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_read_default_group=client'
. ($info->{L} ? ';mysql_local_infile=1' : '');
}
PTDEBUG && _d($dsn);
return ($dsn, $info->{u}, $info->{p});
@@ -2141,6 +2142,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;
@@ -6433,6 +6437,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
@@ -7163,6 +7171,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_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;
@@ -12936,6 +12940,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_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

@@ -116,6 +116,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,7 @@ sub clear_genlogs {
return;
}
sub is_cluster_node {
my ($self, $server) = @_;
@@ -410,6 +415,12 @@ sub is_cluster_node {
: 0;
}
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

@@ -318,7 +318,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

@@ -303,7 +303,6 @@ is_deeply(
# #############################################################################
my $tmpdir = '/tmp/mk-upgrade-res';
SKIP: {
skip "LOAD DATA LOCAL INFILE is disabled", 30 unless $can_load_data;
diag(`rm -rf $tmpdir 2>/dev/null; mkdir $tmpdir`);
@@ -728,7 +727,6 @@ is_deeply(
);
SKIP: {
skip "LOAD DATA LOCAL INFILE is disabled", 2 unless $can_load_data;
$cr = new CompareResults(
method => 'rows',

View File

@@ -218,7 +218,7 @@ is_deeply (
{ S => 'bar', h => 'host' } ))
],
[
'DBI:mysql:foo;host=me;mysql_socket=bar;mysql_read_default_group=client',
'DBI:mysql:foo;host=me;mysql_socket=bar;mysql_read_default_group=client;mysql_local_infile=1',
'a',
'b',
],
@@ -234,7 +234,7 @@ is_deeply (
{ S => 'bar', h => 'host' } ))
],
[
'DBI:mysql:foo;host=me;mysql_socket=bar;charset=foo;mysql_read_default_group=client',
'DBI:mysql:foo;host=me;mysql_socket=bar;charset=foo;mysql_read_default_group=client;mysql_local_infile=1',
'a',
'b',
],
@@ -568,6 +568,42 @@ like(
qr/\QUnknown system variable 'time_zoen'/,
"get_dbh dies with an unknown system variable"
);
$dp->prop('set-vars', undef);
# #############################################################################
# LOAD DATA LOCAL INFILE broken in some platforms
# https://bugs.launchpad.net/percona-toolkit/+bug/821715
# #############################################################################
SKIP: {
skip "LOAD DATA LOCAL INFILE already works here", 1 if $can_load_data;
my $dbh = $dp->get_dbh( $dp->get_cxn_params( $dsn ) );
use File::Temp qw(tempfile);
my ($fh, $filename) = tempfile( 'load_data_test.XXXXXXX', TMPDIR => 1 );
print { $fh } "42\n";
close $fh or die "Cannot close $filename: $!";
$dbh->do(q{DROP DATABASE IF EXISTS bug_821715});
$dbh->do(q{CREATE DATABASE bug_821715});
$dbh->do(q{CREATE TABLE IF NOT EXISTS bug_821715.load_data (i int)});
eval {
$dbh->do(qq{LOAD DATA LOCAL INFILE '$filename' INTO TABLE bug_821715.load_data});
};
is(
$EVAL_ERROR,
'',
"Even though LOCAL INFILE is off by default, the dbhs returned by DSNParser can use it"
);
unlink $filename;
$dbh->do(q{DROP DATABASE IF EXISTS bug_821715});
$dbh->disconnect();
}
# #############################################################################
# Done.

View File

@@ -184,7 +184,6 @@ ok(
# Bug 903387: pt-archiver doesn't honor b=1 flag to create SQL_LOG_BIN statement
# #############################################################################
SKIP: {
skip('LOAD DATA LOCAL INFILE is disabled', 3) if !$can_load_data;
$sb->load_file('master', "t/pt-archiver/samples/bulk_regular_insert.sql");
$sb->wait_for_slaves();

View File

@@ -22,9 +22,6 @@ my $dbh = $sb->get_dbh_for('master');
if ( !$dbh ) {
plan skip_all => 'Cannot connect to sandbox master';
}
elsif ( !$can_load_data ) {
plan skip_all => 'LOAD DATA LOCAL INFILE is disabled';
}
my $output;
my $rows;
@@ -41,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');
@@ -66,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

@@ -22,9 +22,6 @@ my $dbh = $sb->get_dbh_for('master');
if ( !$dbh ) {
plan skip_all => 'Cannot connect to sandbox master';
}
elsif ( !$can_load_data ) {
plan skip_all => 'LOAD DATA LOCAL INFILE is disabled';
}
my $output;
my $cnf = "/tmp/12345/my.sandbox.cnf";
@@ -39,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');
@@ -73,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',
@@ -61,9 +61,6 @@ ok(
'Report for multiple queries (checksum method)'
);
SKIP: {
skip "LOAD DATA LOCAL INFILE is disabled", 2 unless $can_load_data;
ok(
no_diff(
sub { pt_upgrade::main(@args, "$trunk/$sample/001/select-one.log",
@@ -81,7 +78,6 @@ SKIP: {
),
'Report for multiple queries (rows method)'
);
}
ok(
no_diff(
@@ -108,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");
@@ -120,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",
),
@@ -134,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",
),
@@ -155,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");
@@ -185,7 +174,6 @@ SKIP: {
qr/[`"]SUM\(total\)[`"]\s+double\sDEFAULT/i,
"No M,D in table def (bug 926598)"
);
}
# #############################################################################
# SELECT FUNC(), so there are no tables.

View File

@@ -15,13 +15,6 @@ use PerconaTest;
use Sandbox;
require "$trunk/bin/pt-upgrade";
# This test calls pt-upgrade with --compare-results-method rows
# which use LOAD DATA LOCAL INFILE. If LOAD DATA is disabled,
# then this this test can't run.
if ( !$can_load_data ) {
plan skip_all => 'LOAD DATA LOCAL INFILE is disabled';
}
# This runs immediately if the server is already running, else it starts it.
diag(`$trunk/sandbox/start-sandbox master 12348 >/dev/null`);
@@ -43,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 {