X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FManual%2FCookbook.pod;h=3e5aa7b61870a9e8f4784c6e6399ad76ffd96c1a;hb=541df64afe67cde2a5cd2c48c1cb419298452a1f;hp=715c8f85e61a61f6878f271e1fc9f6bd5e0aac14;hpb=5e8b1b2adbc7b67dc7948a41354e36ce0c7998c6;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Manual/Cookbook.pod b/lib/DBIx/Class/Manual/Cookbook.pod index 715c8f8..3e5aa7b 100644 --- a/lib/DBIx/Class/Manual/Cookbook.pod +++ b/lib/DBIx/Class/Manual/Cookbook.pod @@ -70,10 +70,62 @@ This results in the following C clause: For more information on generating complex queries, see L. +=head3 Arbitrary SQL through a custom ResultSource + +Sometimes you have to run arbitrary SQL because your query is too complex +(e.g. it contains Unions, Sub-Selects, Stored Procedures, etc.) or has to +be optimized for your database in a special way, but you still want to +get the results as a L. +The recommended way to accomplish this is by defining a separate ResultSource +for your query. You can then inject complete SQL statements using a scalar +reference (this is a feature of L). + +Say you want to run a complex custom query on your user data, here's what +you have to add to your User class: + + package My::Schema::User; + + use base qw/DBIx::Class/; + + # ->load_components, ->table, ->add_columns, etc. + + # Make a new ResultSource based on the User class + my $source = __PACKAGE__->result_source_instance(); + my $new_source = $source->new( $source ); + $new_source->source_name( 'UserFriendsComplex' ); + + # Hand in your query as a scalar reference + # It will be added as a sub-select after FROM, + # so pay attention to the surrounding brackets! + $new_source->name( \<register_source( 'UserFriendsComplex' => $new_source ); + +Next, you can execute your complex query using bind parameters like this: + + my $friends = [ $schema->resultset( 'UserFriendsComplex' )->search( {}, + { + bind => [ 12345, 12345 ] + } + ) ]; + +... and you'll get back a perfect L. + =head3 Using specific columns -When you only want selected columns from a table, you can use C to -specify which ones you need: +When you only want specific columns from a table, you can use +C to specify which ones you need. This is useful to avoid +loading columns with large amounts of data that you aren't about to +use anyway: my $rs = $schema->resultset('Artist')->search( undef, @@ -85,6 +137,9 @@ specify which ones you need: # Equivalent SQL: # SELECT artist.name FROM artist +This is a shortcut for C and C. + =head3 Using database functions or stored procedures The combination of C attribute of C to force ordering). + +=head2 Want to know if find_or_create found or created a row? + +Just use C instead, then check C: + + my $obj = $rs->find_or_new({ blah => 'blarg' }); + unless ($obj->in_storage) { + $obj->insert; + # do whatever else you wanted if it was a new row + } + +=head3 Wrapping/overloading a column accessor + +Problem: Say you have a table "Camera" and want to associate a description +with each camera. For most cameras, you'll be able to generate the description from +the other columns. However, in a few special cases you may want to associate a +custom description with a camera. + +Solution: + +In your database schema, define a description field in the "Camera" table that +can contain text and null values. + +In DBIC, we'll overload the column accessor to provide a sane default if no +custom description is defined. The accessor will either return or generate the +description, depending on whether the field is null or not. + +First, in your "Camera" schema class, define the description field as follows: + + __PACKAGE__->add_columns(description => { accessor => '_description' }); + +Next, we'll define the accessor-wrapper subroutine: + + sub description { + my $self = shift; + + # If there is an update to the column, we'll let the original accessor + # deal with it. + return $self->_description(@_) if @_; + + # Fetch the column value. + my $description = $self->_description; + + # If there's something in the description field, then just return that. + return $description if defined $description && length $descripton; + + # Otherwise, generate a description. + return $self->generate_description; + } =cut