572184f4d0d3600f7d7b00212d1580dea22a9c8c
[dbsrgits/SQL-Abstract.git] / lib / DBIx / Class / SQLMaker / Role / SQLA2Passthrough.pm
1 package DBIx::Class::SQLMaker::Role::SQLA2Passthrough;
2
3 use strict;
4 use warnings;
5 use Exporter 'import';
6
7 our @EXPORT = qw('on');
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
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;
34               my $func = +{ "-${f}" => $rhs };
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);
49 });
50
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
68 1;
69
70 __END__
71
72 =head1 SETUP
73
74   (on_connect_call => sub {
75      my ($storage) = @_;
76      $storage->sql_maker
77              ->with::roles('DBIx::Class::SQLMaker::Role::SQLA2Passthrough');
78   })
79
80 =head2 expand_join_condition
81
82   __PACKAGE__->has_many(minions => 'Blah::Person' => sub {
83     my ($args) = @_;
84     $args->{self_resultsource}
85          ->schema->storage->sql_maker
86          ->expand_join_condition(
87              $args
88            );
89   });
90
91 =head2 on
92
93   __PACKAGE__->has_many(minions => 'Blah::Person' => on {
94     { 'self.group_id' => 'foreign.group_id',
95       'self.rank' => { '>', 'foreign.rank' } }
96   });
97
98 Or with ParameterizedJoinHack,
99
100   __PACKAGE__->parameterized_has_many(
101       priority_tasks => 'MySchema::Result::Task',
102       [['min_priority'] => sub {
103           my $args = shift;
104           return +{
105               "$args->{foreign_alias}.owner_id" => {
106                   -ident => "$args->{self_alias}.id",
107               },
108               "$args->{foreign_alias}.priority" => {
109                   '>=' => $_{min_priority},
110               },
111           };
112       }],
113   );
114
115 becomes
116
117   __PACKAGE__->parameterized_has_many(
118       priority_tasks => 'MySchema::Result::Task',
119       [['min_priority'] => on {
120         { 'foreign.owner_id' => 'self.id',
121           'foreign.priority' => { '>=', { -value => $_{min_priority} } } }
122       }]
123   );