</div>
<div class="slide">
+ <h1>Contact Info</h1>
+ <ul>
+ <li>IRC: irc.perl.org #dbix-class</li>
+ <li>ML: <a href="http://lists.scsys.co.uk/mailman/listinfo/dbix-class">http://lists.scsys.co.uk/mailman/listinfo/dbix-class</a></li>
+ <li><a href="http://search.cpan.org/perldoc?DBIx::Class">DBIx::Class</a> yo</li>
+ </ul>
+ </div>
+
+ <div class="slide">
<h1>Authors</h1>
<h4>Originally Leo Lapworth @ LPW 2009</h4>
<h4>Amiri Barksdale</h4>
<div class="slide">
<h1>What's up guys?</h1>
- <div class="notes">
- <ul>
- <li>How many people have used any ORM?<ul>
- <li>In Perl?<ul>
- <li>DBIC?</li>
- <li>Class::DBI?</li>
- <li>Rose::DB?</li>
- <li>Fey?</li>
- <li>Others?</li>
- </ul></li>
- <li>AR?</li>
- <li>DataMapper?</li>
- <li>(N)Hibernate?</li>
+ <ul class="incremental">
+ <li>How many people have used any ORM?</li><ul class="incremental">
+ <li>In Perl?<ul class="incremental">
+ <li>DBIC?</li>
+ <li>Class::DBI?</li>
+ <li>Rose::DB?</li>
+ <li>Fey::ORM?</li>
+ <li>Others?</li>
</ul></li>
- </ul>
- </div>
+ <li>AR?</li>
+ <li>(N)Hibernate?</li>
+ </ul></li>
+ </ul>
</div>
<div class="slide">
<p>The purpose of this talk is to show you as many features of
DBIx::Class in 40 minutes so that when you need to do something with
it later you will know what's possible</p>
+ <ul class="incremental">
+ <li>Note: links in slides are so you can find docs for what I'm talking about later</li>
+ </ul>
</div>
<div class="slide">
<div class="slide">
<h1>Responsive Community</h1>
<ul class="incremental">
- <li>needed MSSQL Order by support, they helped me add support</li>
+ <li>needed MSSQL order-by support, they helped me add support</li>
<li>generally very welcoming of people willing to help</li>
</ul>
</div>
<div class="slide">
<h1>DBIC: Create</h1>
-<pre>my $book = $book_rs->create({
+<pre>my $book = $book_rs-><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#create">create</a>({
title => 'A book title',
author_id => $author_id,
});</pre>
<ul class="incremental">
<li>No need to pair placeholders and values</li>
<li>Automatically gets autoincremented id for you</li>
+ <li>Transparently uses INSERT ... RETURNING for databases that support it</li>
</ul>
</div>
authors.name as author_name
FROM books, authors
WHERE books.author = authors.id
-');</pre>
- </div>
+');
- <div class="slide">
- <h1>SQL: Read</h1>
-<pre>while( my $book = $sth->fetchrow_hashref() ) {
+while( my $book = $sth->fetchrow_hashref() ) {
print 'Author of '
. $book->{title}
. ' is '
<div class="slide">
<h1>DBIC: Read</h1>
-<pre>my $book = $book_rs->find($book_id);
+<pre>my $book = $book_rs-><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#find">find</a>($book_id);
-my $book = $book_rs->search({
+my $book = $book_rs-><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#search">search</a>({
title => 'A book title',
-}, { rows => 1 })->single;
+}, { rows => 1 })-><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#next">next</a>;
my @books = $book_rs->search({
author => $author_id,
-})->all;</pre>
- <ul class="incremental">
- <li>TMTOWTDI</li>
- </ul>
- </div>
+})-><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#all">all</a>;
- <div class="slide">
- <h1>DBIC: Read</h1>
-<pre>while( my $book = $books_rs->next ) {
+while( my $book = $books_rs->next ) {
print 'Author of '
. $book->title
. ' is '
. $book->author->name
. "\n";
-}</pre>
+}
+</pre>
+ <ul class="incremental">
+ <li>TMTOWTDI</li>
+ </ul>
</div>
<div class="slide">
<div class="slide">
<h1>DBIC: Update</h1>
-<pre>$book->update({
+<pre>$book-><a href="http://search.cpan.org/perldoc?DBIx::Class::Row#update">update</a>({
title => 'New title',
});</pre>
+ <ul class="incremental">
+ <li>Won't update unless value changes</li>
+ </ul>
</div>
<div class="slide">
<div class="slide">
<h1>DBIC: Delete</h1>
-<pre>$book->delete;</pre>
+<pre>$book-><a href="http://search.cpan.org/perldoc?DBIx::Class::Row#delete">delete</a>;</pre>
+ </div>
+
+ <div class="slide">
+ <h1>SQL: Search</h1>
+<pre>my $sth = $dbh->prepare('
+ SELECT title,
+ authors.name as author_name
+ FROM books
+ WHERE books.name LIKE "%monte cristo%" AND
+ books.topic = "jailbreak"
+');
+</pre>
+ </div>
+
+ <div class="slide">
+ <h1>DBIC: Search</h1>
+<pre>
+my $book = $book_rs-><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#search">search</a>({
+ 'me.name' => { -like => '%monte cristo%' },
+ 'me.topic' => 'jailbreak',
+})-><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#next">next</a>;
+</pre>
+ <ul class="incremental">
+ <li><a href="http://search.cpan.org/perldoc?SQL::Abstract">SQL::Abstract</a></li>
+ <li>(kinda) introspectible</li>
+ <li>Prettier than SQL</li>
+ </ul>
</div>
<div class="slide">
<div class="slide">
<h1>Convenience Methods</h1>
<ul class="incremental">
- <li>find_or_create</li>
- <li>create_or_update</li>
+ <li><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#find_or_create">find_or_create</a></li>
+ <li><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#update_or_create">update_or_create</a></li>
</ul>
</div>
<div class="slide">
<h1>->deploy</h1>
<p>Perl -> DB</p>
-<pre>my $schema = Foo::Schema->connect($dsn, $user, $pass);
-$schema->deploy
+<pre>my $schema = Foo::Schema->connect(
+ $dsn, $user, $pass
+);
+$schema-><a href="http://search.cpan.org/perldoc?DBIx::Class::Schema#deploy">deploy</a>
</pre>
<p>See also: <a href="http://search.cpan.org/perldoc?DBIx::Class::DeploymentHandler">DBIx::Class::DeploymentHandler</a></p>
</div>
<p>DB -> Perl</p>
<pre>package Foo::Schema;
use strict; use warnings;
-use base 'DBIx::Class::Schema::Loader';
-__PACKAGE__->loader_options({
+use base '<a href="http://search.cpan.org/perldoc?DBIx::Class::Schema::Loader">DBIx::Class::Schema::Loader</a>';
+__PACKAGE__-><a href="http://search.cpan.org/perldoc?DBIx::Class::Schema::Loader::Base#CONSTRUCTOR_OPTIONS">loader_options</a>({
naming => 'v7',
debug => $ENV{DBIC_TRACE},
});
# elsewhere...
-my $schema = Foo::Schema->connect($dsn, $user, $pass);
+my $schema = Foo::Schema->connect(
+ $dsn, $user, $pass
+);
</pre>
</div>
<div class="slide">
<h1>Populate</h1>
<p>Made for inserting lots of rows very quicky into database</p>
-<pre>$schema->populate([ Users =>
+<pre>$schema-><a href="http://search.cpan.org/perldoc?DBIx::Class::Schema#populate">populate</a>([ Users =>
[qw( username password )],
- [qw( frew >=4char$ )],
+ [qw( frew >=4char$ )],
[qw( ... )],
[qw( ... )],
);
<div class="slide">
<h1>Multicreate</h1>
<p>Create an object and all of it's related objects all at once</p>
-<pre>$schema->resultset('Author')->create({
+<pre>$schema->resultset('Author')-><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#create">create</a>({
name => 'Stephen King',
books => [{ title => 'The Dark Tower' }],
address => {
street => '123 Turtle Back Lane',
state => { abbreviation => 'ME' },
- city => { name => 'Lowell' },
+ city => { name => 'Lowell' },
},
});
</pre>
<div class="slide">
<h1>Extensible: DBIC::Helpers</h1>
<ul class="incremental">
- <li>DBIx::Class::Helper::ResultSet::IgnoreWantarray</li>
- <li>DBIx::Class::Helper::ResultSet::Random</li>
- <li>DBIx::Class::Helper::ResultSet::SetOperations</li>
- <li>DBIx::Class::Helper::Row::JoinTable</li>
- <li>DBIx::Class::Helper::Row::NumifyGet</li>
- <li>DBIx::Class::Helper::Row::SubClass</li>
- <li>DBIx::Class::Helper::Row::ToJSON</li>
+ <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Helper::ResultSet::IgnoreWantarray">DBIC::Helper::ResultSet::IgnoreWantarray</a></li>
+ <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Helper::ResultSet::Random">DBIC::Helper::ResultSet::Random</a></li>
+ <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Helper::ResultSet::SetOperations">DBIC::Helper::ResultSet::SetOperations</a></li>
+ <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Helper::ResultSet::JoinTable">DBIC::Helper::Row::JoinTable</a></li>
+ <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Helper::ResultSet::NumifyGet">DBIC::Helper::Row::NumifyGet</a></li>
+ <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Helper::ResultSet::SubClass">DBIC::Helper::Row::SubClass</a></li>
+ <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Helper::ResultSet::ToJSON">DBIC::Helper::Row::ToJSON</a></li>
</ul>
</div>
<div class="slide">
- <h1>Extensible: DBIC::TimeStamp</h1>
+ <h1>Extensible: <a href="http://search.cpan.org/perldoc?DBIx::Class::TimeStamp">DBIC::TimeStamp</a></h1>
<ul class="incremental">
<li>Cross DB</li>
<li>set_on_create</li>
</div>
<div class="slide">
- <h1>Extensible: DBIx::Class::Schema::KiokuDB</h1>
+ <h1>Extensible: Kioku</h1>
<ul class="incremental">
+ <li><a href="http://search.cpan.org/perldoc?DBIx::Class::Schema::KiokuDB">DBIx::Class::Schema::KiokuDB</a></li>
<li>Kioku is the new hotness</li>
<li>Mix RDBMS with Object DB</li>
<li>beta ( == sexy )</li>
</div>
<div class="slide">
- <h1>SQL::Abstract</h1>
-<pre>my $resultset = $book_rs->search({
- name => { -like => "%$nick%" },
-});</pre>
- <ul class="incremental">
- <li>(kinda) introspectible</li>
- <li>Prettier than SQL</li>
- </ul>
- </div>
-
- <div class="slide">
<h1>Result vs ResultSet</h1>
<ul class="incremental">
<li>Result == Row</li>
- <li>ResultSet == Query</li>
+ <li>ResultSet == Query Plan<ul class="incremental">
+ <li>Internal Join Optimizer for all DB's (!!!)</li>
+ </ul></li>
<li>(less important but...)</li>
<li>ResultSource == Table</li>
<li>Storage == Database</li>
</div>
<div class="slide">
- <h1>ResultSet methods</h1>
+ <h1><a href="http://search.cpan.org/perldoc?DBIx::Class::Manual::Cookbook#Predefined_searches">ResultSet methods</a></h1>
<pre>package MyApp::Schema::ResultSet::Book;
use base 'DBIx::Class::ResultSet';
sub good {
- $_[0]->search({
- rating => { '>=' => 4 },
+ my $self = shift;
+ $self->search({
+ $self->current_source_alias .
+ '.rating' => { '>=' => 4 },
})
};
sub cheap {
- $_[0]->search({
- price => { '<=' => 5}
+ my $self = shift;
+ $self->search({
+ $self->current_source_alias .
+ '.price' => { '<=' => 5}
})
};
# ...
1;
</pre>
+ </div>
+
+ <div class="slide">
+ <h1>ResultSet method notes</h1>
<ul class="incremental">
<li>All searches should be ResultSet methods</li>
<li>Name has obvious meaning</li>
+ <li><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#current_source_alias">current_source_alias</a> helps things to work no matter what</li>
</ul>
</div>
<div class="slide">
<h1>search_related</h1>
- <pre>*get example from work*</pre>
+<pre>my $score = $schema->resultset('User')
+ ->search({'me.userid' => 'frew'})
+ -><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#related_resultset">related_resultset</a>('access')
+ ->related_resultset('mgmt')
+ ->related_resultset('orders')
+ ->telephone
+ -><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#search_related">search_related</a>( shops => {
+ 'shops.datecompleted' => {
+ -between => ['2009-10-01','2009-10-08']
+ }
+ })->completed
+ ->related_resultset('rpt_score')
+ -><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#get_column">get_column</a>('raw_scores')
+ ->first;
+</pre>
</div>
<div class="slide">
<h1>bonus rel methods</h1>
-<pre>my $book = $author->create_related(
- <strong>books</strong> => {
- title => 'Another Discworld book',
-});
+<pre>my $book = $author-><a href="http://search.cpan.org/perldoc?DBIx::Class::Relationship::Base#create_related">create_related</a>(
+ <strong>books</strong> => {
+ title => 'Another Discworld book',
+ }
+);
-my $book2 = $pratchett->add_to_<strong>books</strong>({
+my $book2 = $pratchett-><a href="http://search.cpan.org/perldoc?DBIx::Class::Relationship::Base#add_to_$rel">add_to_<strong>books</strong></a>({
title => 'MOAR Discworld book',
});</pre>
<ul class="incremental">
<div class="slide">
<h1>Excellent Transaction Support</h1>
-<pre>$schema->txn_do(sub {
+<pre>$schema-><a href="http://search.cpan.org/perldoc?DBIx::Class::Schema#txn_do">txn_do</a>(sub {
...
});
-my $guard = $schema->txn_scope_guard;
+my $guard = $schema-><a href="http://search.cpan.org/perldoc?DBIx::Class::Schema#txn_scope_guard">txn_scope_guard</a>;
# ...
$guard->commit;
-$schema->txn_begin; # <-- low level
+$schema-><a href="http://search.cpan.org/perldoc?DBIx::Class::Schema#txn_begin">txn_begin</a>; # <-- low level
# ...
-$schema->txn_commit;
+$schema-><a href="http://search.cpan.org/perldoc?DBIx::Class::Schema#txn_commit">txn_commit</a>;
</pre>
</div>
<h1>InflateColumn</h1>
<pre>package Foo::Schema::Result::Book;
use base 'DBIx::Class::Core';
-# Result code here
-__PACKAGE__->load_components('InflateColumn');
use DateTime::Format::MySQL;
-__PACKAGE__-><strong>inflate_column</strong>(
+# Result code here
+__PACKAGE__->load_components('<a href="http://search.cpan.org/perldoc?DBIx::Class::InflateColumn">InflateColumn</a>');
+__PACKAGE__-><strong><a href="http://search.cpan.org/perldoc?DBIx::Class::InflateColumn#inflate_column">inflate_column</a></strong>(
<strong>date_published</strong> => {
- inflate => sub { DateTime::Format::MySQL->parse_date(shift) },
- deflate => sub { shift->ymd},
+ inflate => sub {
+ DateTime::Format::MySQL->parse_date(
+ shift
+ )
+ },
+ deflate => sub { shift->ymd },
},
);
-# Automatic see: DBIx::Class::InflateColumn::DateTime</pre>
+# Automatic see: DBIC::InflateColumn::DateTime</pre>
</div>
<div class="slide">
<div class="slide">
<h1>InflateColumn: inflation</h1>
-<pre>my $date_published = $book->date_published;
-print $date_published->month_abbr;</pre>
+<pre>say $book->date_published->month_abbr;</pre>
<strong><em>Nov</em></strong>
</div>
<pre>package Foo::Schema::Result::Book;
use base 'DBIx::Class::Core';
# Result code here
-__PACKAGE__->load_components('FilterColumn');
+__PACKAGE__->load_components('<a href="http://search.cpan.org/perldoc?DBIx::Class::FilterColumn">FilterColumn</a>');
-__PACKAGE__-><strong>filter_column</strong>(
+__PACKAGE__-><strong><a href="http://search.cpan.org/perldoc?DBIx::Class::FilterColumn#filter_column">filter_column</a></strong>(
<strong>length</strong> => {
to_storage => 'to_metric',
from_storage => 'to_imperial',
sub to_metric { $_[1] * .305 }
sub to_imperial { $_[1] * 3.28 }
-# Automatic see: DBIx::Class::InflateColumn::DateTime</pre>
</div>
<div class="slide">
- <h1>ResultSetColumn</h1>
-<pre>my $rsc = $schema->resultset('Book')->get_column('price');
+ <h1><a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSetColumn">ResultSetColumn</a></h1>
+<pre>my $rsc = $schema->resultset('Book')
+ ->get_column('price');
+$rsc->first;
+$rsc->all;
$rsc->min;
$rsc->max;
$rsc->sum;
<div class="slide">
<h1>Aggregates</h1>
<pre>my @res = $rs->search({}, {
- select => [qw(price genre), { max => price }, { avg => price }],
- as => [qw(price genre max_price avg_price)],
- group_by => [qw(price genre)],
+ <a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#select">select</a> => [
+ 'price',
+ 'genre',
+ { max => price },
+ { avg => price },
+ ],
+ <a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#as">as</a> => [
+ qw(price genre max_price avg_price)
+ ],
+ <a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#group_by">group_by</a> => [qw(price genre)],
});
for (@res) {
say $_->price . ' ' . $_->genre;
say $_->get_column('max_price');
say $_->get_column('min_price');
}</pre>
+ </div>
+
+ <div class="slide">
+ <h1>Aggregates Notes</h1>
<ul class="incremental">
<li>Careful, get_column can basicaly mean THREE things</li>
<li>private for get what you should use an accessor for</li>
<div class="slide">
<h1>HRI</h1>
<pre>$rs->search({}, {
- result_class => 'DBIx::Class::ResultClass::HashRefInflator',
+ <a href="http://search.cpan.org/perldoc?DBIx::Class::ResultSet#result_class">result_class</a> =>
+ '<a href="http://search.cpan.org/perldoc?DBIx::Class::ResultClass::HashRefInflator">DBIx::Class::ResultClass::HashRefInflator</a>',
});</pre>
<ul class="incremental">
<li>Easy on memory</li>
</div>
<div class="slide">
- <h1>Subquery Support</h1>
-<pre> my $inside_rs = $schema->resultset('Artist')->search({
+ <h1><a href="http://search.cpan.org/perldoc?DBIx::Class::Manual::Cookbook#Subqueries">Subquery</a> Support</h1>
+<pre>my $inside_query = $schema->resultset('Artist')
+ ->search({
name => [ 'Billy Joel', 'Brittany Spears' ],
-});
+})->get_column('id')->as_query;
my $rs = $schema->resultset('CD')->search({
- artist_id => { -in => $inside_rs->get_column('id')->as_query },
+ artist_id => { -in => $inside_query },
});</pre>
</div>
<div class="slide">
- <h1>Bare SQL w/ Placeholders</h1>
+ <h1><a href="http://search.cpan.org/perldoc?SQL::Abstract#Literal_SQL_with_placeholders_and_bind_values_(subqueries)">Bare SQL w/ Placeholders</a></h1>
<pre>$rs->update({
- price => \"price + $inc", # !!! SQL INJECTION VECTOR
+ # !!! SQL INJECTION VECTOR
+ price => \"price + $inc",
});
$rs->update({