From: Matt S Trout Date: Sat, 18 Mar 2006 23:12:21 +0000 (+0000) Subject: Merge 'DBIx-Class-current' into 'trunk' X-Git-Tag: v0.06000~60 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=7daf649db5e644ea6d26a12f2caba1582bed6224;hp=c17c525c5db20008c195405199271113a53cd289;p=dbsrgits%2FDBIx-Class.git Merge 'DBIx-Class-current' into 'trunk' --- diff --git a/Changes b/Changes index ab6d6fb..7e4682e 100644 --- a/Changes +++ b/Changes @@ -59,7 +59,8 @@ Revision history for DBIx::Class keys of the related table are not fetched - fix count for group_by as scalar - add horrific fix to make Oracle's retarded limit syntax work - - remove Carp require + - changed UUIDColumns to use new UUIDMaker classes for uuid creation + using whatever module may be available 0.05003 2006-02-08 17:50:20 - add component_class accessors and use them for *_class diff --git a/lib/DBIx/Class/Manual/Example.pod b/lib/DBIx/Class/Manual/Example.pod new file mode 100644 index 0000000..365896e --- /dev/null +++ b/lib/DBIx/Class/Manual/Example.pod @@ -0,0 +1,293 @@ +=head1 NAME + +DBIx::Class::Manual::Example - Simple CD database example + +=head1 DESCRIPTION + +This tutorial will guide you through the proeccess of setting up and testing a very basic CD database using Mysql, 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 + +=head3 Create the database/tables and populate them with a few records + + CREATE DATABASE cdtestdb ; + USE cdtestdb; + + CREATE TABLE artist ( + artistid INT NOT NULL AUTO_INCREMENT , + name CHAR( 40 ) NOT NULL , + PRIMARY KEY ( artistid ) + ); + + CREATE TABLE cd ( + cdid INT NOT NULL AUTO_INCREMENT , + artist INT NOT NULL , + title CHAR( 40 ) NOT NULL , + PRIMARY KEY ( cdid ) + ); + + CREATE TABLE track ( + trackid INT NOT NULL AUTO_INCREMENT , + cd INT NOT NULL , + title CHAR( 40 ) NOT NULL , + PRIMARY KEY ( trackid ) + ; + + + INSERT INTO artist VALUES + (NULL,'Michael Jackson'), + (NULL,'Eminem'); + + INSERT INTO cd VALUES + (NULL,'1','Thriller'), + (NULL,'1','Bad'), + (NULL,'2','The Marshall Mathers LP'); + + INSERT INTO track VALUES + (NULL,'1','Beat it'), + (NULL,'1','Billie Jean'), + (NULL,'2','Dirty Diana'), + (NULL,'2','Smooth Criminal'), + (NULL,'2','Leave Me Alone'), + (NULL,'3','Stan'), + (NULL,'3','The Way I Am'); + + + +=head3 Set up DBIx::Class::Schema + +First, create some dirs and change working directory: + + mkdir app + mkdir app/DB + mkdir app/DB/Main + cd app + + +Then, create the following DBIx::Class::Schema classes: + +DB/Main.pm: + + package DB::Main; + use base qw/DBIx::Class::Schema/; + __PACKAGE__->load_classes(qw/Artist CD Track/); + + 1; + + +DB/Main/Artist.pm: + + package DB::Main::Artist; + use base qw/DBIx::Class/; + __PACKAGE__->load_components(qw/Core/); + __PACKAGE__->table('artist'); + __PACKAGE__->add_columns(qw/ artistid name /); + __PACKAGE__->set_primary_key('artistid'); + __PACKAGE__->has_many('cds' => 'DB::Main::CD'); + + 1; + + +DB/Main/CD.pm: + + package DB::Main::CD; + use base qw/DBIx::Class/; + __PACKAGE__->load_components(qw/Core/); + __PACKAGE__->table('cd'); + __PACKAGE__->add_columns(qw/ cdid artist title/); + __PACKAGE__->set_primary_key('cdid'); + __PACKAGE__->belongs_to('artist' => 'DB::Main::Artist'); + __PACKAGE__->has_many('tracks' => 'DB::Main::Track'); + + 1; + + +DB/Main/Track.pm: + + package DB::Main::Track; + use base qw/DBIx::Class/; + __PACKAGE__->load_components(qw/Core/); + __PACKAGE__->table('track'); + __PACKAGE__->add_columns(qw/ trackid cd title/); + __PACKAGE__->set_primary_key('trackid'); + __PACKAGE__->belongs_to('cd' => 'DB::Main::CD'); + + 1; + + +=head3 Create and run the test script + +testdb.pl: + + #!/usr/bin/perl -w + + use DB::Main; + use strict; + + my $schema = DB::Main->connect('dbi:mysql:cdtestdb', 'testuser', 'testpass'); + + 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 AUTHOR + + sc_ + +=cut diff --git a/lib/DBIx/Class/Schema.pm b/lib/DBIx/Class/Schema.pm index d5c0658..33ac06e 100644 --- a/lib/DBIx/Class/Schema.pm +++ b/lib/DBIx/Class/Schema.pm @@ -389,13 +389,12 @@ sub txn_rollback { shift->storage->txn_rollback } =head2 txn_do -=head3 Arguments: <$coderef>, [@coderef_args] +=head3 Arguments: , [@coderef_args] -Executes C<$coderef> with (optional) arguments C<@coderef_args> -transactionally, returning its result (if any). If an exception is -caught, a rollback is issued and the exception is rethrown. If the -rollback fails, (i.e. throws an exception) an exception is thrown that -includes a "Rollback failed" message. +Executes with (optional) arguments <@coderef_args> transactionally, +returning its result (if any). If an exception is caught, a rollback is issued +and the exception is rethrown. If the rollback fails, (i.e. throws an +exception) an exception is thrown that includes a "Rollback failed" message. For example, @@ -427,7 +426,7 @@ For example, } } -Nested transactions work as expected (i.e. only the outermost +Nested transactions should work as expected (i.e. only the outermost transaction will issue a txn_commit on the Schema's storage) =cut diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index 3a7d978..6da680b 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -149,16 +149,7 @@ sub _join_condition { sub _quote { my ($self, $label) = @_; return '' unless defined $label; - return "*" if $label eq '*'; return $label unless $self->{quote_char}; - if(ref $self->{quote_char} eq "ARRAY"){ - return $self->{quote_char}->[0] . $label . $self->{quote_char}->[1] - if !defined $self->{name_sep}; - my $sep = $self->{name_sep}; - return join($self->{name_sep}, - map { $self->{quote_char}->[0] . $_ . $self->{quote_char}->[1] } - split(/\Q$sep\E/,$label)); - } return $self->SUPER::_quote($label); } diff --git a/lib/DBIx/Class/UUIDColumns.pm b/lib/DBIx/Class/UUIDColumns.pm index 1853145..c15dd1a 100644 --- a/lib/DBIx/Class/UUIDColumns.pm +++ b/lib/DBIx/Class/UUIDColumns.pm @@ -145,13 +145,13 @@ sub get_uuid { } sub _find_uuid_module { - if ($^O ne 'openbsd' && eval{require APR::UUID}) { + if (eval{require Data::UUID}) { + return '::Data::UUID'; + } elsif ($^O ne 'openbsd' && eval{require APR::UUID}) { # APR::UUID on openbsd causes some as yet unfound nastyness for XS return '::APR::UUID'; } elsif (eval{require UUID}) { return '::UUID'; - } elsif (eval{require Data::UUID}) { - return '::Data::UUID'; } elsif (eval{ # squelch the 'too late for INIT' warning in Win32::API::Type local $^W = 0; @@ -165,6 +165,78 @@ sub _find_uuid_module { }; }; +1; +__END__ + +=head1 NAME + +DBIx::Class::UUIDColumns - Implicit uuid columns + +=head1 SYNOPSIS + + package Artist; + __PACKAGE__->load_components(qw/UUIDColumns Core DB/); + __PACKAGE__->uuid_columns( 'artist_id' ); + +=head1 DESCRIPTION + +This L component resembles the behaviour of +L, to make some columns implicitly created as uuid. + +When loaded, C will search for a suitable uuid generation module +from the following list of supported modules: + + Data::UUID + APR::UUID* + UUID + Win32::Guidgen + Win32API::GUID + +If no supporting module can be found, an exception will be thrown. + +*APR::UUID will not be loaded under OpenBSD due to an as yet unidentified XS +issue. + +If you would like to use a specific module, you can set C: + + __PACKAGE__->uuid_class('::Data::UUID'); + __PACKAGE__->uuid_class('MyUUIDGenerator'); + +Note that the component needs to be loaded before Core. + +=head1 METHODS + +=head2 uuid_columns(@columns) + +Takes a list of columns to be filled with uuids during insert. + + __PACKAGE__->uuid_columns('id'); + +=head2 uuid_class($classname) + +Takes the name of a UUIDMaker subclass to be used for uuid value generation. +This can be a fully qualified class name, or a shortcut name starting with :: +that matches one of the available DBIx::Class::UUIDMaker subclasses: + + __PACKAGE__->uuid_class('CustomUUIDGenerator'); + # loads CustomeUUIDGenerator + + __PACKAGE->uuid_class('::Data::UUID'); + # loads DBIx::Class::UUIDMaker::Data::UUID; + +Note that C chacks to see that the specified class isa +DBIx::Class::UUIDMaker subbclass and throws and exception if it isn't. + +=head2 uuid_maker + +Returns the current UUIDMaker instance for the given module. + + my $uuid = __PACKAGE__->uuid_maker->as_string; + +=head1 SEE ALSO + +L + =head1 AUTHORS Chia-liang Kao diff --git a/lib/DBIx/Class/UUIDColumns.pm~ b/lib/DBIx/Class/UUIDColumns.pm~ deleted file mode 100644 index 1873c90..0000000 --- a/lib/DBIx/Class/UUIDColumns.pm~ +++ /dev/null @@ -1,63 +0,0 @@ -package DBIx::Class::UUIDColumns; -use base qw/DBIx::Class/; - -use Data::UUID; - -__PACKAGE__->mk_classdata( 'uuid_auto_columns' => [] ); - -=head1 NAME - -DBIx::Class::UUIDColumns - Implicit uuid columns - -=head1 SYNOPSIS - - pacakge Artist; - __PACKAGE__->load_components(qw/UUIDColumns Core DB/); - __PACKAGE__->uuid_columns( 'artist_id' );x - -=head1 DESCRIPTION - -This L component resambles the behaviour of -L, to make some columns implicitly created as uuid. - -Note that the component needs to be loaded before Core. - -=head1 METHODS - -=head2 uuid_columns - -=cut - -# be compatible with Class::DBI::UUID -sub uuid_columns { - my $self = shift; - for (@_) { - $self->throw_exception("column $_ doesn't exist") unless $self->has_column($_); - } - $self->uuid_auto_columns(\@_); -} - -sub insert { - my $self = shift; - for my $column (@{$self->uuid_auto_columns}) { - $self->store_column( $column, $self->get_uuid ) - unless defined $self->get_column( $column ); - } - $self->next::method(@_); -} - -sub get_uuid { - return Data::UUID->new->to_string(Data::UUID->new->create), -} - -=head1 AUTHORS - -Chia-liang Kao - -=head1 LICENSE - -You may distribute this code under the same terms as Perl itself. - -=cut - -1; diff --git a/lib/DBIx/Class/UUIDMaker.pm b/lib/DBIx/Class/UUIDMaker.pm index 67061ad..b9c196c 100644 --- a/lib/DBIx/Class/UUIDMaker.pm +++ b/lib/DBIx/Class/UUIDMaker.pm @@ -9,3 +9,48 @@ sub as_string { }; 1; +__END__ + +=head1 NAME + +DBIx::Class::UUIDMaker - UUID wrapper module + +=head1 SYNOPSIS + + package CustomUUIDMaker; + use base qw/DBIx::Class::/; + + sub as_string { + my $uuid; + ...magic encantations... + return $uuid; + }; + +=head1 DESCRIPTION + +DBIx::Class::UUIDMaker is a base class used by the various uuid generation +subclasses. + +=head1 METHODS + +=head2 as_string + +Returns the new uuid as a string. + +=head1 SEE ALSO + +L, +L, +L, +L, +L, +L, +L + +=head1 AUTHOR + +Chris Laco + +=head1 LICENSE + +You may distribute this code under the same terms as Perl itself. diff --git a/lib/DBIx/Class/UUIDMaker/APR/UUID.pm b/lib/DBIx/Class/UUIDMaker/APR/UUID.pm index 65305f0..136ec5f 100644 --- a/lib/DBIx/Class/UUIDMaker/APR/UUID.pm +++ b/lib/DBIx/Class/UUIDMaker/APR/UUID.pm @@ -7,3 +7,40 @@ sub as_string { }; 1; +__END__ + +=head1 NAME + +DBIx::Class::UUIDMaker::APR::UUID - Create uuids using APR::UUID + +=head1 SYNOPSIS + + package Artist; + __PACKAGE__->load_components(qw/UUIDColumns Core DB/); + __PACKAGE__->uuid_columns( 'artist_id' ); + __PACKAGE__->uuid_class('::APR::UUID'); + +=head1 DESCRIPTION + +This DBIx::Class::UUIDMaker subclass uses APR::UUID to generate uuid +strings in the following format: + + 098f2470-bae0-11cd-b579-08002b30bfeb + +=head1 METHODS + +=head2 as_string + +Returns the new uuid as a string. + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Chris Laco + +=head1 LICENSE + +You may distribute this code under the same terms as Perl itself. diff --git a/lib/DBIx/Class/UUIDMaker/Data/UUID.pm b/lib/DBIx/Class/UUIDMaker/Data/UUID.pm index ffa1afb..820669c 100644 --- a/lib/DBIx/Class/UUIDMaker/Data/UUID.pm +++ b/lib/DBIx/Class/UUIDMaker/Data/UUID.pm @@ -7,3 +7,40 @@ sub as_string { }; 1; +__END__ + +=head1 NAME + +DBIx::Class::UUIDMaker::Data::UUID - Create uuids using Data::UUID + +=head1 SYNOPSIS + + package Artist; + __PACKAGE__->load_components(qw/UUIDColumns Core DB/); + __PACKAGE__->uuid_columns( 'artist_id' ); + __PACKAGE__->uuid_class('::Data::UUID'); + +=head1 DESCRIPTION + +This DBIx::Class::UUIDMaker subclass uses Data::UUID to generate uuid +strings in the following format: + + 098f2470-bae0-11cd-b579-08002b30bfeb + +=head1 METHODS + +=head2 as_string + +Returns the new uuid as a string. + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Chris Laco + +=head1 LICENSE + +You may distribute this code under the same terms as Perl itself. diff --git a/lib/DBIx/Class/UUIDMaker/Data/Uniqid.pm b/lib/DBIx/Class/UUIDMaker/Data/Uniqid.pm index 61bf347..8d9a29d 100644 --- a/lib/DBIx/Class/UUIDMaker/Data/Uniqid.pm +++ b/lib/DBIx/Class/UUIDMaker/Data/Uniqid.pm @@ -7,3 +7,38 @@ sub as_string { }; 1; +__END__ + +=head1 NAME + +DBIx::Class::UUIDMaker::Data::Uniqid - Create uuids using Data::Uniqid + +=head1 SYNOPSIS + + package Artist; + __PACKAGE__->load_components(qw/UUIDColumns Core DB/); + __PACKAGE__->uuid_columns( 'artist_id' ); + __PACKAGE__->uuid_class('::Data::Uniqid'); + +=head1 DESCRIPTION + +This DBIx::Class::UUIDMaker subclass uses Data::Uniqid to generate uuid +strings using Data::Uniqid::luniqid. + +=head1 METHODS + +=head2 as_string + +Returns the new uuid as a string. + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Chris Laco + +=head1 LICENSE + +You may distribute this code under the same terms as Perl itself. diff --git a/lib/DBIx/Class/UUIDMaker/UUID.pm b/lib/DBIx/Class/UUIDMaker/UUID.pm index 28a34b9..7a647a9 100644 --- a/lib/DBIx/Class/UUIDMaker/UUID.pm +++ b/lib/DBIx/Class/UUIDMaker/UUID.pm @@ -11,3 +11,40 @@ sub as_string { }; 1; +__END__ + +=head1 NAME + +DBIx::Class::UUIDMaker::UUID - Create uuids using UUID + +=head1 SYNOPSIS + + package Artist; + __PACKAGE__->load_components(qw/UUIDColumns Core DB/); + __PACKAGE__->uuid_columns( 'artist_id' ); + __PACKAGE__->uuid_class('::UUID'); + +=head1 DESCRIPTION + +This DBIx::Class::UUIDMaker subclass uses UUID to generate uuid +strings in the following format: + + 098f2470-bae0-11cd-b579-08002b30bfeb + +=head1 METHODS + +=head2 as_string + +Returns the new uuid as a string. + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Chris Laco + +=head1 LICENSE + +You may distribute this code under the same terms as Perl itself. diff --git a/lib/DBIx/Class/UUIDMaker/Win32/Guidgen.pm b/lib/DBIx/Class/UUIDMaker/Win32/Guidgen.pm index 9afa652..3c34b9a 100644 --- a/lib/DBIx/Class/UUIDMaker/Win32/Guidgen.pm +++ b/lib/DBIx/Class/UUIDMaker/Win32/Guidgen.pm @@ -4,9 +4,46 @@ use Win32::Guidgen (); sub as_string { my $uuid = Win32::Guidgen::create(); - $uuid =~ s/(^\{|\}$)//; + $uuid =~ s/(^\{|\}$)//g; return $uuid; }; 1; +__END__ + +=head1 NAME + +DBIx::Class::UUIDMaker::Win32:::Guidgen - Create uuids using Win32::Guidgen + +=head1 SYNOPSIS + + package Artist; + __PACKAGE__->load_components(qw/UUIDColumns Core DB/); + __PACKAGE__->uuid_columns( 'artist_id' ); + __PACKAGE__->uuid_class('::Win32::Guidgen'); + +=head1 DESCRIPTION + +This DBIx::Class::UUIDMaker subclass uses Win32::Guidgen to generate uuid +strings in the following format: + + 098f2470-bae0-11cd-b579-08002b30bfeb + +=head1 METHODS + +=head2 as_string + +Returns the new uuid as a string. + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Chris Laco + +=head1 LICENSE + +You may distribute this code under the same terms as Perl itself. diff --git a/lib/DBIx/Class/UUIDMaker/Win32API/GUID.pm b/lib/DBIx/Class/UUIDMaker/Win32API/GUID.pm index 463bbba..85caad1 100644 --- a/lib/DBIx/Class/UUIDMaker/Win32API/GUID.pm +++ b/lib/DBIx/Class/UUIDMaker/Win32API/GUID.pm @@ -7,3 +7,40 @@ sub as_string { }; 1; +__END__ + +=head1 NAME + +DBIx::Class::UUIDMaker::Win32API:::GUID - Create uuids using Win32API::GUID + +=head1 SYNOPSIS + + package Artist; + __PACKAGE__->load_components(qw/UUIDColumns Core DB/); + __PACKAGE__->uuid_columns( 'artist_id' ); + __PACKAGE__->uuid_class('::Win32API::GUID'); + +=head1 DESCRIPTION + +This DBIx::Class::UUIDMaker subclass uses Win32API::GUID to generate uuid +strings in the following format: + + 098f2470-bae0-11cd-b579-08002b30bfeb + +=head1 METHODS + +=head2 as_string + +Returns the new uuid as a string. + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Chris Laco + +=head1 LICENSE + +You may distribute this code under the same terms as Perl itself.