Question

Cette question se réfère au commentaire de Ikegami:

[...] But if you're going to put an eval around every statement, just use RaiseError => 0. [...]

dans ce fil.

Que dois-je prendre, si je l'ai mis RaiseError pour 0 dans de telles situations?

#!/usr/bin/env perl
use warnings;
use 5.10.1;
use DBI;

my $db = 'my_test_sqlite_db.sqlite';
open my $fh, '>', $db or die $!;
close $fh or die $!;

my ( $dbh, $sth );
eval {
    $dbh = DBI->connect( "DBI:SQLite:dbname=$db", "", "", {} );
};
if ( $@ ) { print $@ };

my $table = 'my_sqlite_table';

say   "RaiseError = 1";
say   "PrintError = 0";
$dbh->{RaiseError} = 1;
$dbh->{PrintError} = 0;
eval {
    $sth = $dbh->prepare( "SELECT * FROM $table" );
    $sth->execute();
};
if ( $@ ) { print "ERROR: $@" };

say "\nRaiseError = 0";
say   "PrintError = 1";
$dbh->{RaiseError} = 0;
$dbh->{PrintError} = 1;
eval {
    $sth = $dbh->prepare( "SELECT * FROM $table" );
    $sth->execute();
};
if ( $@ ) { print "ERROR: $@" };

say "\nRaiseError = 0";
say   "PrintError = 0";
$dbh->{RaiseError} = 0;
$dbh->{PrintError} = 0;
eval {
    $sth = $dbh->prepare( "SELECT * FROM $table" );
    $sth->execute();
};
if ( $@ ) { print "ERROR: $@" };

Sortie:

RaiseError = 1
PrintError = 0
ERROR: DBD::SQLite::db prepare failed: no such table: my_sqlite_table at ./perl2.pl line 23.

RaiseError = 0
PrintError = 1
DBD::SQLite::db prepare failed: no such table: my_sqlite_table at ./perl2.pl line 33.
ERROR: Can't call method "execute" on an undefined value at ./perl2.pl line 34.

RaiseError = 0
PrintError = 0
ERROR: Can't call method "execute" on an undefined value at ./perl2.pl line 44.
Était-ce utile?

La solution

En cas d'échec, pour certaines raisons, la plupart des $dbh méthodes, soit:

  • (si RaiseError l'option est définie sur 0) de retour undef
  • (si RaiseError l'option est définie sur 1) immédiatement à la sortie du script ("mourir") avec l'erreur explique message de sortie.

Le point clé ici est que c'est à vous de décider comment traiter les erreurs.Si vous le souhaitez, vous pouvez les ignorer, par exemple (ce qui suit ne sera évidemment le travail avec RaiseError mis à 0 uniquement):

for my $db ( ... ) {
    my $dbh = get_database_handle( $db )
       or next;
    ...
}

Dans cet extrait de code (copié à partir de @ikegami de la réponse que vous avez mentionné dans votre question) vous boucle par le biais de certains de la liste de paramètres pour la connexion DB;si certains de connexion vous donne un undef, vous allez juste pour un autre, et de ne rien faire avec l'erreur.

Habituellement, cependant, que vous devez faire plus que simplement "nexting' quand l'erreur se produit - mais là encore, vous avez deux choix:vérifier chaque $dbh-déclaration avec quelque chose comme ceci:

$sth = $dbh->prepare('some_params') 
  or process_db_error('In prepare');
...
$res = $sth->execute('another_set_of_params') 
  or process_db_error('In execute');
...
$res->doAnythingElse('something completely different') 
  or process_db_error('In something completely different');

(comme or les pièces seront exécutées que si leur correspondant 'gauche des parties à évaluer false dans le contexte Booléen).

...ou juste envelopper tout cela dans Perlish 'try-catch" en bloc:

if (!eval {    
   $sth = $dbh->prepare('some_params');
   ...
   $res = $sth->execute('another_set_of_params');
   ...
   $res->doSomethingElse('something completely different') 
   ...
   1  # No exception
}) {
   process_db_error($@);
}

Ce qui est de choisir, c'est à vous:c'est une décision commune entre les "erreurs dans les instructions return' (sauf que pour aller chercher une erreur réelle que vous avez à demander $dbh objet) et, ainsi, les exceptions.

Mais la ligne de fond est que vous ne pouvez pas écrire ceci:

$sth = $dbh->do_something('that_can_result_in_error');
$sth->do_something('else');

...si vous n'avez définie RaiseError pour 0.Dans ce cas, le script ne meurent pas, $sth sera attribué un undef, et vous obtenez un 'dérivé' erreur (que vous ne pouvez pas appeler une méthode sur undef).

Et c'est exactement ce qui s'est passé dans la dernière partie de code dans votre question initiale.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top