CC: | tyemq [...] cpan.org |
Subject: | method chaining fails where separate method calls succeed |
The basic problem is that the DBIx::Simple object [returned from dbs()]
gets destroyed after the DBIx::Simple::Statement object is created [and
returned by query()] but before it can be used.
The supplied test case, authored by Terrence Brannon, and refined by Tye
McQueen, illustrates the problem precisely.
Subject: | tye.pl |
# use Devel::SimpleTrace;
{
package Util;
sub dbconnect {
use DBI;
DBI->connect('dbi:SQLite:temp.db');
}
}
{
package Local::DBIx::Simple::Q;
use Moo;
has 'q' => ( is => 'rw', default => sub { $main::backgroundqueue } );
has 'standard' => ( is => 'rw', default => sub { 0 } );
use Data::Dumper;
sub BUILD {
my ($self) = @_;
$main::globalstandardconnection = $self->standard
}
sub enq {
my ( $self, @arg ) = @_;
warn sprintf "Enqueing with id %d this data: %s", $self->enq_id,
Dumper( \@arg );
$self->q->enqueue( [ $self->enq_id, @arg ] );
}
}
{
package Local::DBIx::Simple;
use Moo;
extends qw(Local::DBIx::Simple::Q);
use DBIx::Simple;
has 'enq_id' => ( is => 'rw', default => sub { 5 } );
has 'deq_id' => ( is => 'rw', default => sub { 6 } );
sub dbh {
Util::dbconnect;
}
sub dbs {
my ($self) = @_;
my $dbs = DBIx::Simple->connect( $self->dbh );
}
}
{
package main;
use strict;
use warnings;
use Data::Dumper;
use Test::More;
use lib 'lib';
sub constructor {
Local::DBIx::Simple->new( standard => 0 );
}
sub create_database {
my ($dbh) = @_;
my $ddl = <<'EODDL';
create table table_one (
col1 integer not null primary key,
col2 TEXT
)
EODDL
$dbh->do($ddl);
}
sub main {
my $dbh = Util::dbconnect;
create_database($dbh);
my $Q = "SELECT * FROM table_one";
my $desired_class = 'DBIx::Simple::Statement';
my $desired_desc = "object isa $desired_class";
warn "Starting CASE 1";
{ # CASE 1 - successful
my $s = constructor;
my $dbs = DBIx::Simple->connect( $s->dbh );
my $r = $dbs->query($Q);
warn sprintf 'Result of DBIx::Simple query: %s', Dumper($r);
my $h = $r->hashes;
warn sprintf 'Hashes? %s', Dumper($h);
ok( $r->{st}->isa($desired_class), $desired_desc );
}
warn "Starting CASE 2";
{ # CASE 2 - successful
my $s = constructor;
my $dbs = $s->dbs;
my $r = $dbs->query($Q);
warn sprintf 'Result of DBIx::Simple-from-Local query: %s',
Dumper($r);
my $h = $r->hashes;
warn sprintf 'Hashes? %s', Dumper($h);
ok( $r->{st}->isa($desired_class), $desired_desc );
}
warn "Starting CASE 3";
{ # CASE 3 - *FAILS* when $self is quoted on line 165
my $s = constructor;
my $r = $s->dbs->query($Q);
ok( $r->{st}->isa($desired_class), $desired_desc );
}
warn "Starting CASE 4";
{ # CASE 4 - also fails
my $s = constructor;
my $r;
{
my $dbs = $s->dbs;
$r = $dbs->query($Q);
warn sprintf 'Result of DBIx::Simple-from-Local query: %s',
Dumper($r);
}
my $h = $r->hashes;
warn sprintf 'Hashes? %s', Dumper($h);
ok( $r->{st}->isa($desired_class), $desired_desc );
}
}
}
main() unless caller;
1;