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 method recurse_where_hash(LogicEnum $logic, HashRef $ast) returns (AST) {
124 for my $key ( sort keys %$ast ) {
125 my $value = $ast->{$key};
127 if ($key =~ /^-(or|and)$/) {
128 my $val = $self->recurse_where($value, uc $1);
129 if ($val->{op} eq $ret->{op}) {
130 push @args, @{$val->{args}};
138 push @args, $self->field($key, $value);
141 return $args[0] if @args == 1;
146 method recurse_where_array(LogicEnum $logic, ArrayRef $ast) returns (AST) {
155 while (my $key = shift @nodes) {
156 if ($key =~ /^-(or|and)$/) {
157 my $value = shift @nodes
158 or confess "missing value after $key at " . dump($ast);
160 my $val = $self->recurse_where($value, uc $1);
161 if ($val->{op} eq $ret->{op}) {
162 push @args, @{$val->{args}};
170 push @args, $self->recurse_where($key);
173 return $args[0] if @args == 1;
178 method field(Str $key, $value) returns (AST) {
179 my $op = $CMP_MAP{$self->cmp} || $self->cmp;
184 $self->mk_name(1, $key)
188 if (is_HashRef($value)) {
189 my ($op, @rest) = keys %$value;
190 confess "Don't know how to handle " . dump($value) . " (too many keys)"
192 $value = $value->{$op};
194 # TODO: Validate the op?
195 if ($op =~ /^-?(?:(not)[_ ])?([a-z_]+)$/i) {
197 $ret->{op} = "not_" . $ret->{op} if $1;
199 if (is_ArrayRef($value)) {
200 push @{$ret->{args}}, $self->value($_)
209 if (is_ArrayRef($value)) {
210 local $self->{cmp} = $op;
214 # Handle e => { '!=', [qw(f g)] }.
215 # SQLA treats this as a 'DWIM'
216 op => $op eq '!=' ? 'or' : 'and',
218 $self->field($key, $_)
223 push @{$ret->{args}}, $self->value($value);
226 elsif (is_ArrayRef($value)) {
227 # Return an or clause, sort of.
232 $self->field($key, $_)
237 push @{$ret->{args}}, $self->value($value);
243 method value($value) returns (AST) {
244 return $self->apply_convert( { -type => 'value', value => $value })
247 confess "Don't know how to handle terminal value " . dump($value);
250 method apply_convert(AST $ast) {
251 return $ast unless $self->has_field_convertor;
255 op => $self->convert,
265 SQL::Abstract::Compant - compatibility layer for SQL::Abstrct v 1.xx
269 This class attempts to maintain the original behaviour of version 1 of
270 SQL::Abstract. It does this by internally converting to an AST and then using
271 the standard AST visitor.
273 If so desired, you can get hold of this transformed AST somehow. This is aimed
274 at libraries such as L<DBIx::Class> that use SQL::Abstract-style arrays or
275 hashes as part of their public interface.
279 Ash Berlin C<< <ash@cpan.org> >>