Subject: | PATCH: support DBD::Pg, which returns a non-standard "{Name}" value. |
As recently reported on the DBD::Pg list, there is a conflict with this
driver and DBIx::HA, because an unexpected value for {Name} is returned.
I think the best long term solution is for DBD::Pg to change the value
it returns.
However, in the short term it is useful to have DBIx::HA work with the
current, released version of DBD::Pg, so I am providing this patch to
address the issue.
It adds a new subroutine which would also house exceptions for other
drivers with the same issue.
A second patch is provided, which simply cleans up a block of code a
little, without functional changes.
Mark
Subject: | clarity.patch |
Mon Jan 22 11:09:59 EST 2007 mark@summersault.com
* code-clean up: give $_ and $_->[0] names for clarity
diff -rN -u old-DBIx-HA-0.99/lib/DBIx/HA.pm new-DBIx-HA-0.99/lib/DBIx/HA.pm
--- old-DBIx-HA-0.99/lib/DBIx/HA.pm 2007-01-22 13:00:09.000000000 -0500
+++ new-DBIx-HA-0.99/lib/DBIx/HA.pm 2007-01-22 13:00:09.000000000 -0500
@@ -71,9 +71,10 @@
$DATABASE::conf{$dbname}->{'failtest_function'} = sub { 0 };
}
$DATABASE::conf{$dbname}->{'end_of_stack'} = 0; # error condition reaching end of stack
- foreach (@{$DATABASE::conf{$dbname}->{'db_stack'}}) {
+ for my $conn_aref (@{$DATABASE::conf{$dbname}->{'db_stack'}}) {
+ my $dsn = $conn_aref->[0];
# create an easy reverse-lookup table for finding the db server name from the dsn
- $DBIx::HA::finddbserver{$_->[0]} = $dbname;
+ $DBIx::HA::finddbserver{$dsn} = $dbname;
# add timeout when within Apache::DBI
# default to no ping (-1)
if ($loaded_Apache_DBI) {
@@ -81,8 +82,8 @@
die "$prefix Requirement unmet. Apache::DBI must be at version 0.89 or above";
}
# create a cached lookup table for finding the Apache::DBI cache key index from the dsn
- $DBIx::HA::ApacheDBIidx{$_->[0]} = _getApacheDBIidx(@$_);
- Apache::DBI->setPingTimeOut($_->[0], $DATABASE::conf{$dbname}->{'pingtimeout'} || -1);
+ $DBIx::HA::ApacheDBIidx{$dsn} = _getApacheDBIidx(@$conn_aref);
+ Apache::DBI->setPingTimeOut($dsn, $DATABASE::conf{$dbname}->{'pingtimeout'} || -1);
}
};
# set the active database to be the first in the stack
Subject: | translate_dsn.patch |
Mon Jan 22 12:51:02 EST 2007 mark@summersault.com
* add _translate_dsn to support DBD::Drivers which don't return the expected value for $dbh->{Name}
Initial exceptions for DBD::Pg are provided.
diff -rN -u old-DBIx-HA-0.99/lib/DBIx/HA.pm new-DBIx-HA-0.99/lib/DBIx/HA.pm
--- old-DBIx-HA-0.99/lib/DBIx/HA.pm 2007-01-22 12:56:55.000000000 -0500
+++ new-DBIx-HA-0.99/lib/DBIx/HA.pm 2007-01-22 12:56:55.000000000 -0500
@@ -73,8 +73,12 @@
$DATABASE::conf{$dbname}->{'end_of_stack'} = 0; # error condition reaching end of stack
for my $conn_aref (@{$DATABASE::conf{$dbname}->{'db_stack'}}) {
my $dsn = $conn_aref->[0];
- # create an easy reverse-lookup table for finding the db server name from the dsn
- $DBIx::HA::finddbserver{$dsn} = $dbname;
+
+ my $translated_dsn = _translate_dsn($dsn);
+
+ # create an easy reverse-lookup table for finding the db server name from the dsn
+ $DBIx::HA::finddbserver{$translated_dsn} = $dbname;
+
# add timeout when within Apache::DBI
# default to no ping (-1)
if ($loaded_Apache_DBI) {
@@ -98,6 +102,40 @@
};
}
+
+
+# Work around PostgreSQL returning non-standard value for "Name"
+# When this is fixed in DBD::Pg, we can remove this hack, and require
+# the fixed version of DBD::Pg.
+# To get this exactly right, the matching code was lifted from DBD::Pg
+sub _translate_dsn {
+ my $dsn = shift;
+
+ if ($dsn =~ m/^dbi:Pg/) {
+ # Allow "db" and "database" as synonyms for "dbname"
+ $dsn =~ s/\b(?:db|database)\s*=/dbname=/;
+
+ my $pg_name = $dsn;
+ if ($dsn =~ m#dbname\s*=\s*[\"\']([^\"\']+)#) {
+ $pg_name = "'$1'";
+ $dsn =~ s/"/'/g;
+ return "dbi:Pg:$pg_name";
+ }
+ elsif ($pg_name =~ m#dbname\s*=\s*([^;]+)#) {
+ $pg_name = $1;
+ return "dbi:Pg:$pg_name";
+ }
+ # It's already been translated, apparently.
+ else {
+ return $dsn;
+ }
+ }
+ else {
+ return $dsn;
+ }
+}
+
+
sub _init_child {
# Set up debugging PID for children
$DBIx::HA::prefix = "[$$] DBIx::HA: ";
@@ -185,8 +223,9 @@
sub _getdbname {
# returns the db server name when given the dsn string
my $dsn = shift;
- warn "$prefix in _getdbname: $DBIx::HA::finddbserver{$dsn} \n" if (DBIx_HA_DEBUG > 2);
- return $DBIx::HA::finddbserver{$dsn};
+ my $translated_dsn = _translate_dsn($dsn);
+ warn "$prefix in _getdbname: $translated_dsn returns $DBIx::HA::finddbserver{$translated_dsn} \n" if (DBIx_HA_DEBUG > 2);
+ return $DBIx::HA::finddbserver{$translated_dsn};
}
sub _isactivedb {
@@ -198,7 +237,7 @@
# we're not in the active db, because there is no active database, the end of stack is reached.
return 0;
}
- if ($dsn eq $DATABASE::conf{$dbname}->{'active_db'}->[0]) {
+ if ($dsn eq _translate_dsn($DATABASE::conf{$dbname}->{'active_db'}->[0])) {
warn "$prefix in _isactivedb: ".$dsn." is the active one \n" if (DBIx_HA_DEBUG > 2);
return 1;
}
@@ -217,9 +256,10 @@
my $foundmatch = 0;
my $idxnextdb = 0;
my $stackcount = scalar(@{$DATABASE::conf{$dbname}->{'db_stack'}});
- foreach (@{$DATABASE::conf{$dbname}->{'db_stack'}}) {
+ for my $row (@{$DATABASE::conf{$dbname}->{'db_stack'}}) {
+ my $row_dsn = $_->[0];
$idxnextdb++;
- if ($dsn eq $_->[0]) {
+ if ($dsn eq _translate_dsn($row_dsn)) {
# we got to the current db server in the stack
# next db server in the stack is the correct one
$foundmatch = 1;