add some docs for the role
[dbsrgits/SQL-Abstract.git] / lib / DBIx / Class / SQLMaker / Role / SQLA2Passthrough.pm
CommitLineData
5410c047 1package DBIx::Class::SQLMaker::Role::SQLA2Passthrough;
2
78227631 3use strict;
4use warnings;
5use Exporter 'import';
6
48389aca 7our @EXPORT = qw(on);
78227631 8
9sub 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
5410c047 22use Role::Tiny;
23
24around 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;
48389aca 34 my $func = +{ ($f =~ /^-/ ? $f : "-${f}") => $rhs };
5410c047 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);
48389aca 49};
5410c047 50
78227631 51sub 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
5410c047 681;
78227631 69
70__END__
71
82283e69 72=head1 NAME
73
74DBIx::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
86See C<examples/sqla2passthrough.pl> for a small amount of running code.
87
78227631 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
114Or 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
131becomes
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 );
82283e69 140
141=cut