Error handling on DBI->connect - perl

Besides handling error using standard code die "Unable to connect: $DBI::errstr\n" is it possible to write a custom code like below?
Standard:
$dbstore = DBI->connect($dsn, $user, $pw,
{ora_session_mode => $mode, PrintError => 0, RaiseError => 0, AutoCommit => 0})
or die "Unable to connect: $DBI::errstr\n";
Custom:
$dbstore = DBI->connect($dsn, $user, $pw,
{ora_session_mode => $mode, PrintError => 0, RaiseError => 0, AutoCommit => 0});
if (!$dbstore)
{
CUSTOM_LOG_HANDLER("Could not connect to database: $DBI::errstr");
return;
}
Sample Standard Code:
#!/usr/bin/perl
# PERL MODULES WE WILL BE USING
use DBI;
use DBD::mysql;
# HTTP HEADER
print "Content-type: text/html \n\n";
# CONFIG VARIABLES
$platform = "mysql";
$database = "store";
$host = "localhost";
$port = "3306";
$tablename = "inventory";
$user = "username";
$pw = "password";
#DATA SOURCE NAME
$dsn = "dbi:mysql:$database:localhost:3306";
# PERL DBI CONNECT (RENAMED HANDLE)
$dbstore = DBI->connect($dsn, $user, $pw) or die "Unable to connect: $DBI::errstr\n";
Thanks for you time.

You can always use a custom error handler with the DBI:
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
sub handle_error {
my $message = shift;
#write error message wherever you want
print "the message is '$message'\n";
exit; #stop the program
}
my $dbh = DBI->connect(
"dbi:SQLite:foo",
"user",
"pass",
{
PrintError => 0,
HandleError => \&handle_error,
}
) or handle_error(DBI->errstr);
my $sth = $dbh->prepare("select * from doesntexist");
That said, you should be logging errors, and for a web application, the web server's logs makes sense. If you are worried about the amount of noise in your web logs, you should concentrate on fixing the errors, not making the logs less noisy by removing sources of information.

Related

Sqlite connection string in perl

I am using below sqlite connection string in perl to connect sqlite database and getting following below error
Can't set DBI::db=HASH(0x2c34194)->{PRAGMA journal_mode}: unrecognised attribute name or invalid value
my $driver = "SQLite";
my $database = "C:\\Sample\\Sample_Sqlite\\Activities.db3;PRAGMA journal_mode=WAL;";
my $dsn = "DBI:$driver:dbname=$database";
print $dsn;
my $dbh = DBI->connect(
$dsn,
{ RaiseError => 1 },
) or die $DBI::errstr;
Reading the section on PRAGMA in the DBD::SQLite documentation, it looks like you're setting the PRAGMA at the wrong time. It shouldn't be part of the connection string, but an SQL command that is run once you have connected.
my $driver = "SQLite";
my $database = "C:\\Sample\\Sample_Sqlite\\Activities.db3";
my $dsn = "DBI:$driver:dbname=$database";
print $dsn;
my $dbh = DBI->connect(
$dsn,
{ RaiseError => 1 },
) or die $DBI::errstr;
$dbh->do('PRAGMA journal_mode=WAL');
Update: It's probably also worth noting that the journal_mode setting is persistent. So you only need to set it once, and then you can drop it completely from your connection code.

error in establishing DB connection in Perl script?

