Error handling with Mojo::SQLite

61 views
Skip to first unread message

Luc Larochelle

unread,
Mar 15, 2019, 4:22:11 PM3/15/19
to Mojolicious
Hello everyone,

While a 'select' statement can be double checked by the presence of the returned data, how can I confirm that statements such as 'insert' , 'update' or 'delete' are successful ?

For instance, using SQL::Abstract and some helpers

helper insertOne => sub {
my ($c,$table) = @_;
$c->sqlite->db->insert($table, $c->element);
};



I've seen in the documentation that one could eval and look into $@ , but is there a more "inline" way to do this ?

Cheers !

Luc

Veesh Goldman

unread,
Mar 16, 2019, 3:12:11 PM3/16/19
to mojol...@googlegroups.com
Does Try::Tiny strike your fancy? It'll put the error into $_ in the catch block.

Short of that, I'm fairly certain it'll crash your thread if it fails.

--
You received this message because you are subscribed to the Google Groups "Mojolicious" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mojolicious...@googlegroups.com.
To post to this group, send email to mojol...@googlegroups.com.
Visit this group at https://groups.google.com/group/mojolicious.
For more options, visit https://groups.google.com/d/optout.

Luc Larochelle

unread,
Mar 18, 2019, 10:00:15 AM3/18/19
to Mojolicious
Hello Veesh, well to me that looks like "eval" , right ? I meant is there a way with Mojo::SQLite to check errors ?

Dan Book

unread,
Mar 18, 2019, 12:35:48 PM3/18/19
to mojol...@googlegroups.com
As mentioned in the documentation: "Any database errors will throw an exception as RaiseError is automatically enabled, so use eval or Try::Tiny to catch them. "

This is the standard way to handle errors in Perl. Syntax::Keyword::Try is also a nicer interface if you can use keyword plugins (perl 5.14+).

-Dan

Dan Book

unread,
Mar 18, 2019, 12:36:56 PM3/18/19
to mojol...@googlegroups.com
Also note that *not* catching the error and allowing it to render an exception page and log the error message is often exactly what you want.

-Dan

Luc Larochelle

unread,
Mar 20, 2019, 11:58:04 AM3/20/19
to Mojolicious
Thanks ! Maybe I read only the sections and bold titles :)

I'll have a second look.

Luc Larochelle

unread,
May 8, 2019, 1:18:20 PM5/8/19
to Mojolicious
This works just as expected. In my case I wanted to catch foreign key constraints. Now I'm prepared for the critics, I'll post my "del" route, it's from an Lite application serving a web app. I wonder if I'm doing things the right way.

I tried to make it idempotent for GET, POST, PUT & DEL but since I have to deal with little exceptions in the given routes, they all have their definitions. For instance, :id is *id in the GET route, since its principal task is to display the whole table. The helpers though (model ?) are not dealing with exceptions at all and are used to execute simple tasks to the db given the params feeded by the routes.

I'm very opened to discuss all of this, this has to be my most serious project since I started using Mojolicious and I'm learning frontend coding on-the-fly ... 

helper insertOne => sub {
my ($c,$table) = @_;
$c->sqlite->db->insert($table, $c->element);
};


helper deleteOne => sub {

my ($c,$table,$param) = @_;
$c->sqlite->db->delete($table, {$tables->{$table} => $param});
};



del '/api/select/:table/:id' => sub {

my $c = shift;
if ($c->selectOne($c->param('id'))) {
eval { $c->deleteOne($c->param('table'),$c->param('id')) };
unless($@) {
$c->render(status => 200, json => {message => $c->param('id') . $messages->{'Del'}});
} elsif ($@ =~ /FOREIGN KEY constraint failed/) {
$c->render(status => 400, json => {message => $c->param('id') . $messages->{'FK'}});
}
} else { 
$c->render(status => 404, json => {message => "Not found"});
}

};

Dan Book

unread,
May 8, 2019, 2:10:51 PM5/8/19
to mojol...@googlegroups.com
Testing $@ is not the best way to determine an exception occurred. I'd recommend Syntax::Keyword::Try as it handles all the edge cases for you, but otherwise this gets you most of the way:

if (eval { ...; 1 }) {
  # success
} else {
  my $err = $@;
}

And make sure you log errors and rethrow any exceptions you do not handle. You will want to see the error logging later.

-Dan

Luc Larochelle

unread,
May 9, 2019, 9:49:24 AM5/9/19
to Mojolicious
Hi Dan, 

What does the " 1 " stands for in the line : if (eval { ...; 1 }) { ? 

I've never used that kind of notation before. I think it could be some sort of default true ?


To unsubscribe from this group and stop receiving emails from it, send an email to mojol...@googlegroups.com.

Dan Book

unread,
May 9, 2019, 10:11:40 AM5/9/19
to mojol...@googlegroups.com
It is so the eval returns true if it succeeds. If an exception is thrown, eval always returns undef. Thus by this difference you can determine without fail whether an exception occurred.

-Dan

Luc Larochelle

unread,
May 9, 2019, 1:35:12 PM5/9/19
to Mojolicious
Fantastic. Thank you again
Reply all
Reply to author
Forward
0 new messages