sub search {
my $self = shift;
-
- my $rs;
- if( @_ ) {
- my $attrs = { %{$self->{attrs}} };
- my $having = delete $attrs->{having};
- $attrs = { %$attrs, %{ pop(@_) } } if @_ > 1 and ref $_[$#_] eq 'HASH';
-
- my $where = (@_
- ? ((@_ == 1 || ref $_[0] eq "HASH")
- ? shift
- : ((@_ % 2)
- ? $self->throw_exception(
- "Odd number of arguments to search")
- : {@_}))
- : undef());
- if (defined $where) {
- $attrs->{where} = (defined $attrs->{where}
- ? { '-and' =>
- [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
- $where, $attrs->{where} ] }
- : $where);
- }
-
- if (defined $having) {
- $attrs->{having} = (defined $attrs->{having}
- ? { '-and' =>
- [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
- $having, $attrs->{having} ] }
- : $having);
- }
+ my $attrs = { %{$self->{attrs}} };
+ my $having = delete $attrs->{having};
+ $attrs = { %$attrs, %{ pop(@_) } } if @_ > 1 and ref $_[$#_] eq 'HASH';
+
+ my $where = (@_
+ ? ((@_ == 1 || ref $_[0] eq "HASH")
+ ? shift
+ : ((@_ % 2)
+ ? $self->throw_exception(
+ "Odd number of arguments to search")
+ : {@_}))
+ : undef());
+ if (defined $where) {
+ $attrs->{where} = (defined $attrs->{where}
+ ? { '-and' =>
+ [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
+ $where, $attrs->{where} ] }
+ : $where);
+ }
- $rs = (ref $self)->new($self->result_source, $attrs);
+ if (defined $having) {
+ $attrs->{having} = (defined $attrs->{having}
+ ? { '-and' =>
+ [ map { ref $_ eq 'ARRAY' ? [ -or => $_ ] : $_ }
+ $having, $attrs->{having} ] }
+ : $having);
}
- else {
- $rs = $self;
- $rs->reset;
+
+ my $rs = (ref $self)->new($self->result_source, $attrs);
+
+ unless (@_) { # no search, effectively just a clone
+ my $rows = $self->get_cache;
+ if( @{$rows} ) {
+ $rs->set_cache($rows);
+ }
}
+
return (wantarray ? $rs->all : $rs);
}
my $cd = $schema->resultset('CD')->find(5);
-You can also find a row by a specific key or unique constraint by specifying
-the C<key> attribute. For example:
+You can also find a row by a specific unique constraint using the C<key>
+attribute. For example:
my $cd = $schema->resultset('CD')->find('Massive Attack', 'Mezzanine', { key => 'artist_title' });
=cut
sub find {
- my ($self, @vals) = @_;
- my $attrs = (@vals > 1 && ref $vals[$#vals] eq 'HASH' ? pop(@vals) : {});
-
- my %unique_constraints = $self->result_source->unique_constraints;
- $self->throw_exception(
- "Can't find unless a primary key or unique constraint is defined"
- ) unless %unique_constraints;
-
- $self->throw_exception(
- "Unknown key $attrs->{key} on '" . $self->result_source->name . "'"
- ) if (exists $attrs->{key} and not exists $unique_constraints{$attrs->{key}});
-
- # Build a list of queries
- my @unique_hashes;
-
- if (ref $vals[0] eq 'HASH') {
- my @constraint_names = exists $attrs->{key}
- ? ($attrs->{key})
- : keys %unique_constraints;
+ my $self = shift;
+ my $attrs = (@_ > 1 && ref $_[$#_] eq 'HASH' ? pop(@_) : {});
- foreach my $name (@constraint_names) {
- my @unique_cols = @{ $unique_constraints{$name} };
- my $unique_hash = $self->_unique_hash($vals[0], \@unique_cols);
+ # Parse out a hash from input
+ my @cols = exists $attrs->{key}
+ ? $self->result_source->unique_constraint_columns($attrs->{key})
+ : $self->result_source->primary_columns;
- # TODO: Check that the ResultSet defines the rest of the query
- push @unique_hashes, $unique_hash
- if scalar keys %$unique_hash;# == scalar @unique_cols;
- }
+ my $hash;
+ if (ref $_[0] eq 'HASH') {
+ $hash = { %{$_[0]} };
+ }
+ elsif (@_ == @cols) {
+ $hash = {};
+ @{$hash}{@cols} = @_;
}
else {
- my @unique_cols = exists $attrs->{key}
- ? @{ $unique_constraints{$attrs->{key}} }
- : $self->result_source->primary_columns;
+ $self->throw_exception(
+ "Arguments to find must be a hashref or match the number of columns in the "
+ . exists $attrs->{key} ? "$attrs->{key} unique constraint" : "primary key"
+ );
+ }
- if (@vals == @unique_cols) {
- my %unique_hash;
- @unique_hash{@unique_cols} = @vals;
+ # Check the hash we just parsed against our source's unique constraints
+ my @constraint_names = exists $attrs->{key}
+ ? ($attrs->{key})
+ : $self->result_source->unique_constraint_names;
+ $self->throw_exception(
+ "Can't find unless a primary key or unique constraint is defined"
+ ) unless @constraint_names;
- push @unique_hashes, \%unique_hash;
- }
- else {
- # Hack for CDBI queries
- my %hash = @vals;
- push @unique_hashes, \%hash;
- }
- }
+ my @unique_queries;
+ foreach my $name (@constraint_names) {
+ my @unique_cols = $self->result_source->unique_constraint_columns($name);
+ my $unique_query = $self->_build_unique_query($hash, \@unique_cols);
- # Add the ResultSet's alias
- foreach my $unique_hash (@unique_hashes) {
- foreach my $key (grep { ! m/\./ } keys %$unique_hash) {
- $unique_hash->{"$self->{attrs}{alias}.$key"} = delete $unique_hash->{$key};
+ # Add the ResultSet's alias
+ foreach my $key (grep { ! m/\./ } keys %$unique_query) {
+ $unique_query->{"$self->{attrs}{alias}.$key"} = delete $unique_query->{$key};
}
+
+ push @unique_queries, $unique_query if %$unique_query;
}
# Handle cases where the ResultSet already defines the query
- my $query = @unique_hashes ? \@unique_hashes : undef;
+ my $query = @unique_queries ? \@unique_queries : undef;
+ # Run the query
if (keys %$attrs) {
my $rs = $self->search($query, $attrs);
return keys %{$rs->{collapse}} ? $rs->next : $rs->single;
}
}
-# _unique_hash
+# _build_unique_query
#
-# Constrain the specified hash based on the specific column names.
-
-sub _unique_hash {
- my ($self, $hash, $unique_cols) = @_;
+# Constrain the specified query hash based on the specified column names.
- # Ugh, CDBI lowercases column names
- if (exists $INC{'DBIx/Class/CDBICompat/ColumnCase.pm'}) {
- foreach my $key (keys %$hash) {
- $hash->{lc $key} = delete $hash->{$key};
- }
- }
+sub _build_unique_query {
+ my ($self, $query, $unique_cols) = @_;
- my %unique_hash =
- map { $_ => $hash->{$_} }
- grep { exists $hash->{$_} }
+ my %unique_query =
+ map { $_ => $query->{$_} }
+ grep { exists $query->{$_} }
@$unique_cols;
- return \%unique_hash;
+ return \%unique_query;
}
=head2 search_related