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.