Release commit for 0.002001
[dbsrgits/DBIx-Class-ParameterizedJoinHack.git] / lib / DBIx / Class / ResultSet / ParameterizedJoinHack.pm
CommitLineData
638c1533 1package DBIx::Class::ResultSet::ParameterizedJoinHack;
2
3use strict;
4use warnings;
5use DBIx::Class::ParameterizedJoinHack;
6use base qw(DBIx::Class::ResultSet);
7
8sub _parameterized_join_store {
9 $_[0]->result_source->result_class
10 ->$DBIx::Class::ParameterizedJoinHack::STORE
11}
12
13sub with_parameterized_join {
14 my ($self, $rel, $params) = @_;
598b28ef 15 die "Missing relation name in with_parameterized_join"
16 unless defined $rel;
93b74da6 17
598b28ef 18 {
19 my $params_ref = ref($params);
20 $params_ref = 'non-reference-value'
21 unless $params_ref;
22 die "Parameters value must be a hash ref, not ${params_ref}"
23 unless $params_ref eq 'HASH';
24 }
93b74da6 25
6d37bc62 26 die "Parameterized join can only be used once per relation"
27 if exists(($self->{attrs}{join_parameters} || {})->{$rel});
28
638c1533 29 $self->search_rs(
30 {},
31 { join => $rel,
32 join_parameters => {
33 %{$self->{attrs}{join_parameters}||{}},
34 $rel => $params
35 }
36 },
37 );
38}
39
40sub call_with_parameters {
41 my ($self, $method, @args) = @_;
c2ae4b8d 42 my $params = $self->{attrs}{join_parameters}||{};
43 my @param_names = keys %$params;
638c1533 44 my $store = $self->_parameterized_join_store;
c2ae4b8d 45 # This loop is implemented using "goto"; this means the "local" doesn't have
46 # to be in a separate scope, which would defeat the point. Nor does "local
47 # ... foreach ..." work; the localization doesn't survive the loop. The
48 # alternative would be to use recursive subroutine calls, but that would
49 # require not only the N save-stack entries for the localized parameters, but
50 # N call frames too, so this approach saves both time and memory. It also
51 # avoids any risk of a "deep recursion" warning if you have a lot of
52 # parameters; and it avoids cluttering stack traces if the called method
53 # throws an exception. The downside is obviously that it uses "goto" for an
54 # otherwise-simple loop, but at least it's confined to this method. Further,
55 # the result is more than twice as fast as the recursive approach even when
56 # there are no parameters, and the "goto" version wins even more with larger
57 # parameter lists.
58 Loop:
59 return $self->$method(@args)
60 unless @param_names;
61 my $key = shift @param_names;
62 local $store->{$key}{params} = $params->{$key};
63 goto Loop; # Watch Dijkstra roll in his grave
638c1533 64}
65
66sub _resolved_attrs { my $self = shift; $self->call_with_parameters($self->next::can, @_) }
67sub related_resultset { my $self = shift; $self->call_with_parameters($self->next::can, @_) }
68
691;
70
71=head1 NAME
72
73DBIx::Class::ResultSet::ParameterizedJoinHack
74
75=head1 SYNOPSIS
76
77 package MySchema::ResultSet::Person;
78 use base qw(DBIx::Class::ResultSet);
79
80 __PACKAGE__->load_components(qw(ResultSet::ParameterizedJoinHack));
81
82 1;
83
84=head1 DESCRIPTION
85
86This is a ResultSet component allowing you to access the dynamically
87parameterized relations declared with
88L<DBIx::Class::ParameterizedJoinHack>.
89
90Enable the component as usual with:
91
92 __PACKAGE__->load_components(qw( ResultSet::ParameterizedJoinHack ));
93
94in your ResultSet class.
95
96See L<DBIx::Class::ParameterizedJoinHack> for declaration documentation,
97a general overview, and examples.
98
99=head1 METHODS
100
101=head2 with_parameterized_join
102
103 my $joined_rs = $resultset->with_parameterized_join(
104 $relation_name,
105 $parameters,
106 );
107
108This method constructs a ResultSet joined with the given C<$relation_name>
109by the passed C<$parameters>. The C<$relation_name> is the name as
110declared on the Result, C<$parameters> is a hash reference with the keys
111being the parameter names, and the values being the arguments to the join
112builder.
113
114=head1 SPONSORS
115
116Development of this module was sponsored by
117
118=over
119
120=item * Ctrl O L<http://ctrlo.com>
121
122=back
123
124=head1 AUTHOR
125
126 Matt S. Trout <mst@shadowcat.co.uk>
127
128=head1 CONTRIBUTORS
129
130None yet.
131
132=head1 COPYRIGHT
133
134Copyright (c) 2015 the DBIx::Class::ParameterizedJoinHack L</AUTHOR> and L</CONTRIBUTORS>
135as listed above.
136
137=head1 LICENSE
138
139This library is free software and may be distributed under the same terms
140as perl itself.
141
142=cut