# the digits are backcompat stuff
{ regex => qr/^and (?: \s? \d+ )? $/xi, handler => '_where_op_ANDOR' },
{ regex => qr/^or (?: \s? \d+ )? $/xi, handler => '_where_op_ANDOR' },
- { regex => qr/^nest (?: \s? \d+ )? $/xi, handler => '_where_op_NEST' },
{ regex => qr/^ (?: not \s )? bool $/xi, handler => '_where_op_BOOL' },
+ { regex => qr/^ ident $/xi, handler => '_where_op_IDENT' },
+ { regex => qr/^nest (?: \s? \d+ )? $/xi, handler => '_where_op_NEST' },
);
#======================================================================
return ($sql, @bind);
}
+sub _where_op_IDENT {
+ my ($self, $op, $v) = @_;
+
+ if (ref $v) {
+ puke "-$op takes a single scalar argument (a quotable identifier)";
+ }
+
+ return $self->_convert($self->_quote($v));
+}
+
sub _where_op_ANDOR {
my ($self, $op, $v) = @_;
foreach my $val (@$vals) {
my ($sql, @bind) = $self->_SWITCH_refkind($val, {
SCALAR => sub {
- return ($placeholder, ($val));
+ return ($placeholder, $val);
},
SCALARREF => sub {
- return ($self->_convert($$val), ());
+ return $$val;
},
ARRAYREFREF => sub {
my ($sql, @bind) = @$$val;
$self->_assert_bindval_matches_bindtype(@bind);
- return ($self->_convert($sql), @bind);
+ return ($sql, @bind);
},
+ HASHREF => sub {
+ my ($func, $arg, @rest) = %$val;
+ puke ("Only simple { -func => arg } functions accepted as sub-arguments to BETWEEN")
+ if (@rest or $func !~ /^ \- (.+)/x);
+ local $self->{_nested_func_lhs} = $k;
+ $self->_where_func_generic ($1 => $arg);
+ }
});
push @all_sql, $sql;
push @all_bind, @bind;
my ($sql, @bind) = $self->_SWITCH_refkind($vals, {
ARRAYREF => sub { # list of choices
if (@$vals) { # nonempty list
- my $placeholders = join ", ", (($placeholder) x @$vals);
- my $sql = "$label $op ( $placeholders )";
- my @bind = $self->_bindtype($k, @$vals);
+ my (@all_sql, @all_bind);
+
+ for my $val (@$vals) {
+ my ($sql, @bind) = $self->_SWITCH_refkind($val, {
+ SCALAR => sub {
+ return ($placeholder, $val);
+ },
+ SCALARREF => sub {
+ return $$val;
+ },
+ ARRAYREFREF => sub {
+ my ($sql, @bind) = @$$val;
+ $self->_assert_bindval_matches_bindtype(@bind);
+ return ($sql, @bind);
+ },
+ HASHREF => sub {
+ my ($func, $arg, @rest) = %$val;
+ puke ("Only simple { -func => arg } functions accepted as sub-arguments to IN")
+ if (@rest or $func !~ /^ \- (.+)/x);
+ local $self->{_nested_func_lhs} = $k;
+ $self->_where_func_generic ($1 => $arg);
+ }
+ });
+ push @all_sql, $sql;
+ push @all_bind, @bind;
+ }
- return ($sql, @bind);
+ my $sql = sprintf ('%s %s ( %s )',
+ $label,
+ $op,
+ join (', ', @all_sql)
+ );
+ return ($sql, @all_bind);
}
else { # empty list : some databases won't understand "IN ()", so DWIM
my $sql = ($op =~ /\bnot\b/i) ? $self->{sqltrue} : $self->{sqlfalse};
},
{
where => {
- start0 => { -between => [ 1, 2 ] },
+ start0 => { -between => [ 1, { -upper => 2 } ] },
start1 => { -between => \["? AND ?", 1, 2] },
start2 => { -between => \"lower(x) AND upper(y)" },
start3 => { -between => [
] },
},
stmt => "WHERE (
- ( start0 BETWEEN ? AND ? )
+ ( start0 BETWEEN ? AND upper ? )
AND ( start1 BETWEEN ? AND ? )
AND ( start2 BETWEEN lower(x) AND upper(y) )
AND ( start3 BETWEEN lower(x) AND upper(?) )
bind => [2000],
test => '-in POD test',
},
+ {
+ where => { x => { -in => [ \['LOWER(?)', 'A' ], \'LOWER(b)', { -lower => 'c' } ] } },
+ stmt => " WHERE ( x IN ( LOWER(?), LOWER(b), LOWER ? ) )",
+ bind => [qw/A c/],
+ test => '-in with an array of function array refs with args',
+ },
);
plan tests => @in_between_tests*4;