First pass at reimplementation
Daniel Westermann-Clark [Sat, 8 Apr 2006 19:06:30 +0000 (15:06 -0400)]
lib/DBIx/Class/ResultSet.pm
t/run/20unique.tl

index 3541516..323abf4 100644 (file)
@@ -295,40 +295,57 @@ sub find {
   my ($self, @vals) = @_;
   my $attrs = (@vals > 1 && ref $vals[$#vals] eq 'HASH' ? pop(@vals) : {});
 
-  my @cols = $self->result_source->primary_columns;
+  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;
+
+  my @constraint_names = keys %unique_constraints;
   if (exists $attrs->{key}) {
-    my %uniq = $self->result_source->unique_constraints;
     $self->throw_exception(
       "Unknown key $attrs->{key} on '" . $self->result_source->name . "'"
-    ) unless exists $uniq{$attrs->{key}};
-    @cols = @{ $uniq{$attrs->{key}} };
-  }
-  #use Data::Dumper; warn Dumper($attrs, @vals, @cols);
-  $self->throw_exception(
-    "Can't find unless a primary key or unique constraint is defined"
-  ) unless @cols;
-
-  my $query;
-  if (ref $vals[0] eq 'HASH') {
-    $query = { %{$vals[0]} };
-  } elsif (@cols == @vals) {
-    $query = {};
-    @{$query}{@cols} = @vals;
-  } else {
-    $query = {@vals};
+    ) unless exists $unique_constraints{$attrs->{key}};
+
+    @constraint_names = ($attrs->{key});
   }
-  foreach my $key (grep { ! m/\./ } keys %$query) {
-    $query->{"$self->{attrs}{alias}.$key"} = delete $query->{$key};
+
+  my @unique_hashes;
+  foreach my $name (@constraint_names) {
+    my @unique_cols = @{ $unique_constraints{$name} };
+    my %unique_hash;
+    if (ref $vals[0] eq 'HASH') {
+      %unique_hash =
+        map  { $_ => $vals[0]->{$_} }
+        grep { exists $vals[0]->{$_} }
+        @unique_cols;
+    }
+    elsif (scalar @unique_cols == scalar @vals) {
+      # Assume the argument order corresponds to the constraint definition
+      @unique_hash{@unique_cols} = @vals;
+    }
+    elsif (scalar @vals % 2 == 0) {
+      # Fix for CDBI calling with a hash
+      %unique_hash = @vals;
+    }
+
+    foreach my $key (grep { ! m/\./ } keys %unique_hash) {
+      $unique_hash{"$self->{attrs}{alias}.$key"} = delete $unique_hash{$key};
+    }
+
+    #use Data::Dumper; warn Dumper \@vals, \@unique_cols, \%unique_hash;
+    push @unique_hashes, \%unique_hash if %unique_hash;
   }
-  #warn Dumper($query);
-  
+
+  # Handle cases where the ResultSet already defines the query
+  my $query = @unique_hashes ? \@unique_hashes : undef;
+
   if (keys %$attrs) {
-      my $rs = $self->search($query,$attrs);
-      return keys %{$rs->{collapse}} ? $rs->next : $rs->single;
+    my $rs = $self->search($query,$attrs);
+    return keys %{$rs->{collapse}} ? $rs->next : $rs->single;
   } else {
-      return keys %{$self->{collapse}} ?
-        $self->search($query)->next :
-        $self->single($query);
+    return keys %{$self->{collapse}}
+      ? $self->search($query)->next
+      : $self->single($query);
   }
 }
 
index eb747eb..024f09f 100644 (file)
@@ -1,7 +1,7 @@
 sub run_tests {
 my $schema = shift;
 
-plan tests => 18;
+plan tests => 26;
 
 my $artistid = 1;
 my $title    = 'UNIQUE Constraint';
@@ -69,6 +69,35 @@ is($cd5->get_column('artist'), $cd2->get_column('artist'), 'artist is correct');
 is($cd5->title, $cd2->title, 'title is correct');
 is($cd5->year, 2005, 'updated year is correct');
 
+my $cd6 = $schema->resultset('CD')->find_or_create(
+  {
+    artist => $artistid,
+    title  => $title,
+    year   => 2010,
+  },
+  { key => 'artist_title' }
+);
+
+is($cd6->cdid, $cd1->cdid, 'find or create by specific key: cdid is correct');
+is($cd6->get_column('artist'), $cd1->get_column('artist'), 'artist is correct');
+is($cd6->title, $cd1->title, 'title is correct');
+is($cd6->year, $cd1->year, 'year is correct');
+
+my $artist = $schema->resultset('Artist')->find($artistid);
+my $cd7 = $artist->find_or_create_related('cds',
+  {
+    artist => $artistid,
+    title  => $title,
+    year   => 2020,
+  },
+  { key => 'artist_title' }
+);
+
+is($cd7->cdid, $cd1->cdid, 'find or create related by specific key: cdid is correct');
+is($cd7->get_column('artist'), $cd1->get_column('artist'), 'artist is correct');
+is($cd7->title, $cd1->title, 'title is correct');
+is($cd7->year, $cd1->year, 'year is correct');
+
 }
 
 1;