DSNParser.pm: Work around MySQL not resolving encodings sanely.

For some reason, MySQL won't resolve iso-8859-1 or latin-1 as latin1,
and will die if you try to use through in, e.g., SET NAMES.
This commit makes DSNParser resolve those cases on its own
before calling SET NAMES.
This commit is contained in:
Brian Fraser
2012-07-23 01:11:49 -03:00
parent 02c6421a25
commit 61a65fcdbd
3 changed files with 52 additions and 26 deletions

View File

@@ -2121,6 +2121,12 @@ sub fill_in_dsn {
$dsn->{D} ||= $db;
}
my %encoding_aliases = (
'utf-8' => 'utf8',
'iso-8859-1' => 'latin1',
'latin-1' => 'latin1',
);
sub get_dbh {
my ( $self, $cxn_string, $user, $pass, $opts ) = @_;
$opts ||= {};
@@ -2129,7 +2135,7 @@ sub get_dbh {
RaiseError => 1,
PrintError => 0,
ShowErrorStatement => 1,
mysql_enable_utf8 => ($cxn_string =~ m/charset=utf8/i ? 1 : 0),
mysql_enable_utf8 => ($cxn_string =~ m/charset=utf-?8/i ? 1 : 0),
};
@{$defaults}{ keys %$opts } = values %$opts;
@@ -2182,7 +2188,7 @@ sub get_dbh {
PTDEBUG && _d($dbh, $sql);
my ($sql_mode) = eval { $dbh->selectrow_array($sql) };
if ( $EVAL_ERROR ) {
die $EVAL_ERROR;
die "Error getting the current SQL_MODE: $EVAL_ERROR";
}
$sql = 'SET @@SQL_QUOTE_SHOW_CREATE = 1'
@@ -2192,15 +2198,18 @@ sub get_dbh {
PTDEBUG && _d($dbh, $sql);
eval { $dbh->do($sql) };
if ( $EVAL_ERROR ) {
die $EVAL_ERROR;
die "Error setting SQL_QUOTE_SHOW_CREATE, SQL_MODE"
. ($sql_mode ? " and $sql_mode" : '')
. ": $EVAL_ERROR";
}
if ( my ($charset) = $cxn_string =~ m/charset=(\w+)/ ) {
$sql = "/*!40101 SET NAMES $charset*/";
if ( my ($charset) = $cxn_string =~ m/charset=([-\w]+)/ ) {
$charset = $encoding_aliases{lc($charset)} || $charset;
$sql = qq{/*!40101 SET NAMES "$charset"*/};
PTDEBUG && _d($dbh, ':', $sql);
eval { $dbh->do($sql) };
if ( $EVAL_ERROR ) {
die $EVAL_ERROR;
die "Error setting NAMES to $charset: $EVAL_ERROR";
}
PTDEBUG && _d('Enabling charset for STDOUT');
if ( $charset eq 'utf8' ) {
@@ -2212,12 +2221,12 @@ sub get_dbh {
}
}
if ( $self->prop('set-vars') ) {
$sql = "SET " . $self->prop('set-vars');
if ( my $var = $self->prop('set-vars') ) {
$sql = "SET $var";
PTDEBUG && _d($dbh, ':', $sql);
eval { $dbh->do($sql) };
if ( $EVAL_ERROR ) {
die $EVAL_ERROR;
die "Error setting $var: $EVAL_ERROR";
}
}
}