From: Daniel Westermann-Clark Date: Sat, 7 Jan 2006 21:47:04 +0000 (+0000) Subject: - Clean up indentation in Manual X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=40dbc10813c6f5bd0a91a08b5e00d1027c390c0c;p=dbsrgits%2FDBIx-Class-Historic.git - Clean up indentation in Manual - Add SEE ALSO sections - Add examples of complex queries to Cookbook --- diff --git a/lib/DBIx/Class/Manual/Cookbook.pod b/lib/DBIx/Class/Manual/Cookbook.pod index c1fd262..bc9d12c 100644 --- a/lib/DBIx/Class/Manual/Cookbook.pod +++ b/lib/DBIx/Class/Manual/Cookbook.pod @@ -1,18 +1,47 @@ =head1 NAME -DBIx::Class::Manual::Cookbook - Misc recipes +DBIx::Class::Manual::Cookbook - Miscellaneous recipes -=head1 DESCRIPTION +=head1 RECIPES -Things that could be handy +=head2 Complex searches -=head1 RECIPES +Sometimes you need to formulate a query using specific operators: + + my @albums = MyApp::DB::Album->search({ + artist => { 'like', '%Lamb%' }, + title => { 'like', '%Fear of Fours%' }, + }); + +This results in something like the following C clause: + + WHERE artist LIKE '%Lamb%' AND title LIKE '%Fear of Fours%' + +Other queries might require slightly more complex logic: + + my @albums = MyApp::DB::Album->search({ + -or => [ + -and => [ + artist => { 'like', '%Smashing Pumpkins%' }, + title => 'Siamese Dream', + ], + artist => 'Starchildren', + ], + }); + +This results in the following C clause: + + WHERE ( artist LIKE '%Smashing Pumpkins%' AND title = 'Siamese Dream' ) + OR artist = 'Starchildren' + +For more information on generating complex queries, see +L. =head2 Disconnecting cleanly -If you find yourself quitting an app with Control-C a lot during development, -you might like to put the following signal handler in your main database -class to make sure it disconnects cleanly: +If you find yourself quitting an app with Control-C a lot during +development, you might like to put the following signal handler in +your main database class to make sure it disconnects cleanly: $SIG{INT} = sub { __PACKAGE__->storage->dbh->disconnect; @@ -20,113 +49,122 @@ class to make sure it disconnects cleanly: =head2 Using joins and prefetch -See L. +See L. =head2 Transactions As of version 0.04001, there is improved transaction support in -L. Here is an example of the recommended way to use it: +L. Here is an example of the recommended +way to use it: - my $obj = Genus->find(12); + my $genus = Genus->find(12); eval { MyDB->txn_begin; - $obj->add_to_species({ name => 'troglodyte' }); - $obj->wings(2); - $obj->update; - cromulate($obj); # can have a nested transation + $genus->add_to_species({ name => 'troglodyte' }); + $genus->wings(2); + $genus->update; + cromulate($genus); # Can have a nested transation MyDB->txn_commit; }; - if ($@) { eval { MyDB->txn_rollback } } # rollback might fail, too + if ($@) { + # Rollback might fail, too + eval { + MyDB->txn_rollback + }; + } -Currently, a nested commit will do nothing and a nested rollback will die. -The code at each level must be sure to call rollback in the case of an error, -to ensure that the rollback will propagate to the top level and be issued. -Support for savepoints and for true nested transactions (for databases that -support them) will hopefully be added in the future. +Currently, a nested commit will do nothing and a nested rollback will +die. The code at each level must be sure to call rollback in the case +of an error, to ensure that the rollback will propagate to the top +level and be issued. Support for savepoints and for true nested +transactions (for databases that support them) will hopefully be added +in the future. =head2 Many-to-many relationships -This is not as easy as it could be, but it's possible. Here's an example to -illustrate: - - # 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 +This is not as easy as it could be, but it's possible. Here's an +example to illustrate: + + # 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'); + + + # Returns an author record where the bookID field of the + # book2author table equals the bookID of the books (using the + # bookID relationship table) + sub authors { + my ($self) = @_; + return MyApp::DBIC::Author->search( + { 'b2a.bookID' => $self->bookID }, # WHERE clause + { join => 'b2a' } # JOIN condition + ); + } =head2 Setting default values -It's as simple as overriding the C method. Note the use of C. +It's as simple as overriding the C method. Note the use of +C. sub new { - my( $class, $attrs ) = @_; - - $attrs->{ foo } = 'bar' unless defined $attrs->{ foo }; - - $class->next::method( $attrs ); + my ( $class, $attrs ) = @_; + + $attrs->{foo} = 'bar' unless defined $attrs->{foo}; + + $class->next::method($attrs); } =head2 Stringification -Deploy the standard stringification technique by using the C module. Replace -C with the column/method of your choice. +Employ the standard stringification technique by using the C +module. Replace C with the column/method of your choice. use overload '""' => 'foo', fallback => 1; -=back +=cut diff --git a/lib/DBIx/Class/Manual/FAQ.pod b/lib/DBIx/Class/Manual/FAQ.pod index 67cdaef..131f4a0 100644 --- a/lib/DBIx/Class/Manual/FAQ.pod +++ b/lib/DBIx/Class/Manual/FAQ.pod @@ -1,20 +1,18 @@ =head1 NAME -DBIx::Class::Manual::FAQ - Frequently Asked Questions +DBIx::Class::Manual::FAQ - Frequently asked questions -=head1 General +=head1 GENERAL =head2 What is the point of this module? Is it a fork of Class::DBI? -This is an alternative to Class::DBI, intended to provide greater +This is an alternative to L, intended to provide greater functionality and simplicity. -It is inspired by the Class::DBI framework, and meant to support +It is inspired by the L framework, and meant to support compability with it, while restructuring the internals and making it -possible to support some new features like self-joins, distinct, group -bys and more. - -=head2 Who's the intended audience for this module? +possible to support some new features like self-joins, C, +Cs and more. =head2 What databases does it support? @@ -29,32 +27,38 @@ we're trying to make, we will, and any non-compatible changes will merit a full justification on the mailing list and a CPAN developer release for people to test against. -=head2 What's planned in the future? - =head2 Where can I go for support? - Mailing list: http://lists.rawmode.org/mailman/listinfo/dbix-class/ + Mailing list: http://lists.rawmode.org/mailman/listinfo/dbix-class/ - SVN: http://dev.catalyst.perl.org/repos/bast/trunk/DBIx-Class/ + SVN: http://dev.catalyst.perl.org/repos/bast/trunk/DBIx-Class/ - Wiki: http://dbix-class.shadowcatsystems.co.uk/ + Wiki: http://dbix-class.shadowcatsystems.co.uk/ - IRC: irc.perl.org#dbix-class + IRC: irc.perl.org#dbix-class -=head1 PostgresQL Specific Problems +=head1 POSTGRESQL-SPECIFIC PROBLEMS -=head2 Can't get last insert id - inserts with serial primary keys fail +=head2 Can't get last insert ID; inserts with serial primary keys fail -Older DBI and DBD::Pg versions fail to correctly handle -C correctly, causing code that uses auto incrementing -primary key columns to fail with a message such as:- +Older L and L versions do not handle C +correctly, causing code that uses auto-incrementing primary key +columns to fail with a message such as: - Can't get last insert id at /.../DBIx/Class/Row.pm line 95 + Can't get last insert id at /.../DBIx/Class/Row.pm line 95 In particular the RHEL 4 and FC3 Linux distributions both ship with -combinations of DBI and DBD::Pg modules that do not work correctly. +combinations of L and L modules that do not work +correctly. -DBI version 1.50 and DBD::Pg 1.43 are known to work. +L version 1.50 and L 1.43 are known to work. -=cut +=head1 SEE ALSO + +=over 4 +=item L + +=back + +=cut diff --git a/lib/DBIx/Class/Manual/Intro.pod b/lib/DBIx/Class/Manual/Intro.pod index 556c552..6003489 100644 --- a/lib/DBIx/Class/Manual/Intro.pod +++ b/lib/DBIx/Class/Manual/Intro.pod @@ -2,183 +2,204 @@ DBIx::Class::Manual::Intro - Introduction to DBIx::Class -=head1 Introduction. +=head1 INTRODUCTION -So, you are bored with SQL, and want a native perl interface for your classes? -Or you've been doing this for a while with L, and think there's -a better way? You've come to the right place. Let's look at how you can set -and use your first native DBIx::Class tree. +So, you are bored with SQL, and want a native Perl interface for your +database? Or you've been doing this for a while with L, +and think there's a better way? You've come to the right place. Let's +look at how you can set and use your first native L tree. -First we'll see how you can set up your classes yourself. If you want them -to be auto-discovered, just skip to the next section, which shows you how -to use DBIx::Class::Loader. +First we'll see how you can set up your classes yourself. If you want +them to be auto-discovered, just skip to the next section, which shows +you how to use L. =head2 Setting it up manually First, you'll need a base class. It should inherit from DBIx::Class like this: - package MyApp::DB - use base qw/DBIx::Class/; + package MyApp::DB; + use base qw/DBIx::Class/; -You will also want to load some of L's components. -L provides a good basic set. In addition you'll +You will also want to load some of L's components. +L provides a good basic set. In addition you'll have to use either L or L We'll -use DB in this introduction, since it involves less magic. Schema is -mostly useful if you want to use multiple database connections. +use C in this introduction, since it involves less magic. +L is mostly useful if you want to use multiple database +connections. - __PACKAGE__->load_components(qw/Core DB/); + __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 -PK::Auto::* modules help L keep up with newly generated -keys in auto increment database fields. +the apropriate component for your db as well, for example. The +L modules help L keep up with +newly generated keys in auto increment database fields. - __PACKAGE__->load_components(qw/PK::Auto::SQLite Core DB/); + __PACKAGE__->load_components(qw/PK::Auto::SQLite Core DB/); Once you've loaded the components, it's time to set up your connection: - __PACKAGE__->connection('dbi:SQLite:/home/me/myapp/my.db'); + __PACKAGE__->connection('dbi:SQLite:/home/me/myapp/my.db'); -This method is similar to the normal L, and can take user/pass/dbi -attribute hash as well as the dsn. +This method is similar to the normal L, and can take username, +password, and L attribute hash as well as the DSN. With that out of the way, we can define our first table class: - package MyApp::DB::Album; - - use base qw/MyApp::DB/; + package MyApp::DB::Album; + use base qw/MyApp::DB/; Then we specify which table it uses, - __PACKAGE__->table('album'); + __PACKAGE__->table('album'); and specify which columns it has. - __PACKAGE__->add_columns(qw/albumID artist title label year/); + __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. +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('albumID'); + __PACKAGE__->set_primary_key('albumID'); If you have multiple primary keys, just pass a list instead. -That's pretty much all you need for a basic setup. If you have more advanced -needs like using more than 1 database connections for the same class, see -L. +That's pretty much all you need for a basic setup. If you have more +advanced needs like using more than one database connection for the +same class, see L. -=head2 Using L. +=head2 Using L -This is an additional class, and not part of the DBIx::Class distribution. -Like L, it inspects your database, and automatically -creates classes for all the tables in your database. Here's a simple setup: +This is an additional class, and not part of the L +distribution. Like L, it inspects your database, +and automatically creates classes for all the tables in your +database. Here's a simple setup: - package MyApp::DB; - - use DBIx::Class::Loader; + package MyApp::DB; + 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; + 1; -This should be equivalent to the manual in the section above. -L takes lots of other options. For more information, -consult the reference documentation. +This should be equivalent to the manual in the section above. +L takes lots of other options. For more +information, consult its documentation. -=head2 Basic Usage +=head2 Basic usage -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: +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: - $albumID = 14; - $album = MyApp::DB::Album->find($albumID); + my $albumID = 14; + my $album = MyApp::DB::Album->find($albumID); -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 +This will run a select with C in the C clause, +and return an instance of C that represents this +row. Once you have that row, you can access and update columns: - $album->title('Physical Graffiti'); - $title = $album->title; # $title holds 'Physical Graffiti' + $album->title('Physical Graffiti'); + my $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. +If you prefer, you can use the C and C +accessors instead: -Just like with L, you do an 'update' to commit your changes -to the database: + $album->set_column('title', 'Presence'); + $title = $album->get_column('title'); - $album->update; +Just like with L, you do an C to commit your +changes to the database: + + $album->update; If needed, you can drop your local changes instead like this: - $album->discard_changes if $album->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. +As you can see, C allows you to check if there are local +changes to your object. -=head2 Adding and removing rows. +=head2 Adding and removing rows -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. +To create a new record in the database, you can use the C +method from L. It returns a +L object that can be used to access the data +in the new record. - $new_album = MyApp::DB::Album->create({ - title => 'Wish You Were Here', - artist => 'Pink Floyd' - }); + my $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'); + $new_album->label('Capitol'); + $new_album->year('1975'); -likewise, you can remove if from the database like this: +Likewise, you can remove if from the database like this: - $new_album->delete(); + $new_album->delete; -or even without retrieving first. This operation takes the same kind of -arguments as a search. +or even without retrieving first. This operation takes the same kind +of arguments as a search. - MyApp::DB::Album->delete({ artist => 'Falco' }); + MyApp::DB::Album->delete({ artist => 'Falco' }); -=head2 Finding your objects. +=head2 Finding your objects -DBIx::Class provides a few different ways to retrieve data from your database. -The simplest looks something like this: +L provides a few different ways to retrieve data from +your database. The simplest looks something like this: - $album = MyApp::DB::Album->search( artist => 'Santana' ); + my $album = MyApp::DB::Album->search( artist => 'Santana' ); -note that all the search methods return a L object -in scalar context or a list containing all the records 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 C search: - $album = MyApp::DB::Album->search_like( artist => 'Jimi%'); + my $album = MyApp::DB::Album->search_like( artist => 'Jimi%' ); -Or you can provide your own handmade WHERE clause, like +Or you can provide your own handmade C clause, like: - $album = MyApp::DB::Album->search_literal('artist=?','Peter Frampton'); + my $album = MyApp::DB::Album->search_literal( 'artist = ?', 'Peter Frampton' ); + +The preferred way to generate complex queries is to provide a +L construct to C: + + my $album = MyApp::DB::Album->search({ + artist => { '!=', 'Janis Joplin' }, + year => { '<' => 1980 }, + id => [ 1, 14, 15, 65, 43 ] + }); + +For more examples of complex searches, see +L. + +The search can also be modified by passing another hash with +attributes: + + my $album = MyApp::DB::Album->search( + { artist => 'Bob Marley' }, + { page => 1, rows => 2, order_by => 'year' } + ); + +For a complete overview of the available attributes, see +L. -The other way to provide more complex queries, is to provide a -L construct to search: +=head1 SEE ALSO - $album = MyApp::DB::Album->search({ - artist => { '!=', 'Janis Joplin' }, - year => { '<' => 1980 }, - id => [ 1, 14, 15, 65, 43 ] - }); +=over 4 -The search can also be modifyed by passing another hash with attributes: +=item * L - $album = MyApp::DB::Album->search( - { artist => 'Bob Marley' }, - { page => 1, rows => 2, order_by => 'year' } - ); +=item * L -For a complete overview over the available attributes, see -L +=back =cut diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 6364054..6ca976b 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -359,7 +359,7 @@ sub page { return $self->new($self->{source}, $attrs); } -=head1 Attributes +=head1 ATTRIBUTES The resultset takes various attributes that modify its behavior. Here's an overview of them: