From: Aran Deltac Date: Tue, 23 May 2006 13:23:45 +0000 (+0000) Subject: Merge 'DBIx-Class-current' into 'reorganize_tests' X-Git-Tag: v0.07002~75^2~165^2~6 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=d904c338280461a590bfb2f9b2351bcb66d0725b;hp=58d387fec14d2f92723ab0db1d64a18ee449639c;p=dbsrgits%2FDBIx-Class.git Merge 'DBIx-Class-current' into 'reorganize_tests' r1664@moss (orig r1663): matthewt | 2006-05-18 06:19:02 -0700 r8675@cain (orig r1649): castaway | 2006-05-17 09:28:27 +0000 Documentation updates r8676@cain (orig r1650): zarquon | 2006-05-17 09:49:18 +0000 optimised last_insert_id example for searching r8691@cain (orig r1659): castaway | 2006-05-18 09:48:30 +0000 Add pod for params of inflate/deflate coderefs r1678@moss (orig r1677): tomk | 2006-05-18 10:13:14 -0700 Moved UUIDColumns from DBIX-Class-current into it's own dist in the trunk r1679@moss (orig r1678): matthewt | 2006-05-18 10:36:48 -0700 Moved PK::Auto into core r1703@moss (orig r1702): castaway | 2006-05-19 13:26:38 -0700 zbys Postgres casecheck patch r1704@moss (orig r1703): jguenther | 2006-05-19 13:50:55 -0700 added ensure_class_loaded method to Componentized, which should fix problems with nonexistent classes referenced in relationships going undetected r1705@moss (orig r1704): jguenther | 2006-05-19 13:56:32 -0700 removed DBICTest::Schema::Casecheck until someone adds it r1716@moss (orig r1715): matthewt | 2006-05-19 17:34:58 -0700 r8698@cain (orig r1666): tomk | 2006-05-18 15:56:54 +0000 Moved UUIDColumns.pm over from main DBIx::Class dist r8699@cain (orig r1667): tomk | 2006-05-18 15:59:52 +0000 Moved UUIDMaker.pm over from main DBIx::Class dist r8707@cain (orig r1675): tomk | 2006-05-18 16:49:41 +0000 Undoing changes commited in revisions 1664-1671... Sorry for the fuck up r8718@cain (orig r1681): jguenther | 2006-05-18 18:32:06 +0000 added bind information to exception thrown from DBIx::Class::Storage::DBI::_execute() r8731@cain (orig r1684): jguenther | 2006-05-18 21:55:45 +0000 removed another couple extraneous $self->dbh calls r8732@cain (orig r1685): jguenther | 2006-05-18 22:11:20 +0000 fixed small error in the SYNOPSIS of ResultSetManager.pm r8733@cain (orig r1686): jguenther | 2006-05-18 22:34:31 +0000 fixed an out-of-date limitation for has_many prefetch mentioned in Cookbook.pm r8741@cain (orig r1694): castaway | 2006-05-19 12:42:20 +0000 Update VERSION r8742@cain (orig r1695): castaway | 2006-05-19 13:03:20 +0000 Oops, fix bookmark thingy here too r8743@cain (orig r1696): castaway | 2006-05-19 13:12:22 +0000 .. And correct the number of tests r1719@moss (orig r1718): matthewt | 2006-05-19 17:53:52 -0700 r1656@cain (orig r1519): matthewt | 2006-04-26 03:19:25 +0000 Added InflateColumn::DateTime component r1720@moss (orig r1719): matthewt | 2006-05-19 17:54:25 -0700 r8669@cain (orig r1643): matthewt | 2006-05-17 00:22:06 +0000 Missing stuff for DateTime branch r1721@moss (orig r1720): matthewt | 2006-05-19 17:54:29 -0700 r1722@moss (orig r1721): matthewt | 2006-05-19 17:54:33 -0700 r1723@moss (orig r1722): matthewt | 2006-05-19 17:54:37 -0700 r8762@cain (orig r1713): matthewt | 2006-05-20 00:33:14 +0000 added datetime parser types for the dbs I can find them for r1724@moss (orig r1723): matthewt | 2006-05-19 17:54:41 -0700 r8763@cain (orig r1714): matthewt | 2006-05-20 00:34:39 +0000 added datetime parser for MSSQL (ta LTJake) r1725@moss (orig r1724): matthewt | 2006-05-19 17:54:44 -0700 r1726@moss (orig r1725): matthewt | 2006-05-19 18:14:38 -0700 futz changes, fix populate. I'm a retard. r1731@moss (orig r1730): claco | 2006-05-20 13:40:55 -0700 Added delete_related tests to verify it only deletes related records --- diff --git a/Changes b/Changes index 3a51cb7..bfa3bbf 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,6 @@ Revision history for DBIx::Class + - added AutoInflate::DateTime component - refactor debugging to allow for profiling using Storage::Statistics - removed Data::UUID from deps, made other optionals required - modified SQLT parser to skip dupe table names diff --git a/lib/DBIx/Class.pm b/lib/DBIx/Class.pm index 75b87d6..1ba52a0 100644 --- a/lib/DBIx/Class.pm +++ b/lib/DBIx/Class.pm @@ -13,7 +13,7 @@ sub component_base_class { 'DBIx::Class' } # i.e. first release of 0.XX *must* be 0.XX000. This avoids fBSD ports # brain damage and presumably various other packaging systems too -$VERSION = '0.06002'; +$VERSION = '0.06003'; sub MODIFY_CODE_ATTRIBUTES { my ($class,$code,@attrs) = @_; diff --git a/lib/DBIx/Class/CDBICompat/HasA.pm b/lib/DBIx/Class/CDBICompat/HasA.pm index 6930f3b..647674f 100644 --- a/lib/DBIx/Class/CDBICompat/HasA.pm +++ b/lib/DBIx/Class/CDBICompat/HasA.pm @@ -7,7 +7,7 @@ use warnings; sub has_a { my ($self, $col, $f_class, %args) = @_; $self->throw_exception( "No such column ${col}" ) unless $self->has_column($col); - eval "require $f_class"; + $self->ensure_class_loaded($f_class); if ($args{'inflate'} || $args{'deflate'}) { # Non-database has_a if (!ref $args{'inflate'}) { my $meth = $args{'inflate'}; diff --git a/lib/DBIx/Class/Componentised.pm b/lib/DBIx/Class/Componentised.pm index 7e62354..e23a0b4 100644 --- a/lib/DBIx/Class/Componentised.pm +++ b/lib/DBIx/Class/Componentised.pm @@ -5,16 +5,16 @@ use strict; use warnings; use Class::C3; +use Class::Inspector; sub inject_base { my ($class, $target, @to_inject) = @_; { no strict 'refs'; - my %seen; - unshift( @{"${target}::ISA"}, - grep { !$seen{ $_ }++ && $target ne $_ && !$target->isa($_) } - @to_inject - ); + foreach my $to (reverse @to_inject) { + unshift( @{"${target}::ISA"}, $to ) + unless ($target eq $to || $target->isa($to)); + } } # Yes, this is hack. But it *does* work. Please don't submit tickets about @@ -42,10 +42,20 @@ sub load_own_components { sub _load_components { my ($class, @comp) = @_; foreach my $comp (@comp) { - eval "use $comp"; - die $@ if $@; + $class->ensure_class_loaded($comp); } $class->inject_base($class => @comp); } +# TODO: handle ->has_many('rel', 'Class'...) instead of +# ->has_many('rel', 'Some::Schema::Class'...) +sub ensure_class_loaded { + my ($class, $f_class) = @_; + eval "require $f_class"; + my $err = $@; + Class::Inspector->loaded($f_class) + or die $err || "require $f_class was successful but the package". + "is not defined"; +} + 1; diff --git a/lib/DBIx/Class/Core.pm b/lib/DBIx/Class/Core.pm index 96a6a9a..87e7dce 100644 --- a/lib/DBIx/Class/Core.pm +++ b/lib/DBIx/Class/Core.pm @@ -10,6 +10,7 @@ __PACKAGE__->load_components(qw/ Serialize::Storable InflateColumn Relationship + PK::Auto PK Row ResultSourceProxy::Table diff --git a/lib/DBIx/Class/InflateColumn.pm b/lib/DBIx/Class/InflateColumn.pm index 013c724..d9817fe 100644 --- a/lib/DBIx/Class/InflateColumn.pm +++ b/lib/DBIx/Class/InflateColumn.pm @@ -50,6 +50,11 @@ corresponding table class using something like: (Replace L with the appropriate module for your database, or consider L.) +The coderefs you set for inflate and deflate are called with two parameters, +the first is the value of the column to be inflated/deflated, the second is the +row object itself. Thus you can call C<< ->result_source->schema->storage->dbh >> on +it, to feed to L. + In this example, calls to an event's C accessor return a L object. This L object is later "deflated" when used in the database layer. diff --git a/lib/DBIx/Class/InflateColumn/DateTime.pm b/lib/DBIx/Class/InflateColumn/DateTime.pm new file mode 100644 index 0000000..72c8844 --- /dev/null +++ b/lib/DBIx/Class/InflateColumn/DateTime.pm @@ -0,0 +1,40 @@ +package DBIx::Class::InflateColumn::DateTime; + +use strict; +use warnings; +use base qw/DBIx::Class/; + +__PACKAGE__->load_components(qw/InflateColumn/); + +__PACKAGE__->mk_group_accessors('simple' => '__datetime_parser'); + +sub register_column { + my ($self, $column, $info, @rest) = @_; + $self->next::method($column, $info, @rest); + if ($info->{data_type} =~ /^datetime$/i) { + $self->inflate_column( + $column => + { + inflate => sub { + my ($value, $obj) = @_; + $obj->_datetime_parser->parse_datetime($value); + }, + deflate => sub { + my ($value, $obj) = @_; + $obj->_datetime_parser->format_datetime($value); + }, + } + ); + } +} + +sub _datetime_parser { + my $self = shift; + if (my $parser = $self->__datetime_parser) { + return $parser; + } + my $parser = $self->result_source->storage->datetime_parser(@_); + return $self->__datetime_parser($parser); +} + +1; diff --git a/lib/DBIx/Class/Manual/Cookbook.pod b/lib/DBIx/Class/Manual/Cookbook.pod index 081a4d0..00f4c82 100644 --- a/lib/DBIx/Class/Manual/Cookbook.pod +++ b/lib/DBIx/Class/Manual/Cookbook.pod @@ -313,9 +313,8 @@ L has now prefetched all matching data from the C table, so no additional SQL statements are executed. You now have a much more efficient query. -Note that as of L 0.04, C cannot be used with -C relationships. You will get an error along the lines of "No -accessor for prefetched ..." if you try. +Note that as of L 0.05999_01, C I be used with +C relationships. Also note that C should only be used when you know you will definitely use data from a related table. Pre-fetching related tables when you @@ -846,4 +845,17 @@ array: You could then create average, high and low execution times for an SQL statement and dig down to see if certain parameters cause aberrant behavior. +=head2 Getting the value of the primary key for the last database insert + +AKA getting last_insert_id + +If you are using PK::Auto, this is straightforward: + + my $foo = $rs->create(\%blah); + # do more stuff + my $id = $foo->id; # foo->my_primary_key_field will also work. + +If you are not using autoincrementing primary keys, this will probably +not work, but then you already know the value of the last primary key anyway. + =cut diff --git a/lib/DBIx/Class/Relationship.pm b/lib/DBIx/Class/Relationship.pm index b5d6932..f9f85c2 100644 --- a/lib/DBIx/Class/Relationship.pm +++ b/lib/DBIx/Class/Relationship.pm @@ -118,6 +118,9 @@ instead of a join condition hash, that is used as the name of the column holding the foreign key. If $cond is not given, the relname is used as the column name. +Cascading deletes are off per default on a C relationship, to turn +them on, pass C<< cascade_delete => 1 >> in the $attr hashref. + NOTE: If you are used to L relationships, this is the equivalent of C. @@ -151,8 +154,9 @@ you to insert new related items, using the same mechanism as in L. If you delete an object in a class with a C relationship, all -related objects will be deleted as well. However, any database-level -cascade or restrict will take precedence. +the related objects will be deleted as well. However, any database-level +cascade or restrict will take precedence. To turn this behavior off, pass +C<< cascade_delete => 0 >> in the $attr hashref. =head2 might_have @@ -167,6 +171,7 @@ key of the foreign class unless $cond specifies a column or join condition. If you update or delete an object in a class with a C relationship, the related object will be updated or deleted as well. Any database-level update or delete constraints will override this behaviour. +To turn off this behavior, add C<< cascade_delete => 0 >> to the $attr hashref. =head2 has_one diff --git a/lib/DBIx/Class/Relationship/BelongsTo.pm b/lib/DBIx/Class/Relationship/BelongsTo.pm index 535fa75..8c8ceaa 100644 --- a/lib/DBIx/Class/Relationship/BelongsTo.pm +++ b/lib/DBIx/Class/Relationship/BelongsTo.pm @@ -5,11 +5,7 @@ use warnings; sub belongs_to { my ($class, $rel, $f_class, $cond, $attrs) = @_; - eval "require $f_class"; - if ($@) { - $class->throw_exception($@) unless $@ =~ /Can't locate/; - } - + $class->ensure_class_loaded($f_class); # no join condition or just a column name if (!ref $cond) { my %f_primaries = map { $_ => 1 } eval { $f_class->primary_columns }; diff --git a/lib/DBIx/Class/Relationship/HasMany.pm b/lib/DBIx/Class/Relationship/HasMany.pm index a709d6a..aa46486 100644 --- a/lib/DBIx/Class/Relationship/HasMany.pm +++ b/lib/DBIx/Class/Relationship/HasMany.pm @@ -6,11 +6,8 @@ use warnings; sub has_many { my ($class, $rel, $f_class, $cond, $attrs) = @_; - - eval "require $f_class"; - if ($@) { - $class->throw_exception($@) unless $@ =~ /Can't locate/; - } + + $class->ensure_class_loaded($f_class); unless (ref $cond) { my ($pri, $too_many) = $class->primary_columns; diff --git a/lib/DBIx/Class/Relationship/HasOne.pm b/lib/DBIx/Class/Relationship/HasOne.pm index 4efbec0..aa94a08 100644 --- a/lib/DBIx/Class/Relationship/HasOne.pm +++ b/lib/DBIx/Class/Relationship/HasOne.pm @@ -14,11 +14,7 @@ sub has_one { sub _has_one { my ($class, $join_type, $rel, $f_class, $cond, $attrs) = @_; - eval "require $f_class"; - if ($@) { - $class->throw_exception($@) unless $@ =~ /Can't locate/; - } - + $class->ensure_class_loaded($f_class); unless (ref $cond) { my ($pri, $too_many) = $class->primary_columns; $class->throw_exception( "might_have/has_one can only infer join for a single primary key; ${class} has more" ) diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index d6f0dd2..49d615f 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -1498,6 +1498,10 @@ use C instead: You can create your own accessors if required - see L for details. +Please note: This will NOT insert an C into the SQL statement +produced, it is used for internal access only. Thus attempting to use the accessor +in an C clause or similar will fail misrably. + =head2 join =over 4 diff --git a/lib/DBIx/Class/ResultSetManager.pm b/lib/DBIx/Class/ResultSetManager.pm index a0911bc..f5a62b4 100644 --- a/lib/DBIx/Class/ResultSetManager.pm +++ b/lib/DBIx/Class/ResultSetManager.pm @@ -22,7 +22,7 @@ use Class::Inspector; my $cond = shift; my $attrs = shift || {}; $attrs->{order_by} = 'year DESC'; - $self->next::method($cond, $attrs); + $self->search($cond, $attrs); } $rs = $schema->resultset('CD')->search_by_year_desc({ artist => 'Tool' }); diff --git a/lib/DBIx/Class/ResultSource.pm b/lib/DBIx/Class/ResultSource.pm index 4ce8e08..eb58dd5 100644 --- a/lib/DBIx/Class/ResultSource.pm +++ b/lib/DBIx/Class/ResultSource.pm @@ -176,13 +176,15 @@ sub column_info { { $self->{_columns_info_loaded}++; my $info; + my $lc_info; # eval for the case of storage without table - eval { $info = $self->storage->columns_info_for($self->from) }; + eval { $info = $self->storage->columns_info_for( $self->from, keys %{$self->_columns} ) }; unless ($@) { + for my $realcol ( keys %{$info} ) { + $lc_info->{lc $realcol} = $info->{$realcol}; + } foreach my $col ( keys %{$self->_columns} ) { - foreach my $i ( keys %{$info->{$col}} ) { - $self->_columns->{$col}{$i} = $info->{$col}{$i}; - } + $self->_columns->{$col} = $info->{$col} || $lc_info->{lc $col}; } } } @@ -454,10 +456,7 @@ sub add_relationship { my $f_source = $self->schema->source($f_source_name); unless ($f_source) { - eval "require $f_source_name;"; - if ($@) { - die $@ unless $@ =~ /Can't locate/; - } + $self->ensure_class_loaded($f_source_name); $f_source = $f_source_name->result_source; #my $s_class = ref($self->schema); #$f_source_name =~ m/^${s_class}::(.*)$/; diff --git a/lib/DBIx/Class/Schema.pm b/lib/DBIx/Class/Schema.pm index c1ea074..98387b4 100644 --- a/lib/DBIx/Class/Schema.pm +++ b/lib/DBIx/Class/Schema.pm @@ -263,13 +263,7 @@ sub load_classes { foreach my $prefix (keys %comps_for) { foreach my $comp (@{$comps_for{$prefix}||[]}) { my $comp_class = "${prefix}::${comp}"; - eval "use $comp_class"; # If it fails, assume the user fixed it - if ($@) { - $comp_class =~ s/::/\//g; - die $@ unless $@ =~ /Can't locate.+$comp_class\.pm\sin\s\@INC/; - warn $@ if $@; - } - + $class->ensure_class_loaded($comp_class); $comp_class->source_name($comp) unless $comp_class->source_name; push(@to_register, [ $comp_class->source_name, $comp_class ]); diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index bf556cb..9405288 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -509,8 +509,8 @@ Issues a commit against the current dbh. sub txn_commit { my $self = shift; + my $dbh = $self->dbh; if ($self->{transaction_depth} == 0) { - my $dbh = $self->dbh; unless ($dbh->{AutoCommit}) { $self->debugobj->txn_commit() if ($self->debug); @@ -521,7 +521,7 @@ sub txn_commit { if (--$self->{transaction_depth} == 0) { $self->debugobj->txn_commit() if ($self->debug); - $self->dbh->commit; + $dbh->commit; } } } @@ -538,8 +538,8 @@ sub txn_rollback { my $self = shift; eval { + my $dbh = $self->dbh; if ($self->{transaction_depth} == 0) { - my $dbh = $self->dbh; unless ($dbh->{AutoCommit}) { $self->debugobj->txn_rollback() if ($self->debug); @@ -550,7 +550,7 @@ sub txn_rollback { if (--$self->{transaction_depth} == 0) { $self->debugobj->txn_rollback() if ($self->debug); - $self->dbh->rollback; + $dbh->rollback; } else { die DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION->new; @@ -578,9 +578,10 @@ sub _execute { my $sth = eval { $self->sth($sql,$op) }; if (!$sth || $@) { - $self->throw_exception('no sth generated via sql (' . ($@ || $self->_dbh->errstr) . "): $sql"); + $self->throw_exception( + 'no sth generated via sql (' . ($@ || $self->_dbh->errstr) . "): $sql" + ); } - @bind = map { ref $_ ? ''.$_ : $_ } @bind; # stringify args my $rv; if ($sth) { @@ -692,8 +693,10 @@ sub columns_info_for { $column_info{size} = $info->{COLUMN_SIZE}; $column_info{is_nullable} = $info->{NULLABLE} ? 1 : 0; $column_info{default_value} = $info->{COLUMN_DEF}; + my $col_name = $info->{COLUMN_NAME}; + $col_name =~ s/^\"(.*)\"$/$1/; - $result{$info->{COLUMN_NAME}} = \%column_info; + $result{$col_name} = \%column_info; } }; $dbh->{RaiseError} = $old_raise_err; @@ -839,6 +842,21 @@ sub deploy { } } +sub datetime_parser { + my $self = shift; + return $self->{datetime_parser} ||= $self->build_datetime_parser(@_); +} + +sub datetime_parser_type { "DateTime::Format::MySQL"; } + +sub build_datetime_parser { + my $self = shift; + my $type = $self->datetime_parser_type(@_); + eval "use ${type}"; + $self->throw_exception("Couldn't load ${type}: $@") if $@; + return $type; +} + sub DESTROY { shift->disconnect } 1; diff --git a/lib/DBIx/Class/Storage/DBI/DB2.pm b/lib/DBIx/Class/Storage/DBI/DB2.pm index 83e2bc7..8e867e0 100644 --- a/lib/DBIx/Class/Storage/DBI/DB2.pm +++ b/lib/DBIx/Class/Storage/DBI/DB2.pm @@ -21,6 +21,8 @@ sub last_insert_id } +sub datetime_parser_type { "DateTime::Format::DB2"; } + 1; =head1 NAME diff --git a/lib/DBIx/Class/Storage/DBI/MSSQL.pm b/lib/DBIx/Class/Storage/DBI/MSSQL.pm index 171c17a..a303d25 100644 --- a/lib/DBIx/Class/Storage/DBI/MSSQL.pm +++ b/lib/DBIx/Class/Storage/DBI/MSSQL.pm @@ -11,6 +11,14 @@ sub last_insert_id { my( $id ) = $_[0]->_dbh->selectrow_array('SELECT @@IDENTITY' ); return $id; } + +sub build_datetime_parser { + my $self = shift; + my $type = "DateTime::Format::Strptime"; + eval "use ${type}"; + $self->throw_exception("Couldn't load ${type}: $@") if $@; + return $type->new( pattern => '%m/%d/%Y %H:%M:%S' ); +} 1; diff --git a/lib/DBIx/Class/Storage/DBI/Pg.pm b/lib/DBIx/Class/Storage/DBI/Pg.pm index 526abac..5940de2 100644 --- a/lib/DBIx/Class/Storage/DBI/Pg.pm +++ b/lib/DBIx/Class/Storage/DBI/Pg.pm @@ -35,6 +35,8 @@ sub sqlt_type { return 'PostgreSQL'; } +sub datetime_parser_type { return "DateTime::Format::Pg"; } + 1; =head1 NAME diff --git a/lib/DBIx/Class/Test/SQLite.pm b/lib/DBIx/Class/Test/SQLite.pm index 72a3c10..3302289 100644 --- a/lib/DBIx/Class/Test/SQLite.pm +++ b/lib/DBIx/Class/Test/SQLite.pm @@ -35,7 +35,7 @@ use warnings; use base qw/DBIx::Class/; -__PACKAGE__->load_components(qw/PK::Auto CDBICompat Core DB/); +__PACKAGE__->load_components(qw/CDBICompat Core DB/); use File::Temp qw/tempfile/; my (undef, $DB) = tempfile(); diff --git a/lib/DBIx/Class/UUIDColumns.pm b/lib/DBIx/Class/UUIDColumns.pm deleted file mode 100644 index fdd6adc..0000000 --- a/lib/DBIx/Class/UUIDColumns.pm +++ /dev/null @@ -1,152 +0,0 @@ -package DBIx::Class::UUIDColumns; - -use strict; -use warnings; - -use base qw/DBIx::Class/; - -__PACKAGE__->mk_classdata( 'uuid_auto_columns' => [] ); -__PACKAGE__->mk_classdata( 'uuid_maker' ); -__PACKAGE__->uuid_class( __PACKAGE__->_find_uuid_module ); - -# 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 uuid_class { - my ($self, $class) = @_; - - if ($class) { - $class = "DBIx::Class::UUIDMaker$class" if $class =~ /^::/; - - if (!eval "require $class") { - $self->throw_exception("$class could not be loaded: $@"); - } elsif (!$class->isa('DBIx::Class::UUIDMaker')) { - $self->throw_exception("$class is not a UUIDMaker subclass"); - } else { - $self->uuid_maker($class->new); - }; - }; - - return ref $self->uuid_maker; -}; - -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 shift->uuid_maker->as_string; -} - -sub _find_uuid_module { - 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 nastiness for XS - return '::APR::UUID'; - } elsif (eval{require UUID}) { - return '::UUID'; - } elsif (eval{ - # squelch the 'too late for INIT' warning in Win32::API::Type - local $^W = 0; - require Win32::Guidgen; - }) { - return '::Win32::Guidgen'; - } elsif (eval{require Win32API::GUID}) { - return '::Win32API::GUID'; - } else { - shift->throw_exception('no suitable uuid module could be found') - }; -}; - -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 -Chris Laco - -=head1 LICENSE - -You may distribute this code under the same terms as Perl itself. diff --git a/lib/DBIx/Class/UUIDMaker.pm b/lib/DBIx/Class/UUIDMaker.pm deleted file mode 100644 index f492801..0000000 --- a/lib/DBIx/Class/UUIDMaker.pm +++ /dev/null @@ -1,59 +0,0 @@ -package DBIx::Class::UUIDMaker; - -use strict; -use warnings; - -sub new { - return bless {}, shift; -}; - -sub as_string { - return undef; -}; - -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 incantations... - 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 deleted file mode 100644 index c7a383d..0000000 --- a/lib/DBIx/Class/UUIDMaker/APR/UUID.pm +++ /dev/null @@ -1,50 +0,0 @@ -package DBIx::Class::UUIDMaker::APR::UUID; - -use strict; -use warnings; - -use base qw/DBIx::Class::UUIDMaker/; -use APR::UUID (); - -sub as_string { - return APR::UUID->new->format; -}; - -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 deleted file mode 100644 index f70680c..0000000 --- a/lib/DBIx/Class/UUIDMaker/Data/UUID.pm +++ /dev/null @@ -1,50 +0,0 @@ -package DBIx::Class::UUIDMaker::Data::UUID; - -use strict; -use warnings; - -use base qw/DBIx::Class::UUIDMaker/; -use Data::UUID (); - -sub as_string { - return Data::UUID->new->to_string(Data::UUID->new->create); -}; - -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 deleted file mode 100644 index 36189e1..0000000 --- a/lib/DBIx/Class/UUIDMaker/Data/Uniqid.pm +++ /dev/null @@ -1,48 +0,0 @@ -package DBIx::Class::UUIDMaker::Data::Uniqid; - -use strict; -use warnings; - -use base qw/DBIx::Class::UUIDMaker/; -use Data::Uniqid (); - -sub as_string { - return Data::Uniqid->luniqid; -}; - -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 deleted file mode 100644 index f6fb802..0000000 --- a/lib/DBIx/Class/UUIDMaker/UUID.pm +++ /dev/null @@ -1,54 +0,0 @@ -package DBIx::Class::UUIDMaker::UUID; - -use strict; -use warnings; - -use base qw/DBIx::Class::UUIDMaker/; -use UUID (); - -sub as_string { - my ($uuid, $uuidstring); - UUID::generate($uuid); - UUID::unparse($uuid, $uuidstring); - - return $uuidstring; -}; - -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 deleted file mode 100644 index d9ba0ce..0000000 --- a/lib/DBIx/Class/UUIDMaker/Win32/Guidgen.pm +++ /dev/null @@ -1,53 +0,0 @@ -package DBIx::Class::UUIDMaker::Win32::Guidgen; - -use strict; -use warnings; - -use base qw/DBIx::Class::UUIDMaker/; -use Win32::Guidgen (); - -sub as_string { - my $uuid = Win32::Guidgen::create(); - $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 deleted file mode 100644 index 89df553..0000000 --- a/lib/DBIx/Class/UUIDMaker/Win32API/GUID.pm +++ /dev/null @@ -1,50 +0,0 @@ -package DBIx::Class::UUIDMaker::Win32API::GUID; - -use strict; -use warnings; - -use base qw/DBIx::Class::UUIDMaker/; -use Win32API::GUID (); - -sub as_string { - return Win32API::GUID::CreateGuid(); -}; - -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. diff --git a/t/05components.t b/t/05components.t index fd0742f..4b063bf 100644 --- a/t/05components.t +++ b/t/05components.t @@ -15,6 +15,9 @@ ok( DBICTest::ForeignComponent->foreign_test_method, 'foreign component' ); # Test for inject_base to filter out duplicates { package DBICTest::_InjectBaseTest; use base qw/ DBIx::Class /; + package DBICTest::_InjectBaseTest::A; + package DBICTest::_InjectBaseTest::B; + package DBICTest::_InjectBaseTest::C; } DBICTest::_InjectBaseTest->inject_base( 'DBICTest::_InjectBaseTest', qw/ DBICTest::_InjectBaseTest::A diff --git a/t/53delete_related.t b/t/53delete_related.t new file mode 100644 index 0000000..f193566 --- /dev/null +++ b/t/53delete_related.t @@ -0,0 +1,30 @@ +use Test::More; +use strict; +use warnings; +use lib qw(t/lib); +use DBICTest; +use DBICTest::BasicRels; + +plan tests => 7; + +my $schema = DBICTest->schema; +my $total_cds = $schema->resultset('CD')->count; +cmp_ok($total_cds, '>', 0, 'need cd records'); + +# test that delete_related w/o conditions deletes all related records only +my $artist = $schema->resultset("Artist")->find(3); +my $artist_cds = $artist->cds->count; +cmp_ok($artist_cds, '<', $total_cds, 'need more cds than just related cds'); + +ok($artist->delete_related('cds')); +cmp_ok($schema->resultset('CD')->count, '==', ($total_cds - $artist_cds), 'too many cds were deleted'); + +$total_cds -= $artist_cds; + +# test that delete_related w/conditions deletes just the matched related records only +my $artist2 = $schema->resultset("Artist")->find(2); +my $artist2_cds = $artist2->search_related('cds')->count; +cmp_ok($artist2_cds, '<', $total_cds, 'need more cds than related cds'); + +ok($artist2->delete_related('cds', {title => {like => '%'}})); +cmp_ok($schema->resultset('CD')->count, '==', ($total_cds - $artist2_cds), 'too many cds were deleted'); diff --git a/t/lib/DBICTest/FakeComponent.pm b/t/lib/DBICTest/FakeComponent.pm new file mode 100644 index 0000000..5fe3b66 --- /dev/null +++ b/t/lib/DBICTest/FakeComponent.pm @@ -0,0 +1,7 @@ +# belongs to t/run/30ensure_class_loaded.tl +package # hide from PAUSE + DBICTest::FakeComponent; +use warnings; +use strict; + +1; diff --git a/t/lib/DBICTest/Schema.pm b/t/lib/DBICTest/Schema.pm index 8de3ba9..aff1d00 100644 --- a/t/lib/DBICTest/Schema.pm +++ b/t/lib/DBICTest/Schema.pm @@ -11,6 +11,7 @@ __PACKAGE__->load_classes(qw/ CD Link Bookmark + #Casecheck #dummy Track Tag @@ -31,7 +32,7 @@ __PACKAGE__->load_classes(qw/ 'Producer', 'CD_to_Producer', ), - qw/SelfRefAlias TreeLike TwoKeyTreeLike/ + qw/SelfRefAlias TreeLike TwoKeyTreeLike Event/ ); sub deploy { diff --git a/t/lib/DBICTest/Schema/Event.pm b/t/lib/DBICTest/Schema/Event.pm new file mode 100644 index 0000000..fea3b07 --- /dev/null +++ b/t/lib/DBICTest/Schema/Event.pm @@ -0,0 +1,18 @@ +package DBICTest::Schema::Event; + +use strict; +use warnings; +use base qw/DBIx::Class/; + +__PACKAGE__->load_components(qw/InflateColumn::DateTime PK::Auto Core/); + +__PACKAGE__->table('event'); + +__PACKAGE__->add_columns( + id => { data_type => 'integer', is_auto_increment => 1 }, + starts_at => { data_type => 'datetime' } +); + +__PACKAGE__->set_primary_key('id'); + +1; diff --git a/t/lib/DBICTest/Schema/TreeLike.pm b/t/lib/DBICTest/Schema/TreeLike.pm index 9fde9f3..1eca3e1 100644 --- a/t/lib/DBICTest/Schema/TreeLike.pm +++ b/t/lib/DBICTest/Schema/TreeLike.pm @@ -14,7 +14,7 @@ __PACKAGE__->add_columns( }, ); __PACKAGE__->set_primary_key(qw/id/); -__PACKAGE__->belongs_to('parent', 'TreeLike', +__PACKAGE__->belongs_to('parent', 'DBICTest::Schema::TreeLike', { 'foreign.id' => 'self.parent' }); 1; diff --git a/t/lib/sqlite.sql b/t/lib/sqlite.sql index 7a13900..6a63ce7 100644 --- a/t/lib/sqlite.sql +++ b/t/lib/sqlite.sql @@ -1,6 +1,6 @@ -- -- Created by SQL::Translator::Producer::SQLite --- Created on Sun May 14 18:25:49 2006 +-- Created on Sat May 20 01:05:10 2006 -- BEGIN TRANSACTION; @@ -132,6 +132,14 @@ CREATE TABLE link ( ); -- +-- Table: event +-- +CREATE TABLE event ( + id INTEGER PRIMARY KEY NOT NULL, + starts_at datetime NOT NULL +); + +-- -- Table: twokeys -- CREATE TABLE twokeys (