From: Peter Rabbitson Date: Fri, 14 Jan 2011 11:41:42 +0000 (+0100) Subject: Reduce to a warning the find-with-NULL-key exception from b7743dab X-Git-Tag: v0.08127~19 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=dbsrgits%2FDBIx-Class.git;a=commitdiff_plain;h=65c1217de6381d5cc8ffb10cd6bb870144a2649b Reduce to a warning the find-with-NULL-key exception from b7743dab --- diff --git a/Changes b/Changes index 2f6f95b..b675310 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,10 @@ Revision history for DBIx::Class * New Features / Changes - Schema/resultsource instances are now crossreferenced via a new system guaranteeing leak-free mutually assuered destruction + - Switch to a warning when find() is invoked with both a 'key' + argument and a NULL-containing condition to satisfy the named + constraint. Previously (starting with 0.08124) an exception was + thrown. * Fixes - Revert default selection to being lazy again (eagerness introduced diff --git a/lib/DBIx/Class/ResultSet.pm b/lib/DBIx/Class/ResultSet.pm index 5c862e3..d826e03 100644 --- a/lib/DBIx/Class/ResultSet.pm +++ b/lib/DBIx/Class/ResultSet.pm @@ -739,7 +739,7 @@ sub find { }++; push @unique_queries, try { - $self->_build_unique_cond ($c_name, $call_cond) + $self->_build_unique_cond ($c_name, $call_cond, 'croak_on_nulls') } || (); } @@ -797,8 +797,9 @@ sub _qualify_cond_columns { return \%aliased; } +my $callsites_warned_ucond; sub _build_unique_cond { - my ($self, $constraint_name, $extra_cond) = @_; + my ($self, $constraint_name, $extra_cond, $croak_on_null) = @_; my @c_cols = $self->result_source->unique_constraint_columns($constraint_name); @@ -810,15 +811,45 @@ sub _build_unique_cond { }; # trim out everything not in $columns - $final_cond = { map { $_ => $final_cond->{$_} } @c_cols }; - - if (my @missing = grep { ! defined $final_cond->{$_} } (@c_cols) ) { + $final_cond = { map { + exists $final_cond->{$_} + ? ( $_ => $final_cond->{$_} ) + : () + } @c_cols }; + + if (my @missing = grep + { ! ($croak_on_null ? defined $final_cond->{$_} : exists $final_cond->{$_}) } + (@c_cols) + ) { $self->throw_exception( sprintf ( "Unable to satisfy requested constraint '%s', no values for column(s): %s", $constraint_name, join (', ', map { "'$_'" } @missing), ) ); } + if ( + !$croak_on_null + and + !$ENV{DBIC_NULLABLE_KEY_NOWARN} + and + my @undefs = grep { ! defined $final_cond->{$_} } (keys %$final_cond) + ) { + my $callsite = do { + my $w; + local $SIG{__WARN__} = sub { $w = shift }; + carp; + $w + }; + + carp ( sprintf ( + "NULL/undef values supplied for requested unique constraint '%s' (NULL " + . 'values in column(s): %s). This is almost certainly not what you wanted, ' + . 'though you can set DBIC_NULLABLE_KEY_NOWARN to disable this warning.', + $constraint_name, + join (', ', map { "'$_'" } @undefs), + )) unless $callsites_warned_ucond->{$callsite}++; + } + return $final_cond; } diff --git a/t/61findnot.t b/t/61findnot.t index 6d23dc9..d7dde4d 100644 --- a/t/61findnot.t +++ b/t/61findnot.t @@ -52,19 +52,37 @@ ok($art, 'Artist found by key in the resultset'); # collapsing and non-collapsing are separate codepaths, thus the separate tests + $artist_rs = $schema->resultset("Artist"); + warnings_exist { $artist_rs->find({}) } qr/\QDBIx::Class::ResultSet::find(): Query returned more than one row. SQL that returns multiple rows is DEPRECATED for ->find and ->single/ => "Non-unique find generated a cursor inexhaustion warning"; + throws_ok { $artist_rs->find({}, { key => 'primary' }) } qr/Unable to satisfy requested constraint 'primary'/; +for (1, 0) { + warnings_like + sub { + $artist_rs->find({ artistid => undef }, { key => 'primary' }) + }, + $_ ? [ + qr/undef values supplied for requested unique constraint.+almost certainly not what you wanted/, + ] : [], + 'One warning on NULL conditions for constraint' + ; +} + + $artist_rs = $schema->resultset("Artist")->search({}, { prefetch => 'cds' }); + warnings_exist { $artist_rs->find({}) } qr/\QDBIx::Class::ResultSet::find(): Query returned more than one row/, "Non-unique find generated a cursor inexhaustion warning"; + throws_ok { $artist_rs->find({}, { key => 'primary' }) } qr/Unable to satisfy requested constraint 'primary'/;