use Scalar::Util 'blessed';
use DBIx::Class::_Util qw(UNRESOLVABLE_CONDITION serialize);
use SQL::Abstract qw(is_plain_value is_literal_value);
+use DBIx::Class::Carp;
use namespace::clean;
#
),
],
selecting => [
- map { ($sql_maker->_recurse_fields($_))[0] } @{$attrs->{select}},
+ # kill all selectors which look like a proper subquery
+ # this is a sucky heuristic *BUT* - if we get it wrong the query will simply
+ # fail to run, so we are relatively safe
+ grep
+ { $_ !~ / \A \s* \( \s* SELECT \s+ .+? \s+ FROM \s+ .+? \) \s* \z /xsi }
+ map
+ { ($sql_maker->_recurse_fields($_))[0] }
+ @{$attrs->{select}}
],
ordering => [
map { $_->[0] } $self->_extract_order_criteria ($attrs->{order_by}, $sql_maker),
],
};
- # throw away empty chunks and all 2-value arrayrefs: the thinking is that these are
- # bind value specs left in by the sloppy renderer above. It is ok to do this
- # at this point, since we are going to end up rewriting this crap anyway
- for my $v (values %$to_scan) {
- my @nv;
- for (@$v) {
- next if (
- ! defined $_
- or
- (
- ref $_ eq 'ARRAY'
- and
- ( @$_ == 0 or @$_ == 2 )
- )
- );
+ # throw away empty-string chunks, and make sure no binds snuck in
+ # note that we operate over @{$to_scan->{$type}}, hence the
+ # semi-mindbending ... map ... for values ...
+ ( $_ = [ map {
- if (ref $_) {
- require Data::Dumper::Concise;
- $self->throw_exception("Unexpected ref in scan-plan: " . Data::Dumper::Concise::Dumper($v) );
- }
+ (not $_) ? ()
+ : (length ref $_) ? (require Data::Dumper::Concise && $self->throw_exception(
+ "Unexpected ref in scan-plan: " . Data::Dumper::Concise::Dumper($_)
+ ))
+ : $_
- push @nv, $_;
- }
+ } @$_ ] ) for values %$to_scan;
- $v = \@nv;
- }
+ # throw away empty to-scan's
+ (
+ @{$to_scan->{$_}}
+ or
+ delete $to_scan->{$_}
+ ) for keys %$to_scan;
- # kill all selectors which look like a proper subquery
- # this is a sucky heuristic *BUT* - if we get it wrong the query will simply
- # fail to run, so we are relatively safe
- $to_scan->{selecting} = [ grep {
- $_ !~ / \A \s* \( \s* SELECT \s+ .+? \s+ FROM \s+ .+? \) \s* \z /xsi
- } @{ $to_scan->{selecting} || [] } ];
# first see if we have any exact matches (qualified or unqualified)
for my $type (keys %$to_scan) {
my $chunk = shift @pieces;
if (ref $chunk eq 'HASH') {
- push @pairs, map { $_ => $chunk->{$_} } sort keys %$chunk;
+ for (sort keys %$chunk) {
+
+ # Match SQLA 1.79 behavior
+ if ($_ eq '') {
+ is_literal_value($chunk->{$_})
+ ? carp 'Hash-pairs consisting of an empty string with a literal are deprecated, use -and => [ $literal ] instead'
+ : $self->throw_exception("Supplying an empty left hand side argument is not supported in hash-pairs")
+ ;
+ }
+
+ push @pairs, $_ => $chunk->{$_};
+ }
}
elsif (ref $chunk eq 'ARRAY') {
push @pairs, -or => $chunk
if @$chunk;
}
elsif ( ! length ref $chunk) {
+
+ # Match SQLA 1.79 behavior
+ $self->throw_exception("Supplying an empty left hand side argument is not supported in array-pairs")
+ if $where_is_anded_array and (! defined $chunk or $chunk eq '');
+
push @pairs, $chunk, shift @pieces;
}
else {
for (my $i = 0; $i <= $#$where; $i++ ) {
+ # Match SQLA 1.79 behavior
+ $self->throw_exception(
+ "Supplying an empty left hand side argument is not supported in array-pairs"
+ ) if (! defined $where->[$i] or ! length $where->[$i]);
+
my $logic_mod = lc ( ($where->[$i] =~ /^(\-(?:and|or))$/i)[0] || '' );
if ($logic_mod) {
my $sub_elt = $self->_collapse_cond({ $logic_mod => $where->[$i] })
or next;
- $fin_idx->{ "SER_" . serialize $sub_elt } = $sub_elt;
+ my @keys = keys %$sub_elt;
+ if ( @keys == 1 and $keys[0] !~ /^\-/ ) {
+ $fin_idx->{ "COL_$keys[0]_" . serialize $sub_elt } = $sub_elt;
+ }
+ else {
+ $fin_idx->{ "SER_" . serialize $sub_elt } = $sub_elt;
+ }
}
elsif (! length ref $where->[$i] ) {
my $sub_elt = $self->_collapse_cond({ @{$where}[$i, $i+1] })