Search code examples
perldbidbix-class

How to access database data when exception occur?


I have next code:

my $savepoint =  $c->db->txn_scope_guard;
return $self->render( 'subnet/create',  error => [ create => $@ ],
    servers =>  $self->rows( 'Server' )->lookup,
) unless $subnet =  eval{ $self->rows( 'Subnet' )->create( $subnet ) };
$savepoint->commit;

Here rows is Mojolicious helper which provides access to data.

sub model {
    my( $c, $table_name ) =  (shift,shift);

    return $c->db->resultset( $table_name );
}

And ->db is also helper:

sub db { return $schema
    //=  DBIx::Class::Schema->connect( $DB->{ DSN },  @$DB{ qw/ USER PASS / },  {
        AutoCommit => 1,
        RaiseError => 1,
        quote_char => '"',
    })
});

When I create $subnet and unique constraint occurs (here has no matter which constraint occur, actually in case of any exception) I got the error:

DBIx::Class::Storage::DBI::_dbh_execute(): DBI Exception: DBD::Pg::st execute failed: ERROR:  current transaction is aborted, commands ignored until end of transaction block [for Statement "SELECT "me"."id", "me"."hostname" FROM "servers" "me" ORDER BY hostname"] at ...

This is when I catch exception with eval{ ... } the current transaction is aborted and I can not do $self->rows( 'Server' )->lookup

Is there a way to access server data after exception occur?


Solution

  • Seems I found the answer, because read error message more carefully:

    ... commands ignored until end of transaction block

    So I force the end for transaction block when exception occur:

    $c->db->txn_rollback;
    

    The code:

    my $savepoint =  $c->db->txn_scope_guard;
    unless( $subnet =  eval{ $self->rows( 'Subnet' )->create( $subnet ) } ) {
        my $e = $@; # $@ may be changed before `create => $@`
        undef $savepoint; # Or the same: $c->db->txn_rollback;     
        return $self->render( 'subnet/create',  error => [ create => $e ],
            servers =>  $self->rows( 'Server' )->lookup,
        );
    }
    $savepoint->commit;