E’ un periodo in cui sto lavorando molto con perl e database differenti.
Ho già parlato del modulo DBI, e di quanto esso mi gusti.
Se per caso servisse sapere quali driver DBI mette a disposizione, ecco l’elenco dei database a cui è possibile collegarsi.
AnyData
CSV
DBM
ExampleP
File
Gofer
Pg
Proxy
SQLite
Sponge
mysql
Nel delirio perlico che ogni tanto mi prende, mi sono messo a guardare un po’ di codice che richiedeva un differente approccio per collegarsi ai db.
Devo dire che sono rimasto schifosamente affascinato da DBIx::Class e il suo “Schema”, ma non avendoci ancora capito molto, aspetto a scriverci su qualcosa.
Di sicuro invece c’è che DBIx::Simple funziona. Non ho ben capito perchè dovrebbe essere più semplice di DBI, però… funziona.
DBI, come ho già scritto in passato, funge così: si carica l’handler, si prepara la query, la si esegue e si fetcha il risultato nella maniera che si ritiene più opportuna. (*)
use DBI;
my $dsn = "dbi:mysql:database=test";
my $dbh = DBI->connect( $dsn, $username, $password )
or die $DBI::errstr;
my $sth = $dbh->prepare("SELECT * FROM testing")
or die $dbh->errstr;
$sth->execute();
while ( my $row = $sth->fetchrow_hashref() )
{ ... }
Il vantaggio con DBIx::Simple è che prepare() ed execute() sono compresi in un’unica chiamata. Il fetching dei risultati dovrebbe essere un po’ semplificato, ma a me non ha cambiato la vita (i metodi sono al paragrafo DBIx::Simple::Result methods).
use DBIx::Simple;
my $dbh = DBIx::Simple->connect('dbi:Pg:dbname=test',
'username', 'password' ) or die DBIx::Simple->error;
my $res = $dbh->query('SELECT * FROM pluto');
while ( $res->into(my($id, $ti, $ra)) ) {
say "$id $ti $ra";
}
Nota: L’idea del metodo html per ottenere una tabella HTML dal risultato l’ho trovata simpatica.
(*) Attualmente il modo più comodo che ho trovato per fare le chiamate è passando attraverso una subroutine che si mangia l’handler e la query come argomenti:
sub sql_query {
my ($dbh,$query) = @_;
my $result = $dbh->prepare($query)
or print("Failed to set up query: $query\n");
$result->execute()
or print("Failed to exec query: $query\n");
return $result;
}
...
my $dbh = DBI->connect(...)
$risultato = sql_query($dbh, "SELECT * FROM pippo");
while ( my @riga = $risultato->fetchrow_array ) { ... }
Tempo addietro ho parlato del bellissimo DBI di perl, ma non ho parlato dei placeholder.
Dunque ho rispolverato questo post di inizio dicembre 2008, così da aver almeno un paio di note about them.
use DBI;
my $dbh = DBI->connect("dbi:mysql:dbname","user","passwd")
or die("Couldn't connect to db");
La query puo’ essere scritta normalmente come $variabile = ‘SELECT bla FROM blabla [...]‘ oppure manipolata in maniera piu’ interessante come segue:
my @columns = qw(id name surname birth notes);
my $query_ins = "INSERT INTO table (".
join(", ", @columns).
") VALUES (".
join(", ", map {"?"} @columns).
")";
Che equivale ad un INSERT INTO table (id, name, surname, birth, notes) VALUES (?, ?, ?, ?, ?);
I punti interrogativi (?) sono i cosiddetti placeholder, che permettono di inserire singoli parametri molto comodamente.
Perl fa tante cose belle… fra le altre ha un bellissimo modulo che gestisce l’interazione coi database: questo modulo si chiama DBI.
In un programma tipico vediamo la chiamata al modulo, l’impostazione del database handler ($dbh) e dello statement handler ($sth), la query ($sql), poi la preparazione e l’esecuzione della query.
#!/usr/bin/perl
use DBI;
my $dbh = DBI->connect("dbi:mysql:dbname","user","passwd")
or die("Couldn't connect to db: ".$DBI::errstr);
my $sql = "SELECT id,name,surname FROM table";
my $sth = $dbh->prepare($sql)
or die("Couldn't prepare statement: ".$dbh->errstr);
$sth->execute();
La cosa molto interessante, a mio avviso, è che Perl offre moltissimi modi per fetchare i dati dall’oggetto scaricato dal db.
1) fetchrow_array, questo metodo copia i dati dal db all’array @row e poi li manipola intervenendo sull’array.
while ( my @row = $sth->fetchrow_array() )
{
print("$row[0]\t$row[1]\t$row[2]\n");
}
2) fetchrow_arrayref, questo metodo crea un riferimento numerico al record nel db.
while ( my $row = $sth->fetchrow_hashref() )
{
print("$row->[0]\t$row->[1]\t$row->[2]\n");
}
3) fetchrow_hashref, questo metodo crea un riferimento associativo al record nel db.
while ( my $row = $sth->fetchrow_hashref() )
{
print("$row->{id}\t$row->{name}\t$row->{surname}\n");
}
4) fetchall_arrayref, questo metodo è molto interessante perche’ permette di manipolare tutti i record attraverso le reference di un array di reference. (I dati si possono mischiare, scambiando i riferimenti dell’array di riferimento.)
my $row = $sth->fetchall_arrayref();
# stampano i 3 dati del primo [0] e del secondo [1] record
print("$row->[0]->[0]\t$row->[0]->[1]\t$row->[0]->[2]\n");
print("$row->[1]->[0]\t$row->[1]->[1]\t$row->[1]->[2]\n");
# stampa il primo dato del primo record, il secondo dato del secondo
# record, ed il terzo dato del terzo record.
print("$row->[0]->[0]\t$row->[1]->[1]\t$row->[2]->[2]\n");
5) bind_columns / fetch
my( $id, $name, $surname );
$sth->bind_columns( \$id, \$name, \$surname );
while ($sth->fetch())
{
print("$id\t$name $surname\n");
}
Info sparse online: