1 How to allow custom relations:
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:
7 my ( $me_alias, $rel_alias, $me_result_source, $rel_name, $optional_me_object ) = @_;
9 Normally a condition can be constructed using only the first 2 arguments
10 (i.e. { "$left_alias.colA" => { '>', \"$right_alias.colB" } } ).
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)
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
22 The coderef is expected to return one or two values
23 ($on_as_where, $vals_from_related):
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)
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
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
47 Why the complexity of two RVs - custom rels are generally simplifiable
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
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
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
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
73 What needs to be adjusted (non-exhaustive summary):
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
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