2020/12/25

謎の Can't set DBI::db=HASH(0x561364021040)->{CachedKids}: unrecognised attribute name or invalid value at DBI.pm line 734.

[perl] [DBI]

謎のwarnに悩まされている。

Can't set DBI::db=HASH(0x561364021040)->{CachedKids}: unrecognised attribute name or invalid value at x86_64-linux/DBI.pm line 734.

unrecognised attribute name or invalid value ですとよ。

CachedKids を設定しているつもりはない。

ソースを参照してみましょう。DBI 1.643

722         if (%$apply) {
723
724             if ($apply->{DbTypeSubclass}) {
725                 my $DbTypeSubclass = delete $apply->{DbTypeSubclass};
726                 DBI::_rebless_dbtype_subclass($dbh, $rebless_class||$class, $DbTypeSubclass);
727             }
728             my $a;
729             foreach $a (qw(Profile RaiseError PrintError AutoCommit)) { # do these first
730                 next unless  exists $apply->{$a};
731                 $dbh->{$a} = delete $apply->{$a};
732             }
733             while ( my ($a, $v) = each %$apply) {
734                 eval { $dbh->{$a} = $v }; # assign in void context to avoid re-FETCH
735                 warn $@ if $@;
736             }
737         }

さらにピンポイントで抜き出すと、以下の 734 行目ですね。

733             while ( my ($a, $v) = each %$apply) {
734                 eval { $dbh->{$a} = $v }; # assign in void context to avoid re-FETCH
735                 warn $@ if $@;
736             }

eval でエラーがキャッチされて、warn されていると。

エラーとしては

Can't set DBI::db=HASH(0x561364021040)->{CachedKids}

なので、 CachedKids に値がセットできないということか。

ダンプしてみます。

733             while ( my ($a, $v) = each %$apply) {
734                 use Data::Dumper;
735                 warn Dumper($v) if $a eq 'CachedKids';
736                 eval { $dbh->{$a} = $v }; # assign in void context to avoid re-FETCH
737                 warn $@ if $@;
738             }

undef になっています。

$VAR1 = undef;

CacheKids attributeの説明は以下のようにあります。

CachedKids

Type: hash ref

For a database handle, CachedKids returns a reference to the cache (hash) of statement handles created by the "prepare_cached" method. For a driver handle, returns a reference to the cache (hash) of database handles created by the "connect_cached" method.

hash ref じゃないとだめなのに undef を突っ込もうとしてエラーになっている様子。

元になっている %$apply はどこからきているのでしょうか。

my $apply = { ($override_attr) ? (%$attr, %$override_attr ) : %$attr };

上のように定義されています。

ちなみにこの一連のコードは $connect_closure にコードリファレンスとして定義されるルーチンの中に入っています。

$apply に入る値をダンプするコードはソースにコメントアウトされた形で書かれているので、コメントアウトを解除して中身をみてみましょう。

672     my $connect_closure = sub {
673         my ($old_dbh, $override_attr) = @_;
674
675         use Data::Dumper;
676         warn "connect_closure: ".Data::Dumper::Dumper([$attr,\%attributes, $override_attr]);
677
678         my $dbh;

$override_attr に undef になっている CachedKids が存在します。エラーの通り確かに undef なんですね。

ただ、 このあたりのコード を見ると、undef であること自体は問題なさそうです。

my $cache = $drh->{CachedKids} ||= {};

というわけでつまり、undefならスキップすればよさそう?

733             while ( my ($a, $v) = each %$apply) {
734                 next if $a eq 'CachedKids' && !defined $v;
735                 eval { $dbh->{$a} = $v }; # assign in void context to avoid re-FETCH
736                 warn $@ if $@;
737             }

メリークリスマス!

サイト内検索