A spec of what needs to happen to get complete custom relationships support
[dbsrgits/DBIx-Class.git] / BRANCH
1 How to allow custom relations:
2
3 * add_relationship is augmented to accept a coderef in addition to the
4 traditional { foreign... => self... } hashref to specify an ON join
5 condition. The coderef's signature is:
6
7 my ( $me_alias, $rel_alias, $me_result_source, $rel_name, $optional_me_object ) = @_;
8
9 Normally a condition can be constructed using only the first 2 arguments
10 (i.e. { "$left_alias.colA" => { '>', \"$right_alias.colB" } } ).
11
12 The next two arguments are supplied in case the coderef wants to do something
13 clever. Having the result source and the corresponding rel-name (name, not
14 alias) - one has access to virtually the entire DBIC object structure,
15 including a raw $dbh (but don't do that)
16
17 The last argument is supplied in cases like $row_obj->custom_relationship
18 and *may* be used as an optimization path, see discussion of return values
19 below.
20
21
22 The coderef is expected to return one or two values
23   ($on_as_where, $vals_from_related):
24
25 - an *SQLA* where-clause compatible structure (this implies that
26   t1.cola = t2.colb must be written as { t1.cola => \'t2.colb' }).
27   There are plans to introduce an -ident => 'string' SQLAHacks
28   operator to make the \'column' unnecessary (and allow proper
29   quoting when needed). The DBIC-SQLA shim is then augmented to
30   recognize such conditions, and pass them through _recurse_where
31   in order to produce the final textual ON clause (folding whatever
32   bind values at the proper places)
33
34 - an OPTIONAL hashref of resolved values, when an $optional_me_object
35   is supplied to the coderef. This is the data that will be used to
36   make $some_row_obj->set_from_related ($another_obj) work, and also
37   to optimise $row_obj->relationship calls, by avoiding a full-join
38   and instead constructing a WHERE clause with the contents of said
39   hashref
40   (Note - such rel-to-ident resolution is currently possible for *all*
41   DBIC relationships, but can not be guaranteed for all custom rels
42   possible via this syntax. Thus the escape hatch of a *mandatory*
43   ON clause, which can be used to construct a full-blown JOIN even in
44   the $obj->rel case
45
46
47 Why the complexity of two RVs - custom rels are generally simplifiable
48 right?
49
50 This is generally true, except when it isn't. The main issue is that a
51 coderef is blackbox, and we want to keep it this way for simplicity.
52 This means that no state is communicate from DBIC to the coderef (except
53 for the optional row-obj), and no state is communicated out when the
54 coderef returns (i.e. you can use this hashref for real joins but not for
55 set_from_related).
56
57 Here are a couple of edge cases when it is crucial to know if we have
58 a return value for a specific scenario
59
60 - Given a relationship
61     { 'artist.name' => { '!=', 'bob' }, 'artist.id' => \'cds.artistid' }
62   we *have* to do a full join when doing $artist->cds, as this is the
63   only way to evaluate the artist.name condition. For this we need a
64   defined $on_as_where, but a missing $vals_from_related, which will
65   signal the need to wrap a full query
66
67 - Given the same relationship as above, we want
68   $new_cd->set_from_related($artist) to do the right thing depending
69   on the name of $artist - the coderef would be tasked to return
70   { artistid => xxx } or {} depending on the value of $artist->name
71
72
73 What needs to be adjusted (non-exhaustive summary):
74
75 * $obj->create_related is implemented on top of search_related and
76   set_from_related. While search_related will always work, the other
77   may not as discussed above
78
79 * Relationships definitions are treated as fully-introdspectable structures
80   and multiple codepaths expect _resolve_condition to always return something
81   akin to $vals_from_related above. A grep for _resolve_condition will
82   highlight the problematic use-cases