1 package DBIx::Class::SQLMaker::Role::SQLA2Passthrough;
13 $args->{self_resultsource}
14 ->schema->storage->sql_maker
15 ->expand_join_condition(
24 around select => sub {
25 my ($orig, $self, $table, $fields, $where, $rs_attrs, $limit, $offset) = @_;
27 $fields = \[ $self->render_expr({ -list => [
29 map +(ref($_) eq 'HASH'
32 my $as = delete $f{-as};
34 my $func = +{ ($f =~ /^-/ ? $f : "-${f}") => $rhs };
36 ? +{ -op => [ 'as', $func, { -ident => [ $as ] } ] }
39 : $_), ref($fields) eq 'ARRAY' ? @$fields : $fields
42 if (my $gb = $rs_attrs->{group_by}) {
45 group_by => \[ $self->render_expr({ -list => $gb }, -ident) ]
48 $self->$orig($table, $fields, $where, $rs_attrs, $limit, $offset);
51 sub expand_join_condition {
52 my ($self, $cond, $args) = @_;
53 my ($type, %known) = do {
54 if (my $obj = $args->{self_result_object}) {
55 (self => $obj->get_columns)
56 } elsif (my $val = $args->{foreign_values}) {
62 my $maybe = $type ? 1 : 0;
68 my $res = $orig->(@_);
69 my ($name, $col) = @{$res->{-ident}};
70 if ($name eq 'self' or $name eq 'foreign') {
72 $maybe = 0 unless exists $known{$col};
74 return { -ident => [ $args->{"${name}_alias"}, $col ] };
79 my $sqla = $self->clone->wrap_op_expander(ident => $wrap);
80 my $aqt = $sqla->expand_expr($cond, -ident);
81 return $aqt unless $maybe;
82 my $inner_wrap = sub {
83 my $res = $outside->(@_);
84 my ($name, $col) = @{$res->{-ident}};
85 if ($name eq 'self' or $name eq 'foreign') {
87 return { -bind => [ $args->{"${name}_alias"}.'.'.$col, $known{$col} ] };
89 return { -ident => [ $args->{"${name}_alias"}, $col ] };
93 $sqla->op_expander(ident => $inner_wrap);
94 my $inner_aqt = $self->_collapsify($sqla->expand_expr($cond, -ident));
95 return ($aqt, $inner_aqt);
99 my ($self, $aqt) = @_;
100 return $aqt unless my @opargs = @{$aqt->{-op}};
101 my ($logop, @args) = @opargs;
102 return $aqt unless $logop eq 'and';
103 my %collapsed = map {
105 return $aqt unless my @opargs = @{$q->{-op}};
106 my ($op, $lhs, @rest) = @opargs;
107 return $aqt unless my @ident = @{$lhs->{-ident}};
108 (join('.', @ident), { $op => \@rest });
119 DBIx::Class::SQLMaker::Role::SQLA2Passthrough - A test of future possibilities
125 =item * select and group_by options are processed using the richer SQLA2 code
127 =item * expand_join_condition is provided to more easily express rich joins
131 See C<examples/sqla2passthrough.pl> for a small amount of running code.
135 (on_connect_call => sub {
138 ->with::roles('DBIx::Class::SQLMaker::Role::SQLA2Passthrough');
141 =head2 expand_join_condition
143 __PACKAGE__->has_many(minions => 'Blah::Person' => sub {
145 $args->{self_resultsource}
146 ->schema->storage->sql_maker
147 ->expand_join_condition(
154 __PACKAGE__->has_many(minions => 'Blah::Person' => on {
155 { 'self.group_id' => 'foreign.group_id',
156 'self.rank' => { '>', 'foreign.rank' } }
159 Or with ParameterizedJoinHack,
161 __PACKAGE__->parameterized_has_many(
162 priority_tasks => 'MySchema::Result::Task',
163 [['min_priority'] => sub {
166 "$args->{foreign_alias}.owner_id" => {
167 -ident => "$args->{self_alias}.id",
169 "$args->{foreign_alias}.priority" => {
170 '>=' => $_{min_priority},
178 __PACKAGE__->parameterized_has_many(
179 priority_tasks => 'MySchema::Result::Task',
180 [['min_priority'] => on {
181 { 'foreign.owner_id' => 'self.id',
182 'foreign.priority' => { '>=', { -value => $_{min_priority} } } }