Commit | Line | Data |
c509b481 |
1 | package DBIx::Class::SQLMaker::Role::SQLA2Passthrough; |
2 | |
5895b65b |
3 | use strict; |
4 | use warnings; |
5 | use Exporter 'import'; |
6 | |
e6e94947 |
7 | our @EXPORT = qw(on); |
5895b65b |
8 | |
9 | sub on (&) { |
10 | my ($on) = @_; |
11 | sub { |
12 | my ($args) = @_; |
13 | $args->{self_resultsource} |
14 | ->schema->storage->sql_maker |
15 | ->expand_join_condition( |
16 | $on->($args), |
17 | $args |
18 | ); |
19 | } |
20 | } |
21 | |
c509b481 |
22 | use Role::Tiny; |
23 | |
24 | around select => sub { |
25 | my ($orig, $self, $table, $fields, $where, $rs_attrs, $limit, $offset) = @_; |
26 | |
27 | $fields = \[ $self->render_expr({ -list => [ |
28 | grep defined, |
29 | map +(ref($_) eq 'HASH' |
30 | ? do { |
31 | my %f = %$_; |
32 | my $as = delete $f{-as}; |
33 | my ($f, $rhs) = %f; |
e6e94947 |
34 | my $func = +{ ($f =~ /^-/ ? $f : "-${f}") => $rhs }; |
c509b481 |
35 | ($as |
36 | ? +{ -op => [ 'as', $func, { -ident => [ $as ] } ] } |
37 | : $func) |
38 | } |
39 | : $_), ref($fields) eq 'ARRAY' ? @$fields : $fields |
40 | ] }, -ident) ]; |
41 | |
42 | if (my $gb = $rs_attrs->{group_by}) { |
43 | $rs_attrs = { |
44 | %$rs_attrs, |
45 | group_by => \[ $self->render_expr({ -list => $gb }, -ident) ] |
46 | }; |
47 | } |
48 | $self->$orig($table, $fields, $where, $rs_attrs, $limit, $offset); |
e6e94947 |
49 | }; |
c509b481 |
50 | |
5895b65b |
51 | sub expand_join_condition { |
52 | my ($self, $cond, $args) = @_; |
53 | my $wrap = sub { |
54 | my ($orig) = @_; |
55 | sub { |
56 | my $res = $orig->(@_); |
57 | my ($name, @rest) = @{$res->{-ident}}; |
58 | if ($name eq 'self' or $name eq 'foreign') { |
59 | $res->{-ident} = [ $args->{"${name}_alias"}, @rest ]; |
60 | } |
61 | return $res; |
62 | }; |
63 | }; |
64 | my $sqla = $self->clone->wrap_op_expander(ident => $wrap); |
65 | $sqla->expand_expr($cond, -ident); |
66 | } |
67 | |
c509b481 |
68 | 1; |
5895b65b |
69 | |
70 | __END__ |
71 | |
934e6f13 |
72 | =head1 NAME |
73 | |
74 | DBIx::Class::SQLMaker::Role::SQLA2Passthrough - A test of future possibilities |
75 | |
76 | =head1 SYNOPSIS |
77 | |
78 | =over 4 |
79 | |
80 | =item * select and group_by options are processed using the richer SQLA2 code |
81 | |
82 | =item * expand_join_condition is provided to more easily express rich joins |
83 | |
84 | =back |
85 | |
86 | See C<examples/sqla2passthrough.pl> for a small amount of running code. |
87 | |
5895b65b |
88 | =head1 SETUP |
89 | |
90 | (on_connect_call => sub { |
91 | my ($storage) = @_; |
92 | $storage->sql_maker |
93 | ->with::roles('DBIx::Class::SQLMaker::Role::SQLA2Passthrough'); |
94 | }) |
95 | |
96 | =head2 expand_join_condition |
97 | |
98 | __PACKAGE__->has_many(minions => 'Blah::Person' => sub { |
99 | my ($args) = @_; |
100 | $args->{self_resultsource} |
101 | ->schema->storage->sql_maker |
102 | ->expand_join_condition( |
103 | $args |
104 | ); |
105 | }); |
106 | |
107 | =head2 on |
108 | |
109 | __PACKAGE__->has_many(minions => 'Blah::Person' => on { |
110 | { 'self.group_id' => 'foreign.group_id', |
111 | 'self.rank' => { '>', 'foreign.rank' } } |
112 | }); |
113 | |
114 | Or with ParameterizedJoinHack, |
115 | |
116 | __PACKAGE__->parameterized_has_many( |
117 | priority_tasks => 'MySchema::Result::Task', |
118 | [['min_priority'] => sub { |
119 | my $args = shift; |
120 | return +{ |
121 | "$args->{foreign_alias}.owner_id" => { |
122 | -ident => "$args->{self_alias}.id", |
123 | }, |
124 | "$args->{foreign_alias}.priority" => { |
125 | '>=' => $_{min_priority}, |
126 | }, |
127 | }; |
128 | }], |
129 | ); |
130 | |
131 | becomes |
132 | |
133 | __PACKAGE__->parameterized_has_many( |
134 | priority_tasks => 'MySchema::Result::Task', |
135 | [['min_priority'] => on { |
136 | { 'foreign.owner_id' => 'self.id', |
137 | 'foreign.priority' => { '>=', { -value => $_{min_priority} } } } |
138 | }] |
139 | ); |
934e6f13 |
140 | |
141 | =cut |