From: Matt S Trout Date: Wed, 16 Nov 2005 02:48:44 +0000 (+0000) Subject: Merge 'DBIx-Class-C3' into 'trunk' X-Git-Tag: v0.05005~167 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=8294874d21acf4dfc75765a0359ffd2d0f9c016b;hp=1edd17220a3f0fa2768084572d8ca57cfc2a2fcc;p=dbsrgits%2FDBIx-Class.git Merge 'DBIx-Class-C3' into 'trunk' --- diff --git a/lib/DBIx/Class/Manual/Cookbook.pod b/lib/DBIx/Class/Manual/Cookbook.pod index ee5ea22..1d2b4c6 100644 --- a/lib/DBIx/Class/Manual/Cookbook.pod +++ b/lib/DBIx/Class/Manual/Cookbook.pod @@ -13,55 +13,66 @@ DBIx::Class::Manual::Cookbook - Misc receipes This is not as easy as it could be, but it's possible. Here's an example to illustrate: - package Base; - - use base qw/DBIx::Class/; - - __PACKAGE__->load_components(qw/Core DB/); - __PACKAGE__->connection(...); - - package Left; - - use base qw/Base/; - - __PACKAGE__->table('left'); - __PACKAGE__->add_columns(qw/id left_stuff/); - __PACKAGE__->set_primary_key(qw/id/); - __PACKAGE__->has_many('mid' => 'Mid'); - - sub right { - my ($self) = @_; - return Right->search( - { 'left.id' => $self->id }, - { join => { 'mid' => 'left' }}); - } - - package Mid; - - use base qw/Base/; - - __PACKAGE__->table('mid'); - __PACKAGE__->add_columns(qw/left right/); - __PACKAGE__->set_primary_key(qw/left right/); - - __PACKAGE__->belongs_to('left' => 'Left'); - __PACKAGE__->belongs_to('right' => 'Right'); - - package Right; - - use base qw/Base/; - - __PACKAGE__->table('right'); - __PACKAGE__->add_columns(qw/id right_stuff/); - __PACKAGE__->set_primary_key(qw/id/); - __PACKAGE__->has_many('mid' => 'Mid'); - - sub left { - my ($self) = @_; - return Left->search( - { 'right.id' => $self->id }, - { join => { 'mid' => 'right' }); - } + # Set up inherited connection information + package MyApp::DBIC; + use base qw/DBIx::Class/; + + __PACKAGE__->load_components(qw/PK::Auto::SQLite Core DB/); + __PACKAGE__->connection(...); + + # Set up a class for the 'authors' table + package MyApp::DBIC::Author; + use base qw/MyApp::DBIC/; + + __PACKAGE__->table('authors'); + __PACKAGE__->add_columns(qw/authID first_name last_name/); + __PACKAGE__->set_primary_key(qw/authID/); + + # Define relationship to the link table + __PACKAGE__->has_many('b2a' => 'MyApp::DBIC::Book2Author', 'authID'); + + # Create the accessor for books from the ::Author class + sub books { + my ($self) = @_; + return MyApp::DBIC::Book->search( + { 'b2a.authID' => $self->authID }, # WHERE clause + { join => 'b2a' } # join condition (part of search attrs) + # 'b2a' refers to the relationship named earlier in the Author class. + # 'b2a.authID' refers to the authID column of the b2a relationship, + # which becomes accessible in the search by being joined. + ); + } + + # define the link table class + package MyApp::DBIC::Book2Author; + use base qw/MyApp::DBIC/; + + __PACKAGE__->table('book2author'); + __PACKAGE__->add_columns(qw/bookID authID/); + __PACKAGE__->set_primary_key(qw/bookID authID/); + + __PACKAGE__->belongs_to('authID' => 'MyApp::DBIC::Author'); + __PACKAGE__->belongs_to('bookID' => 'MyApp::DBIC::Book'); + + package MyApp::DBIC::Book; + use base qw/MyApp::DBIC/; + + __PACKAGE__->table('books'); + __PACKAGE__->add_columns(qw/bookID title edition isbn publisher year/); + __PACKAGE__->set_primary_key(qw/bookID/); + + __PACKAGE__->has_many('b2a' => 'MyApp::DBIC::Book2Author', 'bookID'); + + sub authors { + my ($self) = @_; + return MyApp::DBIC::Author->search( + { 'b2a.bookID' => $self->bookID }, # WHERE clause + { join => 'b2a' }); # join condition (part of search attrs) + } + + # So the above search returns an author record where the bookID field of the + # book2author table equals the bookID of the books (using the bookID + # relationship table =item Advanced Exception handling diff --git a/lib/DBIx/Class/Manual/Intro.pod b/lib/DBIx/Class/Manual/Intro.pod index cdb8144..556c552 100644 --- a/lib/DBIx/Class/Manual/Intro.pod +++ b/lib/DBIx/Class/Manual/Intro.pod @@ -30,7 +30,9 @@ mostly useful if you want to use multiple database connections. __PACKAGE__->load_components(qw/Core DB/); If you want serial/auto-incremental primary keys, you'll need to add -the apropriate component for your db as well, for example +the apropriate component for your db as well, for example. The +PK::Auto::* modules help L keep up with newly generated +keys in auto increment database fields. __PACKAGE__->load_components(qw/PK::Auto::SQLite Core DB/); @@ -43,24 +45,24 @@ attribute hash as well as the dsn. With that out of the way, we can define our first table class: - package MyApp::DB::Frob + package MyApp::DB::Album; use base qw/MyApp::DB/; Then we specify which table it uses, - __PACKAGE__->table('frob'); + __PACKAGE__->table('album'); and specify which columns it has. - __PACKAGE__->add_columns(qw/id foo bar/); + __PACKAGE__->add_columns(qw/albumID artist title label year/); This will automatically create accessors for each of the columns, so that you can read/update the values in rows you've retrieved. Also, you need to tell it which column is the primary key: - __PACKAGE__->set_primary_key('id'); + __PACKAGE__->set_primary_key('albumID'); If you have multiple primary keys, just pass a list instead. @@ -78,9 +80,9 @@ creates classes for all the tables in your database. Here's a simple setup: use DBIx::Class::Loader; - my $loader=DBIx::Class::Loader->new( - dsn => 'dbi:SQLite:/home/me/myapp/my.db', - namespace => 'MyApp::DB'); + my $loader = DBIx::Class::Loader->new( + dsn => 'dbi:SQLite:/home/me/myapp/my.db', + namespace => 'MyApp::DB'); 1; This should be equivalent to the manual in the section above. @@ -92,14 +94,15 @@ consult the reference documentation. Once you've defined the basic classes, you can start interacting with your database. The simplest way to get a column is by primary key: - my $frob=MyApp::DB::Frob->find(14); + $albumID = 14; + $album = MyApp::DB::Album->find($albumID); -This will run a select with id=14 in the WHERE clause, and return an instance -of MyApp::DB::Frob that represents this row. Once you have that row, you can +This will run a select with albumID=14 in the WHERE clause, and return an instance +of MyApp::DB::Artist that represents this row. Once you have that row, you can access and update columns - my $val=$frob->bar; - $frob->bar(14); + $album->title('Physical Graffiti'); + $title = $album->title; # $title holds 'Physical Graffiti' or if you prefer, you can use the set_column/get_column accessors instead of the autogenerated accessors based on your column names. @@ -107,64 +110,73 @@ of the autogenerated accessors based on your column names. Just like with L, you do an 'update' to commit your changes to the database: - $frob->update; + $album->update; If needed, you can drop your local changes instead like this: - $frob->discard_changes if $frob->is_changed; + $album->discard_changes if $album->is_changed; As you can see, is_changed allows you to check if there are local changes to your object. =head2 Adding and removing rows. -To make a new row, and put it into the database, you can use the 'create' -method from L +To create a new record in the database, you can use the 'create' +method from L. It returns a L +object that can be used to access the data in the new record. - my $new_thingie=MyApp::DB::Frob->create({ - foo=>'homer', - bar=>'bart' }); + $new_album = MyApp::DB::Album->create({ + title => 'Wish You Were Here', + artist => 'Pink Floyd' + }); + +Now you can add data to the new record: + + $new_album->label('Capitol'); + $new_album->year('1975'); likewise, you can remove if from the database like this: - $new_thingie->delete(); + $new_album->delete(); or even without retrieving first. This operation takes the same kind of arguments as a search. - MyApp::DB::Frob->delete({foo=>'bart'}); + MyApp::DB::Album->delete({ artist => 'Falco' }); =head2 Finding your objects. DBIx::Class provides a few different ways to retrieve data from your database. The simplest looks something like this: - $rs=MyApp::DB::Frob->search(foo=>'bart'); + $album = MyApp::DB::Album->search( artist => 'Santana' ); -note that all the search methods return a recordset in scalar context or -a list containing all the elements in list context. +note that all the search methods return a L object +in scalar context or a list containing all the records in list context. -We also provide a handy shortcut for doing a like search: +We also provide a handy shortcut for doing a "like" search: - $rs=MyApp::DB::Frob->search_like(foo=>'bar%'); + $album = MyApp::DB::Album->search_like( artist => 'Jimi%'); Or you can provide your own handmade WHERE clause, like - $rs=MyApp::DB::Frob->search_literal('foo=?','bart'); + $album = MyApp::DB::Album->search_literal('artist=?','Peter Frampton'); The other way to provide more complex queries, is to provide a L construct to search: - $rs=MyApp::DB::Frob->search({ - bar=>{'>' => 10 }, - foo=>{'!=','bart'}, - id => [1,14,15,65,43] + $album = MyApp::DB::Album->search({ + artist => { '!=', 'Janis Joplin' }, + year => { '<' => 1980 }, + id => [ 1, 14, 15, 65, 43 ] }); The search can also be modifyed by passing another hash with attributes: - $rs=MyApp::DB::Frob->search( {foo=>'bart'}, - { page=>1, rows=>2, order_by=>'bar' } ); + $album = MyApp::DB::Album->search( + { artist => 'Bob Marley' }, + { page => 1, rows => 2, order_by => 'year' } + ); For a complete overview over the available attributes, see L diff --git a/lib/DBIx/Class/PK/Auto.pm b/lib/DBIx/Class/PK/Auto.pm index 2c368a6..94a65f8 100644 --- a/lib/DBIx/Class/PK/Auto.pm +++ b/lib/DBIx/Class/PK/Auto.pm @@ -35,7 +35,7 @@ sub insert { # if all primaries are already populated, skip auto-inc my $populated = 0; - map { $populated++ if $self->$_ } $self->primary_columns; + map { $populated++ if $self->has_column($_) } $self->primary_columns; return $ret if ( $populated == scalar $self->primary_columns ); my ($pri, $too_many) = diff --git a/lib/DBIx/Class/PK/Auto/Pg.pm b/lib/DBIx/Class/PK/Auto/Pg.pm index 52185e5..ab401f8 100644 --- a/lib/DBIx/Class/PK/Auto/Pg.pm +++ b/lib/DBIx/Class/PK/Auto/Pg.pm @@ -27,7 +27,7 @@ sub get_autoinc_seq { while (my $foo = $sth->fetchrow_arrayref){ if(defined $foo->[12] && $foo->[12] =~ /^nextval/) { ($self->{_autoinc_seq}) = $foo->[12] =~ - m!^nextval\('"?([^"']+)"?'::text\)!; + m!^nextval\('"?([^"']+)"?'::(?:text|regclass)\)!; } } }