use Moose::Util::TypeConstraints;
use MooseX::Types -declare => [qw/NameSeparator/];
- use MooseX::Types::Moose qw/ArrayRef Str Int HashRef/;
+ use MooseX::Types::Moose qw/ArrayRef Str Int HashRef CodeRef/;
use MooseX::AttributeHelpers;
clean;
has where_dispatch_table => (
is => 'ro',
lazy_build => 1,
+ isa => HashRef[CodeRef],
+ metaclass => 'Collection::ImmutableHash',
+ provides => {
+ get => 'lookup_where_dispatch'
+ }
);
has binop_map => (
sub _build_binop_map { return {%BINOP_MAP} };
method _build_where_dispatch_table {
- my $binop = $self->can('_binop');
+ my $binop = $self->can('_binop') or croak "InternalError: $self can't do _binop!";
return {
map { $_ => $binop } $self->binary_operators
}
clean;
+ # set things that are valid in where clauses
override _build_where_dispatch_table {
return {
%{super()},
-in => $self->can('_in'),
- -not_in => $self->can('_in')
+ -not_in => $self->can('_in'),
+ map { +"-$_" => $self->can("_$_") } qw/
+ value
+ name
+ true
+ false
+ /
};
}
my @output;
foreach (@$clauses) {
- croak "invalid component in where clause" unless ArrayRef->check($_);
+ croak "invalid component in where clause: $_" unless ArrayRef->check($_);
my $op = $_->[0];
- if (my $code = $dispatch_table->{$op}) {
-
- push @output, $code->($self, $_);
-
- } elsif ($op =~ /^-(and|or)$/) {
+ if ($op =~ /^-(and|or)$/) {
my $sub_prio = $SQL::Abstract::PRIO{$1};
if ($sub_prio <= $prio) {
push @output, '(' . $self->_recurse_where($_) . ')';
}
} else {
- croak "Unknown where clause '$op'";
+ push @output, $self->_where_component($_);
}
}
return join(" $OP ", @output);
}
+ method _where_component($ast) {
+ my $op = $ast->[0];
+
+ if (my $code = $self->lookup_where_dispatch($op)) {
+
+ return $code->($self, $ast);
+
+ }
+ croak "'$op' is not a valid clause in a where AST"
+ if $op =~ /^-/;
+
+ croak "'$op' is not a valid operator";
+
+ }
+
+
method _binop($ast) {
my ($op, $lhs, $rhs) = @$ast;
- join (' ', $self->dispatch($lhs),
+ join (' ', $self->_where_component($lhs),
$self->binop_mapping($op) || croak("Unknown binary operator $op"),
- $self->dispatch($rhs)
+ $self->_where_component($rhs)
);
}
my $not = $tag =~ /^-not/ ? " NOT" : "";
return $self->_false if @values == 0;
- return $self->dispatch($field) .
+ return $self->_where_component($field) .
$not.
" IN (" .
join(", ", map { $self->dispatch($_) } @values ) .
my $not = $tag =~ /^-not/ ? " NOT" : "";
return $self->_false if @values == 0;
- return $self->dispatch($field) .
+ return $self->_where_component($field) .
$not.
- " LIKE (" .
- join(", ", map { $self->dispatch($_) } @values ) .
- ")";
+ " LIKE " .
+ join(", ", map { $self->_where_component($_) } @values ) .
+ "";
}
method _generic_func(ArrayRef $ast) {
--- /dev/null
+use strict;
+use warnings;
+
+use Test::More tests => 3;
+use Test::Exception;
+
+use_ok('SQL::Abstract') or BAIL_OUT( "$@" );
+
+my $sqla = SQL::Abstract->create(1);
+
+throws_ok {
+ $sqla->dispatch(
+ [ -where =>
+ [ '==', [-name => qw/me id/], [ -alias => [-name => qw/me foo/], 'bar' ] ]
+ ]
+ )
+} qr/^'-alias' is not a valid clause in a where AST/, "Error from invalid part in where";
+
+throws_ok {
+ $sqla->dispatch(
+ [ -where =>
+ [ '~', [-name => qw/me id/], [ -alias => [-name => qw/me foo/], 'bar' ] ]
+ ]
+ )
+} qr/^'~' is not a valid operator/,
+ "Error from invalid operator in where";