2. DBI
● The standard module for working with RDBMSs
DBD::Pg, DBD::mysql, DBD::SQLite, DBD::Oracle, DBD::ODBC
● Works on some non-RDBMSs
DBD::CSV, DBD::Cassandra, DBD::Amazon, DBD::Google, DBD::Salesforce
● DBD::Sponge
3. DBI History – The Bad Old Days
Different builds of perl for each database
● oraperl
● syperl
● INGperl
Each with it's own, incompatible API
4. DBI History – More Modern
First release Sept 1994, coincides with a pre-
release of perl5
One of the oldest maintained modules on CPAN
Over 130 releases
6. DBD - Drivers
Namespace for DBI drivers
● DBD::Pg
● DBD::mysql
● DBD::SQLite
● DBD::Oracle
● etc
Only for access compatibility, not SQL
7. Lifecycle of a request
● Text
● Compile
● Execute
● Results
8. Lifecycle of a request
● Text
● Compile
● Execute
● Results
my $sql = “select * from ...”;
my $sth = $dbh->prepare($sql)
$sth->execute('Bob');
my $row = $sth->fetchrow_arrayref()
9. Simple query
my $name = $ARGV[0];
my $dbh = DBI->connect('dbi:Pg:dbname=DataStore',
$username,
$passwd)
|| die “Can't connect: “ . DBI->errstr;
my $sth = $dbh->prepare(
qq(select * from student where name = '$name'));
$sth->execute();
while (my $row = $sth->fetchrow_arrayref()) {
print join(', ', @$row),”n”;
}
10. Simple query
my $name = $ARGV[0];
my $dbh = DBI->connect('dbi:Pg:dbname=DataStore',
$username,
$passwd)
|| die “Can't connect: “ . DBI->errstr;
my $sth = $dbh->prepare(
qq(select * from student where name = '$name'));
$sth->execute();
while (my $row = $sth->fetchrow_arrayref()) {
print join(', ', @$row),”n”;
}
> ./list_students “Jimbo Jones”
11. Simple query
my $name = $ARGV[0];
my $dbh = DBI->connect('dbi:Pg:dbname=DataStore',
$username,
$passwd)
|| die “Can't connect: “ . DBI->errstr;
my $sth = $dbh->prepare(
qq(select * from student where name = '$name'));
$sth->execute();
while (my $row = $sth->fetchrow_arrayref()) {
print join(', ', @$row),”n”;
}
> ./list_students “Robert';drop table students;--”
12. Simple query - Placeholders
my $name = $ARGV[0];
my $dbh = DBI->connect('dbi:Pg:dbname=DataStore',
$username,
$passwd)
|| die “Can't connect: “ . DBI->errstr;
my $sth = $dbh->prepare(
qq(select * from student where name = ?));
$sth->execute($name);
while (my $row = $sth->fetchrow_arrayref()) {
print join(', ', @$row),”n”;
}
> ./list_students “Robert';drop table students;--”
13. Placeholders
my $sth = $dbh->prepare(q(
select name, age, teacher
from students
where name = ?
and age < ?
));
$sth->execute('Bob', 15);
print join(', ', @$_) while $_ = $sth->fetchrow_arrayref;
$sth->execute('Joe', 10);
print join(', ', @$_) while $_ = $sth→fetchrow_arrayref;
$sth->execute('Fred', 20);
print join(', ', @$_) while $_ = $sth->fetchrow_arrayref;
15. Placeholders - Limitations
my $sth = $dbh->prepare(q(delete from ? where name = ?));
my $sth = $dbh->prepare(q(update students set ? = 2 where name = ?));
16. Placeholders - Limitations
my $sth = $dbh->prepare(q(delete from ? where name = ?));
my $sth = $dbh->prepare(q(update students set ? = 2 where name = ?));
my $sth = $dbh->prepare(q(select * from students ?));
17. Placeholders - Limitations
my $sth = $dbh->prepare(q(delete from ? where name = ?));
my $sth = $dbh->prepare(q(update students set ? = 2 where name = ?));
my $sth = $dbh->prepare(q(select * from students ?))
my $sth = $dbh->prepare(q(select * from students where id in (?)));
18. Placeholders - Limitations
my $sth = $dbh->prepare(q(delete from ? where name = ?));
my $sth = $dbh->prepare(q(update students set ? = 2 where name = ?));
my $sth = $dbh->prepare(q(select * from students ?))
my $sth = $dbh->prepare(q(select * from students where id in (?)));
my $sth = $dbh->prepare(q(select * from students where teacher = ?));
$sth->execute(undef);
19. Placeholders - Limitations
my $sth = $dbh->prepare(q(delete from ? where name = ?));
my $sth = $dbh->prepare(q(update students set ? = 2 where name = ?));
my $sth = $dbh->prepare(q(select * from students ?))
my $sth = $dbh->prepare(q(select * from students where id in (?)));
my $sth = $dbh->prepare(q(select * from students where teacher = ?));
$sth->execute(undef);
● Build SQL on the fly
● SQL::Abstract
20. Caching
● connect_cached()
my $dbh = DBI->connect_cached('dbi:Pg:dbname=foo;host=bar',
$username,
$passwd,
{ RaiseError => 1, AutoCommit => 0 });
● prepare_cached()
my $sth = $dbh->prepare_cached('select * from foo where bar = ?');
21. Convenience
my $aref = $sth->fetchrow_arrayref();
my @array = $sth->fetchrow_array();
my $href = $sth->fetchrow_hashref();
22. Convenience
my $aref_of_aref = $sth->fetchall_arrayref();
my $aref_of_aref = $sth->fetchall_arrayref([0,-1]);
my $aref_of_href = $sth->fetchall_arrayref({});
my $href_of_href = $sth->fetchall_hashref('col_name');
23. Convenience
my @array = $dbh->selectrow_array($sql);
my $aref = $dbh->selectrow_arrayref($sql);
my $href = $dbh->selectrow_hashref($sql);
24. Convenience
my @array_of_aref = $dbh->seletall_array($sql);
my $aref_of_aref = $dbh->selectall_arrayref($sql);
my $href_of_href = $dbh->selectall_hashref(
$sql,
'col_name');
26. Binding parameters
my $sth = $dbh->prepare('select key, value from attrs where item_id=?');
foreach my $id ( @id_list ) {
$sth->bind_param(0, $id, { ora_type => ORA_BLOB });
$sth->execute();
while (my $row = $sth->fetchrow_hashref()) {
printf(“%s => %sn”, $row->{key}, $row→{value});
}
}
27. Binding results
my $sth = $dbh->prepare('select key, value from attrs where item_id=?');
my($key, $value);
$sth->bind_col(0, $key);
$sth->bind_col(1, $value);
foreach my $id ( @id_list ) {
$sth->execute($id);
while( $sth->fetchrow_arrayref() ) {
print “$key => $valuen”;
}
}
28. last_insert_id
$dbh->do('create table things( id serial, name varchar )');
$sth = $dbh->prepare('insert into things (name) values (?)');
foreach my $name ( @name_list ) {
$sth->execute($name);
my $id = $sth->last_insert_id();
print “for $name, ID is $idn”;
}
30. Error Handling
● $dbh->{RaiseError} = 1;
● $dbh->{PrintError} = 1;
● $dbh->{HandleError} = sub { … };
● $DBI::err and $dbh->err
● $DBI::errstr and $dbh->errstr
31. Transactions
$dbh->{AutoCommit} = 1;
$sth = $dbh->prepare('update students
set grade = ?
where name = ?');
while(my($name, $grade) = each %student_grades) {
$sth->execute($name, $grade);
}
32. Transactions
$sth = $dbh->prepare('update students
set grade = ?
where name = ?');
$dbh->begin_work();
while(my($name, $grade) = each %student_grades) {
$sth->execute($name, $grade);
}
$dbh->commit();
37. DBIx::Class
● Canonical Object-Relational Mapper for Perl
● Supports most any DB supported by DBI
● Auto-discovers schema or customize
● First release August 2005
● Hundreds of contributors
38. DBIx::Class
● Program can have many schemas (databases)
● Schemas have many resultsources (tables)
● Resultsources have many resultsets
● Resultsets have many objects (rows)
40. DBIx::Class Result Source
package MyApp::School::Result::Teacher;
use base qw/DBIx::Class::Core/;
__PACKAGE__->table('teacher');
__PACKAGE__->add_columns(qw/teacher_ id name subject /);
__PACKAGE__->set_primary_key(teacher_'id');
__PACKAGE__->has_many(students =>
'MyApp::School::Result::Student', 'teacher_id');
1;
41. DBIx::Class Result Source
package MyApp::School::Result::Student;
use base qw/DBIx::Class::Core/;
__PACKAGE__->table('student');
__PACKAGE__->add_columns(qw/ student_id name age grade teacher_id /);
__PACKAGE__->set_primary_key('student_id');
__PACKAGE__->belongs_to(teacher =>
'MyApp::School::Result::teacher', 'teacher_id');
1;
42. DBIx::Class Fetch All
use MyApp::School;
my $schema = MyApp::School->connect(
$dbi_dsn,
$user,
$passwd);
my @all_teachers = $schema->resultset('Teacher')->all;
foreach my $teacher ( @all_teachers ) {
print “Teacher named “, $teacher->name, “n”;
}
43. DBIx::Class Find
my $student = $schema->resultset('Student')
->find(62);
print “student name “,$student->name, “n”;
44. DBIx::Class Search
my $student_rs = $schema->resultset('Student')
->search({ grade => 'B' });
while (my $student = $student_rs->next) {
print $student->name, “ got a Bn”;
}
45. DBIx::Class Search Related
my $smith_teachers_rs = $schema->resultset('Teacher')
->search({ name => { like => '% Smith' }});
my $student_rs = $smith_teachers_rs->search_related('students',
{ grade => 'C' });
46. DBIx::Class Create
my $student = $schema->resultset('Student')->new({
Name => 'Jimbo Jones',
Age => 11,
});;
$student->insert();