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
+++ /dev/null
-Build.PL
-Changes
-lib/DBIx/Class.pm
-lib/DBIx/Class/AccessorGroup.pm
-lib/DBIx/Class/CDBICompat.pm
-lib/DBIx/Class/CDBICompat/AccessorMapping.pm
-lib/DBIx/Class/CDBICompat/AttributeAPI.pm
-lib/DBIx/Class/CDBICompat/AutoUpdate.pm
-lib/DBIx/Class/CDBICompat/ColumnCase.pm
-lib/DBIx/Class/CDBICompat/ColumnGroups.pm
-lib/DBIx/Class/CDBICompat/Constraints.pm
-lib/DBIx/Class/CDBICompat/Constructor.pm
-lib/DBIx/Class/CDBICompat/DestroyWarning.pm
-lib/DBIx/Class/CDBICompat/GetSet.pm
-lib/DBIx/Class/CDBICompat/HasA.pm
-lib/DBIx/Class/CDBICompat/HasMany.pm
-lib/DBIx/Class/CDBICompat/ImaDBI.pm
-lib/DBIx/Class/CDBICompat/LazyLoading.pm
-lib/DBIx/Class/CDBICompat/LiveObjectIndex.pm
-lib/DBIx/Class/CDBICompat/MightHave.pm
-lib/DBIx/Class/CDBICompat/ObjIndexStubs.pm
-lib/DBIx/Class/CDBICompat/Pager.pm
-lib/DBIx/Class/CDBICompat/ReadOnly.pm
-lib/DBIx/Class/CDBICompat/Retrieve.pm
-lib/DBIx/Class/CDBICompat/Stringify.pm
-lib/DBIx/Class/CDBICompat/TempColumns.pm
-lib/DBIx/Class/CDBICompat/Triggers.pm
-lib/DBIx/Class/ClassResolver/PassThrough.pm
-lib/DBIx/Class/Componentised.pm
-lib/DBIx/Class/Core.pm
-lib/DBIx/Class/Cursor.pm
-lib/DBIx/Class/DB.pm
-lib/DBIx/Class/InflateColumn.pm
-lib/DBIx/Class/Manual.pod
-lib/DBIx/Class/Manual/Cookbook.pod
-lib/DBIx/Class/Manual/FAQ.pod
-lib/DBIx/Class/Manual/Glossary.pod
-lib/DBIx/Class/Manual/Intro.pod
-lib/DBIx/Class/Manual/SchemaIntro.pod
-lib/DBIx/Class/Manual/Troubleshooting.pod
-lib/DBIx/Class/PK.pm
-lib/DBIx/Class/PK/Auto.pm
-lib/DBIx/Class/PK/Auto/DB2.pm
-lib/DBIx/Class/PK/Auto/MSSQL.pm
-lib/DBIx/Class/PK/Auto/MySQL.pm
-lib/DBIx/Class/PK/Auto/Oracle.pm
-lib/DBIx/Class/PK/Auto/Pg.pm
-lib/DBIx/Class/PK/Auto/SQLite.pm
-lib/DBIx/Class/Relationship.pm
-lib/DBIx/Class/Relationship/Accessor.pm
-lib/DBIx/Class/Relationship/Base.pm
-lib/DBIx/Class/Relationship/BelongsTo.pm
-lib/DBIx/Class/Relationship/CascadeActions.pm
-lib/DBIx/Class/Relationship/HasMany.pm
-lib/DBIx/Class/Relationship/HasOne.pm
-lib/DBIx/Class/Relationship/Helpers.pm
-lib/DBIx/Class/Relationship/ManyToMany.pm
-lib/DBIx/Class/Relationship/ProxyMethods.pm
-lib/DBIx/Class/ResultSet.pm
-lib/DBIx/Class/ResultSetManager.pm
-lib/DBIx/Class/ResultSetProxy.pm
-lib/DBIx/Class/ResultSource.pm
-lib/DBIx/Class/ResultSource/Table.pm
-lib/DBIx/Class/ResultSourceProxy.pm
-lib/DBIx/Class/ResultSourceProxy/Table.pm
-lib/DBIx/Class/Row.pm
-lib/DBIx/Class/Schema.pm
-lib/DBIx/Class/Serialize/Storable.pm
-lib/DBIx/Class/Storage.pm
-lib/DBIx/Class/Storage/DBI.pm
-lib/DBIx/Class/Storage/DBI/Cursor.pm
-lib/DBIx/Class/Storage/DBI/DB2.pm
-lib/DBIx/Class/Storage/DBI/MSSQL.pm
-lib/DBIx/Class/Storage/DBI/mysql.pm
-lib/DBIx/Class/Storage/DBI/Oracle.pm
-lib/DBIx/Class/Storage/DBI/Pg.pm
-lib/DBIx/Class/Storage/DBI/SQLite.pm
-lib/DBIx/Class/Test/SQLite.pm
-lib/DBIx/Class/UUIDColumns.pm
-lib/DBIx/Class/UUIDMaker.pm
-lib/DBIx/Class/UUIDMaker/APR/UUID.pm
-lib/DBIx/Class/UUIDMaker/Data/Uniqid.pm
-lib/DBIx/Class/UUIDMaker/Data/UUID.pm
-lib/DBIx/Class/UUIDMaker/UUID.pm
-lib/DBIx/Class/UUIDMaker/Win32/Guidgen.pm
-lib/DBIx/Class/UUIDMaker/Win32API/GUID.pm
-lib/DBIx/Class/Validation.pm
-lib/SQL/Translator/Parser/DBIx/Class.pm
-lib/SQL/Translator/Producer/DBIx/Class/File.pm
-Makefile.PL
-MANIFEST This list of files
-README
-t/02pod.t
-t/03podcoverage.t.disabled
-t/04dont_break_c3.t
-t/18inserterror.t
-t/19quotes.t
-t/20setuperrors.t
-t/30dbicplain.t
-t/40resultsetmanager.t
-t/41orrible.t
-t/42toplimit.t
-t/50fork.t
-t/basicrels/01core.t
-t/basicrels/04db.t
-t/basicrels/05multipk.t
-t/basicrels/06relationship.t
-t/basicrels/07pager.t
-t/basicrels/08inflate.t
-t/basicrels/08inflate_has_a.t
-t/basicrels/09update.t
-t/basicrels/10auto.t
-t/basicrels/11mysql.t
-t/basicrels/12pg.t
-t/basicrels/13oracle.t
-t/basicrels/145db2.t
-t/basicrels/14mssql.t
-t/basicrels/15limit.t
-t/basicrels/16joins.t
-t/basicrels/17join_count.t
-t/basicrels/18self_referencial.t
-t/basicrels/19uuid.t
-t/basicrels/20unique.t
-t/basicrels/21serialize.t
-t/basicrels/22cascade_copy.t
-t/basicrels/23cache.t
-t/cdbi-sweet-t/08pager.t
-t/cdbi-t/01-columns.t
-t/cdbi-t/02-Film.t
-t/cdbi-t/03-subclassing.t
-t/cdbi-t/04-lazy.t
-t/cdbi-t/06-hasa.t
-t/cdbi-t/09-has_many.t
-t/cdbi-t/11-triggers.t
-t/cdbi-t/12-filter.t
-t/cdbi-t/13-constraint.t
-t/cdbi-t/14-might_have.t
-t/cdbi-t/15-accessor.t
-t/cdbi-t/16-reserved.t
-t/cdbi-t/18-has_a.t
-t/cdbi-t/19-set_sql.t
-t/cdbi-t/21-iterator.t
-t/cdbi-t/22-self_referential.t
-t/cdbi-t/30-pager.t
-t/cdbi-t/98-failure.t
-t/helperrels/01core.t
-t/helperrels/04db.t
-t/helperrels/05multipk.t
-t/helperrels/06relationship.t
-t/helperrels/07pager.t
-t/helperrels/08inflate.t
-t/helperrels/08inflate_has_a.t
-t/helperrels/09update.t
-t/helperrels/10auto.t
-t/helperrels/11mysql.t
-t/helperrels/12pg.t
-t/helperrels/13oracle.t
-t/helperrels/145db2.t
-t/helperrels/14mssql.t
-t/helperrels/15limit.t
-t/helperrels/16joins.t
-t/helperrels/17join_count.t
-t/helperrels/18self_referencial.t
-t/helperrels/19uuid.t
-t/helperrels/20unique.t
-t/helperrels/21transactions.t
-t/lib/DBICTest.pm
-t/lib/DBICTest/BasicRels.pm
-t/lib/DBICTest/Extra.pm
-t/lib/DBICTest/Extra/Foo.pm
-t/lib/DBICTest/HelperRels.pm
-t/lib/DBICTest/Plain.pm
-t/lib/DBICTest/Plain/Test.pm
-t/lib/DBICTest/Schema.pm
-t/lib/DBICTest/Schema/Artist.pm
-t/lib/DBICTest/Schema/ArtistUndirectedMap.pm
-t/lib/DBICTest/Schema/BasicRels.pm
-t/lib/DBICTest/Schema/CD.pm
-t/lib/DBICTest/Schema/CD_to_Producer.pm
-t/lib/DBICTest/Schema/FourKeys.pm
-t/lib/DBICTest/Schema/HelperRels.pm
-t/lib/DBICTest/Schema/LinerNotes.pm
-t/lib/DBICTest/Schema/OneKey.pm
-t/lib/DBICTest/Schema/Producer.pm
-t/lib/DBICTest/Schema/SelfRef.pm
-t/lib/DBICTest/Schema/SelfRefAlias.pm
-t/lib/DBICTest/Schema/Tag.pm
-t/lib/DBICTest/Schema/Track.pm
-t/lib/DBICTest/Schema/TreeLike.pm
-t/lib/DBICTest/Schema/TwoKeys.pm
-t/lib/DBICTest/Setup.pm
-t/lib/sqlite.sql
-t/run/01core.tl
-t/run/04db.tl
-t/run/05multipk.tl
-t/run/06relationship.tl
-t/run/07pager.tl
-t/run/08inflate.tl
-t/run/08inflate_has_a.tl
-t/run/09update.tl
-t/run/10auto.tl
-t/run/11mysql.tl
-t/run/12pg.tl
-t/run/13oracle.tl
-t/run/145db2.tl
-t/run/14mssql.tl
-t/run/15limit.tl
-t/run/16joins.tl
-t/run/17join_count.tl
-t/run/18self_referencial.tl
-t/run/19uuid.tl
-t/run/20unique.tl
-t/run/21transactions.tl
-t/testlib/Actor.pm
-t/testlib/ActorAlias.pm
-t/testlib/Binary.pm
-t/testlib/Blurb.pm
-t/testlib/CDBase.pm
-t/testlib/Director.pm
-t/testlib/Film.pm
-t/testlib/Lazy.pm
-t/testlib/Log.pm
-t/testlib/MyBase.pm
-t/testlib/MyFilm.pm
-t/testlib/MyFoo.pm
-t/testlib/MyStar.pm
-t/testlib/MyStarLink.pm
-t/testlib/MyStarLinkMCPK.pm
-t/testlib/Order.pm
-t/testlib/OtherFilm.pm
-t/testlib/PgBase.pm
-META.yml
=cut
__PACKAGE__->mk_classdata('class_resolver' =>
- 'DBIx::Class::ClassResolver::PassThrough');
+ 'DBIx::Class::ClassResolver::PassThrough');
=head2 connection
=cut
-sub txn_begin { $_[0]->schema_instance->txn_begin }
+sub txn_begin { shift->schema_instance->txn_begin(@_); }
=head2 txn_commit
=cut
-sub txn_commit { $_[0]->schema_instance->txn_commit }
+sub txn_commit { shift->schema_instance->txn_commit(@_); }
=head2 txn_rollback
=cut
-sub txn_rollback { $_[0]->schema_instance->txn_rollback }
+sub txn_rollback { shift->schema_instance->txn_rollback(@_); }
+
+=head2 txn_do
+
+Executes a block of code transactionally. If this code reference
+throws an exception, the transaction is rolled back and the exception
+is rethrown. See txn_do in L<DBIx::Class::Schema> for more details.
+
+=cut
+
+sub txn_do { shift->schema_instance->txn_do(@_); }
{
my $warn;
return $obj;
}
+sub update {
+ my ($class, $attrs, @rest) = @_;
+ $attrs ||= {};
+ foreach my $key (keys %$attrs) {
+ if (ref $attrs->{$key}
+ && exists $class->column_info($key)->{_inflate_info}) {
+ $attrs->{$key} = $class->_deflated_column($key, $attrs->{$key});
+ }
+ }
+ return $class->next::method($attrs, @rest);
+}
+
sub new {
my ($class, $attrs, @rest) = @_;
$attrs ||= {};
=head2 Transactions
As of version 0.04001, there is improved transaction support in
-L<DBIx::Class::Storage::DBI>. Here is an example of the recommended
-way to use it:
+L<DBIx::Class::Storage::DBI> and L<DBIx::Class::Schema>. Here is an
+example of the recommended way to use it:
- my $genus = Genus->find(12);
- eval {
- MyDB->txn_begin;
+ my $genus = $schema->resultset('Genus')->find(12);
+
+ my $coderef1 = sub {
+ my ($schema, $genus, $code) = @_;
$genus->add_to_species({ name => 'troglodyte' });
$genus->wings(2);
$genus->update;
- cromulate($genus); # Can have a nested transation
- MyDB->txn_commit;
+ $schema->txn_do($code, $genus); # Can have a nested transation
+ return $genus->species;
+ };
+
+ my $coderef2 = sub {
+ my ($genus) = @_;
+ $genus->extinct(1);
+ $genus->update;
};
- if ($@) {
- # Rollback might fail, too
- eval {
- MyDB->txn_rollback
- };
+
+ my $rs;
+ eval {
+ $rs = $schema->txn_do($coderef1, $schema, $genus, $coderef2);
+ };
+
+ if ($@) { # Transaction failed
+ die "the sky is falling!" #
+ if ($@ =~ /Rollback failed/); # Rollback failed
+
+ deal_with_failed_transaction();
}
-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
+Nested transactions will work as expected. That is, only the outermost
+transaction will actually issue a commit to the $dbh, and a rollback
+at any level of any transaction will cause the entire nested
+transaction to fail. Support for savepoints and for true nested
transactions (for databases that support them) will hopefully be added
in the future.
validate => $validate || 0,
parser_args => {
'DBIx::Schema' => $schema,
- }
+ },
producer_args => {
'prefix' => 'My::Schema',
- }
+ },
);
$translator->parser('DBIx::Class');
--- /dev/null
+=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 SQLite, 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
+
+Install DBIx::Class via CPAN should be sufficient.
+
+=head3 Create the database/tables.
+
+First make and change the directory:
+
+ mkdir app
+ cd app
+
+This example uses SQLite which is a dependency of DBIx::Class, so you
+shouldn't have to install extra software.
+
+Save the following into a example.sql
+
+ CREATE TABLE artist (
+ artistid INTEGER PRIMARY KEY,
+ name TEXT NOT NULL
+ );
+
+ CREATE TABLE cd (
+ cdid INTEGER PRIMARY KEY,
+ artist INTEGER NOT NULL REFERENCES artist(artistid),
+ title TEXT NOT NULL);
+
+ CREATE TABLE track (
+ trackid INTEGER PRIMARY KEY,
+ cd INTEGER NOT NULL REFERENCES cd(cdid),
+ title TEXT NOT NULL) ;
+
+and create the sqlite database file:
+
+sqlite3 example.db < example.sql
+
+=head3 Set up DBIx::Class::Schema
+
+First, create some dirs and change working directory:
+
+ mkdir MyDatabase
+ mkdir MyDatabase/Main
+
+Then, create the following DBIx::Class::Schema classes:
+
+MyDatabase/Main.pm:
+
+ package MyDatabase::Main;
+ use base qw/DBIx::Class::Schema/;
+ __PACKAGE__->load_classes(qw/Artist Cd Track/);
+
+ 1;
+
+
+MyDatabase/Main/Artist.pm:
+
+ package MyDatabase::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' => 'MyDatabase::Main::Cd');
+
+ 1;
+
+
+MyDatabase/Main/Cd.pm:
+
+ package MyDatabase::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' => 'MyDatabase::Main::Artist');
+ __PACKAGE__->has_many('tracks' => 'MyDatabase::Main::Track');
+
+ 1;
+
+
+MyDatabase/Main/Track.pm:
+
+ package MyDatabase::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' => 'MyDatabase::Main::Cd');
+
+ 1;
+
+
+=head3 Write a script to insert some records.
+
+insertdb.pl
+
+ #!/usr/bin/perl -w
+
+ use MyDatabase::Main;
+ use strict;
+
+ my $schema = MyDatabase::Main->connect('dbi:SQLite:example.db');
+
+ # here's some of the sql that is going to be generated by the schema
+ # INSERT INTO artist VALUES (NULL,'Michael Jackson');
+ # INSERT INTO artist VALUES (NULL,'Eminem');
+
+ my @artists = (['Michael Jackson'], ['Eminem']);
+ $schema->populate('Artist', [
+ [qw/name/],
+ @artists,
+ ]);
+
+ my %albums = (
+ 'Thriller' => 'Michael Jackson',
+ 'Bad' => 'Michael Jackson',
+ 'The Marshall Mathers LP' => 'Eminem',
+ );
+
+ my @cds;
+ foreach my $lp (keys %albums) {
+ my $artist = $schema->resultset('Artist')->search({
+ name => $albums{$lp}
+ });
+ push @cds, [$lp, $artist->first];
+ }
+
+ $schema->populate('Cd', [
+ [qw/title artist/],
+ @cds,
+ ]);
+
+
+ my %tracks = (
+ 'Beat It' => 'Thriller',
+ 'Billie Jean' => 'Thriller',
+ 'Dirty Diana' => 'Bad',
+ 'Smooth Criminal' => 'Bad',
+ 'Leave Me Alone' => 'Bad',
+ 'Stan' => 'The Marshall Mathers LP',
+ 'The Way I Am' => 'The Marshall Mathers LP',
+ );
+
+ my @tracks;
+ foreach my $track (keys %tracks) {
+ my $cdname = $schema->resultset('Cd')->search({
+ title => $tracks{$track},
+ });
+ push @tracks, [$cdname->first, $track];
+ }
+
+ $schema->populate('Track',[
+ [qw/cd title/],
+ @tracks,
+ ]);
+
+=head3 Create and run the scripts
+
+testdb.pl:
+
+ #!/usr/bin/perl -w
+
+ use MyDatabase::Main;
+ use strict;
+
+ my $schema = MyDatabase::Main->connect('dbi:SQLite:example.db');
+
+ 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 Notes
+
+With these scripts we're relying on @INC looking in the current
+working directory. You may want to add the MyDatabase namespaces to
+@INC in a different way when it comes to deployemnt.
+
+The testdb.pl script is an excellent start for testing your database
+model.
+
+=head1 TODO
+
+=head1 AUTHOR
+
+ sc_ from irc.perl.org#dbix-class
+ Kieren Diment <kd@totaldatasolution.com>
+
+=cut
=head3 Arguments: ($source, \%$attrs)
The resultset constructor. Takes a source object (usually a
-L<DBIx::Class::ResultSourceProxy::Table>) and an attribute hash (see L</ATRRIBUTES>
+L<DBIx::Class::ResultSourceProxy::Table>) and an attribute hash (see L</ATTRIBUTES>
below). Does not perform any queries -- these are executed as needed by the
other methods.
use base qw/DBIx::Class/;
-sub search { shift->resultset_instance->search(@_); }
-sub search_literal { shift->resultset_instance->search_literal(@_); }
-sub search_like { shift->resultset_instance->search_like(@_); }
-sub count { shift->resultset_instance->count(@_); }
-sub count_literal { shift->resultset_instance->count_literal(@_); }
-sub find { shift->resultset_instance->find(@_); }
-sub create { shift->resultset_instance->create(@_); }
-sub find_or_create { shift->resultset_instance->find_or_create(@_); }
+sub search { shift->resultset_instance->search(@_); }
+sub search_literal { shift->resultset_instance->search_literal(@_); }
+sub search_like { shift->resultset_instance->search_like(@_); }
+sub count { shift->resultset_instance->count(@_); }
+sub count_literal { shift->resultset_instance->count_literal(@_); }
+sub find { shift->resultset_instance->find(@_); }
+sub create { shift->resultset_instance->create(@_); }
+sub find_or_create { shift->resultset_instance->find_or_create(@_); }
+sub update_or_create { shift->resultset_instance->update_or_create(@_); }
1;
Registers a class which isa ResultSourceProxy; equivalent to calling
- $schema->register_source($moniker, $class->result_source_instance);
+ $schema->register_source($moniker, $component_class->result_source_instance);
=cut
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);
}
sub dbh {
my ($self) = @_;
- $self->_dbh(undef)
- if $self->_connection_pid && $self->_connection_pid != $$;
+ if($self->_connection_pid && $self->_connection_pid != $$) {
+ $self->_dbh->{InactiveDestroy} = 1;
+ $self->_dbh(undef)
+ }
$self->ensure_connected;
return $self->_dbh;
}
Calls begin_work on the current dbh.
+See L<DBIx::Class::Schema> for the txn_do() method, which allows for
+an entire code block to be executed transactionally.
+
=cut
sub txn_begin {
my $self = shift;
- $self->dbh->begin_work if $self->{transaction_depth}++ == 0 and $self->dbh->{AutoCommit};
+ $self->dbh->begin_work
+ if $self->{transaction_depth}++ == 0 and $self->dbh->{AutoCommit};
}
=head2 txn_commit
=head2 txn_rollback
-Issues a rollback against the current dbh.
+Issues a rollback against the current dbh. A nested rollback will
+throw a L<DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION> exception,
+which allows the rollback to propagate to the outermost transaction.
=cut
my ($sql, @bind) = $self->sql_maker->$op($ident, @args);
unshift(@bind, @$extra_bind) if $extra_bind;
if ($self->debug) {
- my @debug_bind = map { defined $_ ? $_ : 'NULL' } @bind;
- $self->debugfh->print("$sql: @debug_bind\n");
+ my @debug_bind = map { defined $_ ? qq{`$_'} : q{`NULL'} } @bind;
+ $self->debugfh->print("$sql: " . join(', ', @debug_bind) . "\n");
}
my $sth = $self->sth($sql,$op);
$self->throw_exception("no sth generated via sql: $sql") unless $sth;
eval {
my $dbh = PgTest->schema->storage->dbh;
- $dbh->do("CREATE TABLE cd (cdid serial PRIMARY KEY, artist INTEGER NOT NULL UNIQUE, title VARCHAR(255) NOT NULL UNIQUE, year VARCHAR(255));");
+ eval {
+ $dbh->do("DROP TABLE cd");
+ $dbh->do("CREATE TABLE cd (cdid serial PRIMARY KEY, artist INTEGER NOT NULL UNIQUE, title VARCHAR(255) NOT NULL UNIQUE, year VARCHAR(255));");
+ };
PgTest->resultset('CD')->create({ title => 'vacation in antarctica', artist => 123, year => 1901 });
PgTest->resultset('CD')->create({ title => 'vacation in antarctica part 2', artist => 456, year => 1901 });
OneKey
#dummy
TwoKeys
+ Serialized
/]},
(
'FourKeys',
--- /dev/null
+package DBICTest::Schema::Serialized;
+
+use base 'DBIx::Class::Core';
+
+DBICTest::Schema::Serialized->table('serialized');
+DBICTest::Schema::Serialized->add_columns(
+ 'id' => { data_type => 'integer' },
+ 'serialized' => { data_type => 'text' },
+);
+DBICTest::Schema::Serialized->set_primary_key('id');
+
+1;
name varchar NOT NULL
);
+--
+-- Table: serialized
+--
+CREATE TABLE serialized (
+ id INTEGER PRIMARY KEY NOT NULL,
+ serialized text NOT NULL
+);
+
COMMIT;
eval { require DateTime };
plan skip_all => "Need DateTime for inflation tests" if $@;
-plan tests => 3;
+plan tests => 5;
DBICTest::Schema::CD->inflate_column( 'year',
{ inflate => sub { DateTime->new( year => shift ) },
($cd) = $schema->resultset("CD")->search( year => $now->year );
is( $cd->year->year, $now->year, 'deflate ok' );
+use YAML;
+DBICTest::Schema::Serialized->inflate_column( 'serialized',
+ { inflate => sub { Load (shift) },
+ deflate => sub { die "Expecting a reference" unless (ref $_[0]); Dump (shift) } }
+);
+Class::C3->reinitialize;
+
+my $complex1 = {
+ id => 1,
+ serialized => {
+ a => 1,
+ b => 2,
+ },
+};
+
+my $complex2 = {
+ id => 1,
+ serialized => [qw/a b 1 2/],
+};
+
+my $rs = $schema->resultset('Serialized');
+
+my $entry = $rs->create($complex2);
+
+ok($entry->update ($complex1), "update with hashref deflating ok");
+
+ok($entry->update ($complex2), "update with arrayref deflating ok");
+
}
1;