use base 'DBIx::Class::Storage';
use mro 'c3';
-use Carp::Clan qw/^DBIx::Class/;
use List::Util 'first';
use Scalar::Util 'blessed';
use namespace::clean;
# the fake group_by is so that the pruner throws away all non-selecting, non-restricting
# multijoins (since we def. do not care about those inside the subquery)
- my $subq_joinspec = do {
+ my $inner_subq = do {
# must use it here regardless of user requests
local $self->{_use_join_optimizer} = 1;
local $self->{_use_join_optimizer} = 0;
# generate the subquery
- my $subq = $self->_select_args_to_query (
+ $self->_select_args_to_query (
$inner_from,
$inner_select,
$where,
$inner_attrs,
);
-
- +{
- -alias => $attrs->{alias},
- -rsrc => $inner_from->[0]{-rsrc},
- $attrs->{alias} => $subq,
- };
};
# Generate the outer from - this is relatively easy (really just replace
$j = [ $j ] unless ref $j eq 'ARRAY'; # promote the head-from to an AoH
if ($j->[0]{-alias} eq $attrs->{alias}) { # time to swap
+
push @outer_from, [
- $subq_joinspec,
+ {
+ -alias => $attrs->{alias},
+ -rsrc => $j->[0]{-rsrc},
+ $attrs->{alias} => $inner_subq,
+ },
@{$j}[1 .. $#$j],
];
last; # we'll take care of what's left in $from below
or next;
$return{$col} = {
- %{ ( $colinfos->{$source_alias} ||= $rsrc->columns_info )->{$colname} },
+ %{
+ ( $colinfos->{$source_alias} ||= $rsrc->columns_info )->{$colname}
+ ||
+ $self->throw_exception(
+ "No such column '$colname' on source " . $rsrc->source_name
+ );
+ },
-result_source => $rsrc,
-source_alias => $source_alias,
};
# at all. What this code tries to do (badly) is introspect the condition
# and remove all column qualifiers. If it bails out early (returns undef)
# the calling code should try another approach (e.g. a subquery)
+
+sub _strip_cond_qualifiers_from_array {
+ my ($self, $where) = @_;
+ my @cond;
+ for (my $i = 0; $i < @$where; $i++) {
+ my $entry = $where->[$i];
+ my $hash;
+ my $ref = ref $entry;
+ if ($ref eq 'HASH' or $ref eq 'ARRAY') {
+ $hash = $self->_strip_cond_qualifiers($entry);
+ }
+ elsif (! $ref) {
+ $entry =~ /([^.]+)$/;
+ $hash->{$1} = $where->[++$i];
+ }
+ push @cond, $hash;
+ }
+ return \@cond;
+}
+
sub _strip_cond_qualifiers {
my ($self, $where) = @_;
return $cond unless $where;
if (ref $where eq 'ARRAY') {
- $cond = [
- map {
- my %hash;
- foreach my $key (keys %{$_}) {
- $key =~ /([^.]+)$/;
- $hash{$1} = $_->{$key};
- }
- \%hash;
- } @$where
- ];
+ $cond = $self->_strip_cond_qualifiers_from_array($where);
}
elsif (ref $where eq 'HASH') {
if ( (keys %$where) == 1 && ( (keys %{$where})[0] eq '-and' )) {
- $cond->{-and} = [];
- my @cond = @{$where->{-and}};
- for (my $i = 0; $i < @cond; $i++) {
- my $entry = $cond[$i];
- my $hash;
- my $ref = ref $entry;
- if ($ref eq 'HASH' or $ref eq 'ARRAY') {
- $hash = $self->_strip_cond_qualifiers($entry);
- }
- elsif (! $ref) {
- $entry =~ /([^.]+)$/;
- $hash->{$1} = $cond[++$i];
- }
- else {
- $self->throw_exception ("_strip_cond_qualifiers() is unable to handle a condition reftype $ref");
- }
- push @{$cond->{-and}}, $hash;
- }
+ $cond->{-and} =
+ $self->_strip_cond_qualifiers_from_array($where->{-and});
}
else {
foreach my $key (keys %$where) {