1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
|
=head1 NAME
DBIx::Class::Manual::Example - Simple CD database example
=head1 DESCRIPTION
This tutorial will guide you through the process of setting up and
testing a very basic CD database using SQLite, with DBIx::Class::Schema
as the database frontend.
The database consists of the following:
table 'artist' with columns: artistid, name
table 'cd' with columns: cdid, artist, title
table 'track' with columns: trackid, cd, title
And these rules exists:
one artist can have many cds
one cd belongs to one artist
one cd can have many tracks
one track belongs to one cd
=head2 Installation
Install DBIx::Class via CPAN should be sufficient.
=head3 Create the database/tables.
First make and change the directory:
mkdir app
cd app
mkdir db
cd db
This example uses SQLite which is a dependency of DBIx::Class, so you
shouldn't have to install extra software.
Save the following into a example.sql in the directory db
CREATE TABLE artist (
artistid INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
CREATE TABLE cd (
cdid INTEGER PRIMARY KEY,
artist INTEGER NOT NULL REFERENCES artist(artistid),
title TEXT NOT NULL
);
CREATE TABLE track (
trackid INTEGER PRIMARY KEY,
cd INTEGER NOT NULL REFERENCES cd(cdid),
title TEXT NOT NULL
);
and create the sqlite database file:
sqlite3 example.db < example.sql
=head3 Set up DBIx::Class::Schema
Change directory back from db to the directory app:
cd ../
Now create some more directories:
mkdir MyDatabase
mkdir MyDatabase/Main
Then, create the following DBIx::Class::Schema classes:
MyDatabase/Main.pm:
package MyDatabase::Main;
use base qw/DBIx::Class::Schema/;
__PACKAGE__->load_classes(qw/Artist Cd Track/);
1;
MyDatabase/Main/Artist.pm:
package MyDatabase::Main::Artist;
use base qw/DBIx::Class/;
__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('artist');
__PACKAGE__->add_columns(qw/ artistid name /);
__PACKAGE__->set_primary_key('artistid');
__PACKAGE__->has_many('cds' => 'MyDatabase::Main::Cd');
1;
MyDatabase/Main/Cd.pm:
package MyDatabase::Main::Cd;
use base qw/DBIx::Class/;
__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('cd');
__PACKAGE__->add_columns(qw/ cdid artist title/);
__PACKAGE__->set_primary_key('cdid');
__PACKAGE__->belongs_to('artist' => 'MyDatabase::Main::Artist');
__PACKAGE__->has_many('tracks' => 'MyDatabase::Main::Track');
1;
MyDatabase/Main/Track.pm:
package MyDatabase::Main::Track;
use base qw/DBIx::Class/;
__PACKAGE__->load_components(qw/PK::Auto Core/);
__PACKAGE__->table('track');
__PACKAGE__->add_columns(qw/ trackid cd title/);
__PACKAGE__->set_primary_key('trackid');
__PACKAGE__->belongs_to('cd' => 'MyDatabase::Main::Cd');
1;
=head3 Write a script to insert some records.
insertdb.pl
#!/usr/bin/perl -w
use MyDatabase::Main;
use strict;
my $schema = MyDatabase::Main->connect('dbi:SQLite:db/example.db');
# here's some of the sql that is going to be generated by the schema
# INSERT INTO artist VALUES (NULL,'Michael Jackson');
# INSERT INTO artist VALUES (NULL,'Eminem');
my @artists = (['Michael Jackson'], ['Eminem']);
$schema->populate('Artist', [
[qw/name/],
@artists,
]);
my %albums = (
'Thriller' => 'Michael Jackson',
'Bad' => 'Michael Jackson',
'The Marshall Mathers LP' => 'Eminem',
);
my @cds;
foreach my $lp (keys %albums) {
my $artist = $schema->resultset('Artist')->search({
name => $albums{$lp}
});
push @cds, [$lp, $artist->first];
}
$schema->populate('Cd', [
[qw/title artist/],
@cds,
]);
my %tracks = (
'Beat It' => 'Thriller',
'Billie Jean' => 'Thriller',
'Dirty Diana' => 'Bad',
'Smooth Criminal' => 'Bad',
'Leave Me Alone' => 'Bad',
'Stan' => 'The Marshall Mathers LP',
'The Way I Am' => 'The Marshall Mathers LP',
);
my @tracks;
foreach my $track (keys %tracks) {
my $cdname = $schema->resultset('Cd')->search({
title => $tracks{$track},
});
push @tracks, [$cdname->first, $track];
}
$schema->populate('Track',[
[qw/cd title/],
@tracks,
]);
=head3 Create and run the test scripts
testdb.pl:
#!/usr/bin/perl -w
use MyDatabase::Main;
use strict;
my $schema = MyDatabase::Main->connect('dbi:SQLite:db/example.db');
# for other DSNs, e.g. MySql, see the perldoc for the relevant dbd
# driver, e.g perldoc L<DBD::mysql>.
get_tracks_by_cd('Bad');
get_tracks_by_artist('Michael Jackson');
get_cd_by_track('Stan');
get_cds_by_artist('Michael Jackson');
get_artist_by_track('Dirty Diana');
get_artist_by_cd('The Marshall Mathers LP');
sub get_tracks_by_cd {
my $cdtitle = shift;
print "get_tracks_by_cd($cdtitle):\n";
my $rs = $schema->resultset('Track')->search(
{
'cd.title' => $cdtitle
},
{
join => [qw/ cd /],
prefetch => [qw/ cd /]
}
);
while (my $track = $rs->next) {
print $track->title . "\n";
}
print "\n";
}
sub get_tracks_by_artist {
my $artistname = shift;
print "get_tracks_by_artist($artistname):\n";
my $rs = $schema->resultset('Track')->search(
{
'artist.name' => $artistname
},
{
join => {
'cd' => 'artist'
},
}
);
while (my $track = $rs->next) {
print $track->title . "\n";
}
print "\n";
}
sub get_cd_by_track {
my $tracktitle = shift;
print "get_cd_by_track($tracktitle):\n";
my $rs = $schema->resultset('Cd')->search(
{
'tracks.title' => $tracktitle
},
{
join => [qw/ tracks /],
}
);
my $cd = $rs->first;
print $cd->title . "\n\n";
}
sub get_cds_by_artist {
my $artistname = shift;
print "get_cds_by_artist($artistname):\n";
my $rs = $schema->resultset('Cd')->search(
{
'artist.name' => $artistname
},
{
join => [qw/ artist /],
prefetch => [qw/ artist /]
}
);
while (my $cd = $rs->next) {
print $cd->title . "\n";
}
print "\n";
}
sub get_artist_by_track {
my $tracktitle = shift;
print "get_artist_by_track($tracktitle):\n";
my $rs = $schema->resultset('Artist')->search(
{
'tracks.title' => $tracktitle
},
{
join => {
'cds' => 'tracks'
}
}
);
my $artist = $rs->first;
print $artist->name . "\n\n";
}
sub get_artist_by_cd {
my $cdtitle = shift;
print "get_artist_by_cd($cdtitle):\n";
my $rs = $schema->resultset('Artist')->search(
{
'cds.title' => $cdtitle
},
{
join => [qw/ cds /],
}
);
my $artist = $rs->first;
print $artist->name . "\n\n";
}
It should output:
get_tracks_by_cd(Bad):
Dirty Diana
Smooth Criminal
Leave Me Alone
get_tracks_by_artist(Michael Jackson):
Beat it
Billie Jean
Dirty Diana
Smooth Criminal
Leave Me Alone
get_cd_by_track(Stan):
The Marshall Mathers LP
get_cds_by_artist(Michael Jackson):
Thriller
Bad
get_artist_by_track(Dirty Diana):
Michael Jackson
get_artist_by_cd(The Marshall Mathers LP):
Eminem
=head1 Notes
A reference implentation of the database and scripts in this example
are available in the main distribution for DBIx::Class under the
directory t/examples/Schema
With these scripts we're relying on @INC looking in the current
working directory. You may want to add the MyDatabase namespaces to
@INC in a different way when it comes to deployment.
The testdb.pl script is an excellent start for testing your database
model.
=head1 TODO
=head1 AUTHOR
sc_ from irc.perl.org#dbix-class
Kieren Diment <kd@totaldatasolution.com>
=cut
|