From: Matt S Trout Date: Mon, 25 Jul 2011 15:05:09 +0000 (+0000) Subject: handle more IN/BETWEEN odd cases, fix value_meta handling X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=a420b11f45abb5017d1ad517212f537d1e33f9b4;p=dbsrgits%2FSQL-Abstract.git handle more IN/BETWEEN odd cases, fix value_meta handling --- diff --git a/lib/SQL/Abstract.pm b/lib/SQL/Abstract.pm index cf283bf..8843e51 100644 --- a/lib/SQL/Abstract.pm +++ b/lib/SQL/Abstract.pm @@ -145,7 +145,7 @@ sub _render_dq { wantarray ? ($self->{bindtype} eq 'normal' ? ($sql, map $_->{value}, @bind) - : ($sql, map [ $_->{meta}, $_->{value} ], @bind) + : ($sql, map [ $_->{value_meta}, $_->{value} ], @bind) ) : $sql; } @@ -188,7 +188,7 @@ sub _bind_to_dq { sub _value_to_dq { my ($self, $value) = @_; - perl_scalar_value($value); + perl_scalar_value($value, our $Cur_Col_Meta); } sub _ident_to_dq { @@ -644,9 +644,17 @@ sub _where_hashpair_to_dq { args => [ ref($v) ? $self->_where_to_dq($v) : $self->_ident_to_dq($v) ] }; } else { - die "Not done this bit yet"; + return +{ + type => DQ_OPERATOR, + operator => { 'SQL.Naive' => 'apply' }, + args => [ + $self->_ident_to_dq($op), + (map $self->_where_to_dq($_), (ref($v) eq 'ARRAY' ? @$v : $v)) + ], + }; } } else { + local our $Cur_Col_Meta = $k; if (ref($v) eq 'ARRAY') { if (!@$v) { return $self->_literal_to_dq($self->{sqlfalse}); @@ -676,8 +684,22 @@ sub _where_hashpair_to_dq { s/^-//, s/_/ /g for $op; if ($op eq 'BETWEEN' or $op eq 'IN' or $op eq 'NOT IN' or $op eq 'NOT BETWEEN') { if (ref($rhs) ne 'ARRAY') { + if ($op =~ /IN$/) { + # have to add parens if none present because -in => \"SELECT ..." + # got documented. mst hates everything. + if (ref($rhs) eq 'SCALAR') { + my $x = $$rhs; + $x = "($x)" unless $x =~ /^\s*\(/; + $rhs = \$x; + } else { + my ($x, @rest) = @{$$rhs}; + $x = "($x)" unless $x =~ /^\s*\(/; + $rhs = \[ $x, @rest ]; + } + } return $self->_literal_with_prepend_to_dq("$k $op", $$rhs); } + return $self->_literal_to_dq($self->{sqlfalse}) unless @$rhs; return +{ type => DQ_OPERATOR, operator => { 'SQL.Naive' => $op }, diff --git a/t/05in_between.t b/t/05in_between.t index d2ee54f..abc35d6 100644 --- a/t/05in_between.t +++ b/t/05in_between.t @@ -75,7 +75,7 @@ my @in_between_tests = ( ] }, }, stmt => "WHERE ( - ( start0 BETWEEN ? AND UPPER ? ) + ( start0 BETWEEN ? AND UPPER(?) ) AND ( start1 BETWEEN ? AND ? ) AND ( start2 BETWEEN lower(x) AND upper(y) ) AND ( start3 BETWEEN lower(x) AND upper(?) ) @@ -95,7 +95,7 @@ my @in_between_tests = ( ] }, }, stmt => "WHERE ( - ( start0 BETWEEN ? AND UPPER ? ) + ( start0 BETWEEN ? AND UPPER(?) ) AND ( start1 BETWEEN ? AND ? ) AND ( start2 BETWEEN lower(x) AND upper(y) ) AND ( start3 BETWEEN lower(x) AND upper(?) ) @@ -134,7 +134,7 @@ my @in_between_tests = ( { parenthesis_significant => 1, where => { x => { -in => \['( ( ?,?,lower(y) ) )', 1, 2] } }, - stmt => "WHERE ( x IN ( ?,?,lower(y) ) )", # note that outer parens are opened even though literal was requested (RIBASUSHI) + stmt => "WHERE ( x IN ( ( ?,?,lower(y) ) ) )", # note that outer parens are opened even though literal was requested (RIBASUSHI) bind => [1, 2], test => '-in with a literal arrayrefref', }, @@ -152,10 +152,10 @@ my @in_between_tests = ( parenthesis_significant => 1, where => { customer => { -in => \[ - 'SELECT cust_id FROM cust WHERE balance > ?', + '( SELECT cust_id FROM cust WHERE balance > ? )', 2000, ]}, - status => { -in => \'SELECT status_codes FROM states' }, + status => { -in => \'( SELECT status_codes FROM states )' }, }, stmt => " WHERE (( @@ -168,7 +168,7 @@ my @in_between_tests = ( }, { where => { x => { -in => [ \['LOWER(?)', 'A' ], \'LOWER(b)', { -lower => 'c' } ] } }, - stmt => " WHERE ( x IN ( LOWER(?), LOWER(b), LOWER ? ) )", + stmt => " WHERE ( x IN ( LOWER(?), LOWER(b), LOWER(?) ) )", bind => [qw/A c/], test => '-in with an array of function array refs with args', },