I am using perl 5.24. I am trying to learn Perl.
I had written a simple Perl code to connect to a DB. But gives error stating
DBI connect('database=vms','DBA',...) failed: (no error string) at simpleperl.pl line 13.
The code is
#!/usr/bin/perl
use DBI;
use DBD::SQLAnywhere;
my $driver = "SQLAnywhere";
my $database = "vms";
my $dsn = "DBI:$driver:database=$database";
my $userid = "DBA";
my $password = "admin";
my $dbh = DBI->connect($dsn, $userid, $password,{RaiseError => 1}) or die ("died connection:$DBI::errstr");
if($dbh)
{
print "Connection Established";
}
Can anyone point out what might be the problem here?
Note the following in DBD::SQLAnywhere documentation:
$dbh = DBI->connect( 'dbi:SQLAnywhere:ENG=demo', $userid, $passwd );
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
my $driver = "SQLAnywhere";
my $database = "vms";
my $dsn = "DBI:$driver:ENG=$database";
my $userid = "DBA";
my $password = "admin";
my $dbh = DBI->connect($dsn, $userid, $password, {RaiseError => 1});
print "Connection established\n";
$dbh->disconnect;
Note also the following:
Always use strict and warnings.
You do not need use DBD::SQLAnywhere;. DBI will pick the driver based on what you specify in the connection string.
You specified {RaiseError => 1} in your connection options. That means, there is no need for the or die. DBI will croak if connect fails.
You probably want AutoCommit => 0 to go with that RaiseError => 1.
There is no need for the if ($dbh) following the connection attempt. You won't get there unless connect succeeded.
Given that fixing the connection string did not solve the problem and I do not have an instance of a SQLAnywhere database to test things, I am going to recommend you add:
DBI->trace( 5 );
before the connect call, and update your question with the trace information. See also TRACING.

Return object handle from a subroutine

I want to know if it is possible to return a object handle from a subroutine in a Perl program.
I will use a specific example from a program that uses MAIL::IMAPClient
Create client object handle
my $client = Mail::IMAPClient->new(
Socket => $socket,
User => $user,
Password => $pass,
)
or die "new(): $#";
I would like to create this object handle from a sub routine instead
my $client = &create_client_object;
sub create_client_object {
my $client = Mail::IMAPClient->new(
Socket => $socket,
User => $user,
Password => $pass,
)
or die "new(): $#";
return $client;
}
If possible, what is the proper way to do this?
Yes, that works perfectly. Besides #Miller's comment, I'd recommend you to also pass the $socket, $user and $pass as parameters to your function instead of using them from context:
my $client = create_client_object($socket, $user, $pass);
sub create_client_object {
my ($socket, $user, $pass) = #_;
my $client = Mail::IMAPClient->new(
Socket => $socket,
User => $user,
Password => $pass,
)
or die "new(): $#";
return $client;
}

can't connect through socket /opt/lampp/var/mysql/mysql.sock in perl

I am having trouble connecting to a database. Below is the Perl script that doesn't work:
use DBI;
my $dbh = DBI->connect(
'dbi:mysql:orders;mysql_socket:/opt/lampp/var/mysql/mysql.sock',
$username,
$password,
{ RaiseError => 0, AutoCommit => 0 },
)
or die $DBI::errstr;
Normally when I try to open the mysql.sock file using open function there is a error but I can't open it.
You should use '=' for extra parameters in dsn, so be it:
'dbi:mysql:orders;mysql_socket=/opt/lampp/var/mysql/mysql.sock',

Perl DBI - Capturing errors

What's the best way of capturing any DBI errors in Perl? For example if an insert fails because there were illegal characters in the values being inserted, how can I not have the script fail, but capture the error and handle it appropriately.
I don't want to do the "or die" because I don't want to stop execution of the script.
Use the RaiseError=>1 configuration in DBI->connect, and wrap your calls to the $dbh and $sth in a try block (TryCatch and Try::Tiny are good implementations for try blocks).
See the docs for more information on other connect variables available.
for example:
use strict;
use warnings;
use DBI;
use Try::Tiny;
my $dbh = DBI->connect(
$your_dsn_here,
$user,
$password,
{
PrintError => 0,
PrintWarn => 1,
RaiseError => 1,
AutoCommit => 1,
}
);
try
{
# deliberate typo in query here
my $data = $dbh->selectall_arrayref('SOHW TABLES', {});
}
catch
{
warn "got dbi error: $_";
};
you can also do the following, which will allow you to die, or gracefully handle the errors and continue.
$dbh = DBI->connect($data_src, $user, $pwd) or die $DBI::errstr;
my $sth = $dbh->prepare("DELETE FROM table WHERE foo = '?'");
$sth->execute('bar');
if ( $sth->err )
{
die "DBI ERROR! : $sth->err : $sth->errstr \n";
}