select by id support
Matt S Trout [Sun, 10 Jan 2010 06:48:38 +0000 (06:48 +0000)]
lib/DBIx/Data/Collection/Set.pm
lib/DBIx/Data/Store/CRUD.pm
lib/DBIx/Data/Store/Command/Row.pm
t/01basic_collection.t

index 7e71b8e..ceb1e3f 100644 (file)
@@ -68,20 +68,22 @@ method _key_cache_has_object ($obj) {
 }
 
 method _key_cache_get_raw ($raw) {
-  my $id = $self->_raw_to_id($raw);
-  exists $self->_key_cache->{$id}
-    ? ($self->_key_cache->{$id})
-    : ()
+  $self->_key_cache_get_id($self->_raw_to_id($raw))
 }
 
 method _key_cache_get_object ($obj) {
-  $self->_key_cache_get_raw($self->_deflate($obj))
+  $self->_key_cache_get_id($self->_object_to_id($obj))
 }
 
-## loading data
+method _key_cache_get_object_spec ($spec) {
+  # see _object_spec_to_id for doc of what the difference is
+  $self->_key_cache_get_id($self->_object_spec_to_id($spec))
+}
 
-method _new_raw_stream {
-  $self->_store->new_select_command([])->execute
+method _key_cache_get_id ($id) {
+  exists $self->_key_cache->{$id}
+    ? ($self->_key_cache->{$id})
+    : ()
 }
 
 ## thunking between the store representation and the set representation
@@ -90,6 +92,8 @@ method _new_raw_stream {
 # _deflate is final repr -> raw data
 # _merge takes final repr + raw data and updates the repr
 #    (this is used for pk-generated values and later lazy loading)
+#
+# _deflate_spec is attributes of final repr -> raw data
 
 method _inflate ($raw) {
   bless($raw, $self->_class) if $self->_has_class;
@@ -105,6 +109,10 @@ method _merge ($obj, $raw) {
   $obj
 }
 
+method _deflate_spec ($spec) {
+  $spec
+}
+
 ## methods to get ids
 
 method _raw_to_id ($raw) {
@@ -116,8 +124,19 @@ method _object_to_id ($obj) {
   $self->_raw_to_id($self->_deflate($obj))
 }
 
+method _object_spec_to_id ($spec) {
+  # intentionally C&P from _raw_to - this is not the same thing. If a column
+  # were mapped to an attribute of a different name, the raw would have the
+  # column name as a key but an object spec would have the attribute name
+  join ';', map $spec->{$_}, @{$self->_set_over}
+}
+
 ## array-ish operations - i.e. get all members
 
+method _new_raw_stream {
+  $self->_store->new_select_command([])->execute
+}
+
 method flatten {
   @{$self->_member_cache};
 }
@@ -126,6 +145,22 @@ method as_stream {
   Data::Perl::Stream::Array->new(array => $self->_member_cache);
 }
 
+## load single row
+
+method get ($spec) {
+  if (my ($got) = $self->_key_cache_get_object_spec($spec)) {
+    return $got
+  }
+  if (my ($raw) = $self->_get_from_store($self->_deflate_spec($spec))) {
+    return $self->_add_to_key_cache($self->_inflate($raw))
+  }
+  return undef # we aren't handling cache misses here yet
+}
+
+method _get_from_store ($raw) {
+  $self->_store->new_select_single_command($raw)->execute
+}
+
 ## add to set
 
 method add ($new) {
index eff5e58..88bd4ff 100644 (file)
@@ -5,7 +5,7 @@ use Method::Signatures::Simple;
 
 has raw_store => (is => 'ro', required => 1); # DBIx::Data::Store object
 
-foreach my $type (qw(select insert update delete)) {
+foreach my $type (qw(select select_single insert update delete)) {
   has "${type}_sql" => (is => 'ro', predicate => "has_${type}_sql");
   has "${type}_argument_order" => (is => 'ro', default => sub { [] });
 }
@@ -23,6 +23,15 @@ method new_select_command ($args) {
   );
 }
 
+method new_select_single_command ($args) {
+  die "$self->has_select_single_sql" unless $self->has_select_single_sql;
+  $self->raw_store->new_row_command(
+    $self->select_single_sql,
+    $self->_unwrap_args_for(select_single => $args),
+    $self->select_column_order
+  );
+}
+
 method _unwrap_args_for ($type, $args) {
   [ @{$args}{@{$self->${\"${type}_argument_order"}}} ]
 }
index 402b616..53cb4b5 100644 (file)
@@ -7,7 +7,7 @@ use Method::Signatures::Simple;
 has 'column_order' => (is => 'ro', required => 1);
 
 method execute {
-  my $result = (my $stream = DBIx::Data::Stream::STH->new(
+  return unless my ($result) = (my $stream = DBIx::Data::Stream::STH->new(
     sth => $self->_new_active_sth, column_order => $self->column_order,
   ))->next;
   if ($stream->next) {
index 94ccb0f..c987036 100644 (file)
@@ -120,4 +120,17 @@ my ($fresh_pterry) = grep $_->{name} =~ /Pterry/, $set->flatten;
 
 is($fresh_pterry->{name}, 'Sir Pterry', 'Update persisted correctly');
 
+$set = make_set {}, {
+  select_single_sql => q{SELECT id, name FROM person WHERE id = ?},
+  select_single_argument_order => [ qw(id) ],
+};
+
+my $pterry_id = (grep $_->{name} eq 'Pterry', @expect)[0]->{id};
+
+$pterry = $set->get({ id => $pterry_id });
+
+is($pterry->{name}, 'Sir Pterry', 'Pterry retrieved by id');
+
+ok(!defined($set->get({ id => -1 })), 'undef on missing id');
+
 done_testing;