* 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
}++;
push @unique_queries, try {
- $self->_build_unique_cond ($c_name, $call_cond)
+ $self->_build_unique_cond ($c_name, $call_cond, 'croak_on_nulls')
} || ();
}
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);
};
# 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;
}
# 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'/;