Merge 'DBIx-Class-C3' into 'trunk'
Matt S Trout [Wed, 16 Nov 2005 02:48:44 +0000 (02:48 +0000)]
lib/DBIx/Class/Manual/Cookbook.pod
lib/DBIx/Class/Manual/Intro.pod
lib/DBIx/Class/PK/Auto.pm
lib/DBIx/Class/PK/Auto/Pg.pm

index ee5ea22..1d2b4c6 100644 (file)
@@ -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
 
index cdb8144..556c552 100644 (file)
@@ -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<DBIx::Class> 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<Class::DBI>, 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<DBIx::Class::Row>
+To create a new record in the database, you can use the 'create' 
+method from L<DBIx::Class::Row>.  It returns a L<DBIx::Class::ResultSet>
+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<DBIx::Class::ResultSet> 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<SQL::Abstract> 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<DBIx::Class::ResultSet>
index 2c368a6..94a65f8 100644 (file)
@@ -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) =
index 52185e5..ab401f8 100644 (file)
@@ -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)\)!;
       }
     }
 }