I'm writing some code which, amongst other things, utilities MySQL server-side prepare statements to ensure the validity of chunks of SQL. However, I have to wrap the prepare in an eval because it dies when it encounters bad SQL:
eval { $dbh->prepare( $statement, { mysql_server_prepare => 1 } ) }; if ( my $error = $@ ) { ... }
Well, that seems pretty reasonable, except for one tiny problem. I trap the exception, but it still gets sent to STDERR unless I do this:
eval { local $SIG{__WARN__} = sub {}; $dbh->prepare( $statement, { mysql_server_prepare => 1 } ) }; if ( my $error = $@ ) { ... }
Why the heck do I need to do that? Am I have a total brain-cramp and missing something obvious here? A complete example of how I'm doing this is below, though I think all of the relevant bits are above.
use DBI; use DBD::mysql 3.0002_1; # so we have have server-side prepares use Data::Record; use Regexp::Common; my $dbh = DBI->connect( "DBI:mysql:$database:$server", $user, $pass, { AutoCommit => 0, RaiseError => 1, } ); my $sql = <<'END_SQL'; SELECT 1; ALTER TABLET foo; END_SQL use Data::Dumper; my @errors = invalid_sql($dbh, $sql); print Dumper(\@errors); sub invalid_sql { my ( $dbh, $sql ) = @_; my @errors; foreach my $statement ( split_sql($sql) ) { next unless $statement =~ /\S/; local $SIG{__WARN__} = sub {}; # XXX Why do I need this? eval { $dbh->prepare( $statement, { mysql_server_prepare => 1 +} ) }; if ( my $error = $@ ) { push @errors => [ $statement => $error ]; } } return wantarray ? @errors : \@errors; } sub split_sql { my $sql = shift; my $record = Data::Record->new( { split => ';', unless => $RE{quoted}, } ); return $record->records($sql); }
Cheers,
Ovid
New address of my CGI Course.
In reply to DBD::mysql warns *and* dies? by Ovid
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |