3 class SQL::Abstract::Compat {
5 use Moose::Util::TypeConstraints;
6 use MooseX::Types::Moose qw/Str ScalarRef ArrayRef HashRef/;
7 use SQL::Abstract::Types::Compat ':all';
8 use SQL::Abstract::Types qw/AST/;
9 use SQL::Abstract::AST::v1;
10 use Data::Dump qw/pp/;
11 use Devel::PartialDump qw/dump/;
14 class_type 'SQL::Abstract';
27 isa => 'SQL::Abstract',
28 clearer => 'clear_visitor',
30 builder => '_build_visitor',
47 predicate => 'has_field_convertor'
50 method select(Str|ArrayRef|ScalarRef $from, ArrayRef|Str $fields,
54 my $ast = $self->select_ast($from,$fields,$where,$order);
56 return ($self->visitor->dispatch($ast), $self->visitor->binds);
58 method select_ast(Str|ArrayRef|ScalarRef $from, ArrayRef|Str $fields,
67 } ( is_Str($fields) ? $fields : @$fields )
69 tablespec => $self->tablespec($from)
73 $ast->{where} = $self->recurse_where($where)
78 method where(WhereType $where,
84 my $ast = $self->recurse_where($where);
85 $ret .= "WHERE " . $self->visitor->_expr($ast);
91 method _build_visitor() {
92 return SQL::Abstract->create(1);
96 my ($self, $use_convert) = (shift,shift);
97 my $ast = { -type => 'name', args => [ @_ ] };
100 unless $use_convert && $self->has_field_convertor;
102 return $self->apply_convert($ast);
105 method tablespec(Str|ArrayRef|ScalarRef $from) {
106 return $self->mk_name(0, $from)
110 method recurse_where(WhereType $ast, LogicEnum $logic?) returns (AST) {
111 return $self->recurse_where_hash($logic || 'AND', $ast) if is_HashRef($ast);
112 return $self->recurse_where_array($logic || 'OR', $ast) if is_ArrayRef($ast);
113 croak "Unknown where clause type " . dump($ast);
116 # Deals with where({ .... }) case
117 method recurse_where_hash(LogicEnum $logic, HashRef $ast) returns (AST) {
125 for my $key ( sort keys %$ast ) {
126 my $value = $ast->{$key};
128 if ($key =~ /^-(or|and)$/) {
129 my $val = $self->recurse_where($value, uc $1);
130 if ($val->{op} eq $ret->{op}) {
131 push @args, @{$val->{args}};
139 push @args, $self->field($key, $value);
142 return $args[0] if @args == 1;
147 # Deals with where([ .... ]) case
148 method recurse_where_array(LogicEnum $logic, ArrayRef $ast) returns (AST) {
157 while (my $key = shift @nodes) {
158 if ($key =~ /^-(or|and)$/) {
159 my $value = shift @nodes
160 or confess "missing value after $key at " . dump($ast);
162 my $val = $self->recurse_where($value, uc $1);
163 if ($val->{op} eq $ret->{op}) {
164 push @args, @{$val->{args}};
172 push @args, $self->recurse_where($key);
175 return $args[0] if @args == 1;
180 # { field => { .... } } case
181 method field_hash(Str $key, HashRef $value) returns (AST) {
182 my ($op, @rest) = keys %$value;
184 confess "Don't know how to handle " . dump($value) . " (too many keys)"
187 $value = $value->{$op};
193 $self->mk_name(1, $key)
198 # TODO: Validate the op?
199 # 'word_like' operator
200 if ($op =~ /^-?(?:(not)[_ ])?([a-z_]+)$/i) {
202 $ret->{op} = "not_" . $ret->{op} if $1;
205 if (is_ArrayRef($value)) {
206 push @{$ret->{args}}, $self->value($_) for @{$value};
212 # field => { '!=' => [ 'a','b','c'] }
213 # field => { '<' => [ 'a','b','c'] }
215 # *not* when op is a work or function operator - basic cmp operator only
216 if (is_ArrayRef($value)) {
217 local $self->{cmp} = $op;
222 # Handle e => { '!=', [qw(f g)] }.
223 # SQLA treats this as a 'DWIM' since e != f AND e != g doesn't make sense
224 op => $op eq '!=' ? 'or' : 'and',
226 $self->field($key, $_)
233 push @{$ret->{args}}, $self->value($value);
237 # Handle [ { ... }, { ... } ]
238 method field_array(Str $key, ArrayRef $value) {
239 # Return an or clause, sort of.
244 $self->field($key, $_)
249 method field(Str $key, $value) returns (AST) {
251 if (is_HashRef($value)) {
252 return $self->field_hash($key, $value);
254 elsif (is_ArrayRef($value)) {
255 return $self->field_array($key, $value);
260 op => $CMP_MAP{$self->cmp} || $self->cmp,
262 $self->mk_name(1, $key),
270 method value($value) returns (AST) {
271 return $self->apply_convert( { -type => 'value', value => $value })
274 confess "Don't know how to handle terminal value " . dump($value);
277 method apply_convert(AST $ast) {
278 return $ast unless $self->has_field_convertor;
282 op => $self->convert,
292 SQL::Abstract::Compant - compatibility layer for SQL::Abstrct v 1.xx
296 This class attempts to maintain the original behaviour of version 1 of
297 SQL::Abstract. It does this by internally converting to an AST and then using
298 the standard AST visitor.
300 If so desired, you can get hold of this transformed AST somehow. This is aimed
301 at libraries such as L<DBIx::Class> that use SQL::Abstract-style arrays or
302 hashes as part of their public interface.
306 Ash Berlin C<< <ash@cpan.org> >>