Subject: | ::Storage::DBI modifies the options hash of connect_info |
Suppose you have the following code:
$config->{'connect_info'} = [
'dbi:mysql:foo',
'bar',
'baz',
{ quote_char => '`', name_sep => '.' }
];
$schema1 = MyApp::Schema->connect( @{$config->{'connect_info'}} );
$schema2 = MyApp::Schema->connect( @{$config->{'connect_info'}} );
Operations through $schema1 will use the quote_char/name_sep, but
operations through $schema2 will not. After hunting it down, I located
the problem in ::Storage::DBI, inside "connect_info":
if($info_arg) {
# Kill sql_maker/_sql_maker_opts, so we get a fresh one with only
# the new set of options
$self->_sql_maker(undef);
$self->_sql_maker_opts({});
my $info = [ @$info_arg ]; # copy because we can alter it
my $last_info = $info->[-1];
if(ref $last_info eq 'HASH') {
if(my $on_connect_do = delete $last_info->{on_connect_do}) {
$self->on_connect_do($on_connect_do);
}
for my $sql_maker_opt (qw/limit_dialect quote_char name_sep/) {
if(my $opt_val = delete $last_info->{$sql_maker_opt}) {
$self->_sql_maker_opts->{$sql_maker_opt} = $opt_val;
}
}
As the comment says, it copies $info_arg. But it only makes a shallow
copy. So when it later deletes from the options hash, it modifies the
original hash, not a copy.
I suggest a fix of either:
my $info = dclone( $info_arg ); # copy because we can alter it
or (not as correct):
my $last_info = $info->[-1];
if(ref $last_info eq 'HASH') {
$last_info = { %$last_info };
Versions:
::Storage::DBI - 0.07006
perl - v5.8.8 built for i586-linux-thread-multi
OpenSUSE 10.2 - kernel 2.6.18.8-0.3-default #1 SMP