Add some extra tests written while debugging, remove design draft
Peter Rabbitson [Mon, 17 Jan 2011 03:17:44 +0000 (04:17 +0100)]
BRANCH [deleted file]
t/relationship/custom.t

diff --git a/BRANCH b/BRANCH
deleted file mode 100644 (file)
index 78cb8d5..0000000
--- a/BRANCH
+++ /dev/null
@@ -1,88 +0,0 @@
-How to allow custom relations:
-
-* add_relationship is augmented to accept a coderef in addition to the
-traditional { foreign... => self... } hashref to specify an ON join
-condition. The coderef's signature is:
-
-my ( $me_alias, $rel_alias, $me_result_source, $rel_name, $optional_me_object ) = @_;
-
-Normally a condition can be constructed using only the first 2 arguments
-(i.e. { "$left_alias.colA" => { '>', \"$right_alias.colB" } } ).
-
-The next two arguments are supplied in case the coderef wants to do something
-clever. Having the result source and the corresponding rel-name (name, not
-alias) - one has access to virtually the entire DBIC object structure,
-including a raw $dbh (but don't do that)
-
-The last argument is supplied in cases like $row_obj->custom_relationship
-and *may* be used as an optimization path, see discussion of return values
-below.
-
-
-The coderef is expected to return one or two values
-  ($on_as_where, $vals_from_related):
-
-- an *SQLA* where-clause compatible structure (this implies that
-  t1.cola = t2.colb must be written as { t1.cola => \'t2.colb' }).
-  There are plans to introduce an -ident => 'string' SQLAHacks
-  operator to make the \'column' unnecessary (and allow proper
-  quoting when needed). The DBIC-SQLA shim is then augmented to
-  recognize such conditions, and pass them through _recurse_where
-  in order to produce the final textual ON clause (folding whatever
-  bind values at the proper places)
-
-- an OPTIONAL hashref of resolved values, when an $optional_me_object
-  is supplied to the coderef. This is the data that will be used to
-  make $some_row_obj->set_from_related ($another_obj) work, and also
-  to optimise $row_obj->relationship calls, by avoiding a full-join
-  and instead constructing a WHERE clause with the contents of said
-  hashref. Naturally the values of this hashref *must be* plain
-  scalars.
-  (Note - such rel-to-ident resolution is currently possible for *all*
-  DBIC relationships, but can not be guaranteed for all custom rels
-  possible via this syntax. Thus the escape hatch of a *mandatory*
-  ON clause, which can be used to construct a full-blown JOIN even in
-  the $obj->rel case
-
-
-Why the complexity of two RVs - custom rels are generally simplifiable
-right?
-
-This is generally true, except when it isn't. The main issue is that a
-coderef is a blackbox, and we want to keep it this way for simplicity.
-This means that no state is communicated from DBIC to the coderef (except
-for the optional row-obj), and no state is communicated out when the
-coderef returns (i.e. you can use this hashref for real joins but not for
-set_from_related).
-
-Here are a couple of edge cases when it is crucial to know if we have
-a return value for a specific scenario
-
-- Given a relationship
-    { 'artist.name' => { '!=', 'bob' }, 'artist.id' => \'cds.artistid' }
-  we *have* to do a full join when doing $artist->cds, as this is the
-  only way to evaluate the artist.name condition. For this we need a
-  defined $on_as_where, but a missing $vals_from_related, which will
-  signal the need to wrap a full query. Also set_from_related will
-  throw an exception here, as it largely makes no sense.
-
-- Given a relationship
-    { 'cd.year' => '2000', 'artist.id' => \'cds.artistid }
-  we could use the knowledge of the year to pre-fill the correct value
-  via $artist->create_related('year_2k_cd', {});
-
-
-What needs to be adjusted (non-exhaustive summary):
-
-* $obj->create_related is implemented on top of search_related and
-  set_from_related. While search_related will always work, the other
-  may not as discussed above
-
-* Relationships definitions are treated as fully-introdspectable structures
-  and multiple codepaths expect _resolve_condition to always return something
-  akin to $vals_from_related above. A grep for _resolve_condition will
-  highlight the problematic use-cases
-
-Additional Note:
-
-When using extended_rels all cascade options default to 0.
index 68936e3..5d44d18 100644 (file)
@@ -134,22 +134,21 @@ throws_ok {
 } qr/\Qunable to set_from_related - no simplified condition available for 'cds_90s'/, 'Create failed - non-simplified rel';
 
 # Do a self-join last-entry search
-my @last_track_ids;
+my @last_tracks;
 for my $cd ($schema->resultset('CD')->search ({}, { order_by => 'cdid'})->all) {
-  push @last_track_ids, $cd->tracks
-                            ->search ({}, { order_by => { -desc => 'position'} })
-                              ->get_column ('trackid')
-                                ->next;
+  push @last_tracks, $cd->tracks
+                         ->search ({}, { order_by => { -desc => 'position'} })
+                          ->next || ();
 }
 
-my $last_tracks = $schema->resultset('Track')->search (
+my $last_tracks_rs = $schema->resultset('Track')->search (
   {'next_track.trackid' => undef},
   { join => 'next_track', order_by => 'me.cd' },
 );
 
 is_deeply (
-  [$last_tracks->get_column ('trackid')->all],
-  [ grep { $_ } @last_track_ids ],
+  [$last_tracks_rs->get_column ('trackid')->all],
+  [ map { $_->trackid } @last_tracks ],
   'last group-entry via self-join works',
 );
 
@@ -187,4 +186,27 @@ lives_ok {
 is(scalar @artists, 1, 'only one artist is associated');
 
 
+# Make a single for each last_track
+my @singles = map {
+  $_->create_related('cd_single', {
+    title => $_->title . ' (the single)',
+    artist => $artist,
+    year => 1999,
+  }) } @last_tracks
+;
+
+# See if chaining works
+is_deeply (
+  [ map { $_->title } $last_tracks_rs->search_related('cd_single')->all ],
+  [ map { $_->title } @singles ],
+  'Retrieved singles in proper order'
+);
+
+# See if prefetch works
+is_deeply (
+  [ map { $_->cd_single->title } $last_tracks_rs->search({}, { prefetch => 'cd_single' })->all ],
+  [ map { $_->title } @singles ],
+  'Prefetched singles in proper order'
+);
+
 done_testing;