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)
109 method recurse_where(WhereType $ast, LogicEnum $logic?) returns (AST) {
110 return $self->recurse_where_hash($logic || 'AND', $ast) if is_HashRef($ast);
111 return $self->recurse_where_array($logic || 'OR', $ast) if is_ArrayRef($ast);
112 croak "Unknown where clause type " . dump($ast);
115 # Deals with where({ .... }) case
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 # Deals with where([ .... ]) case
147 method recurse_where_array(LogicEnum $logic, ArrayRef $ast) returns (AST) {
156 while (my $key = shift @nodes) {
157 if ($key =~ /^-(or|and)$/) {
158 my $value = shift @nodes
159 or confess "missing value after $key at " . dump($ast);
161 my $val = $self->recurse_where($value, uc $1);
162 if ($val->{op} eq $ret->{op}) {
163 push @args, @{$val->{args}};
171 push @args, $self->recurse_where($key);
174 return $args[0] if @args == 1;
179 # { field => { .... } } case
180 method field_hash(Str $key, HashRef $value) returns (AST) {
181 my ($op, @rest) = keys %$value;
183 confess "Don't know how to handle " . dump($value) . " (too many keys)"
186 $value = $value->{$op};
192 $self->mk_name(1, $key)
197 # TODO: Validate the op?
198 # 'word_like' operator
199 if ($op =~ /^-?(?:(not)[_ ])?([a-z_]+)$/i) {
201 $ret->{op} = "not_" . $ret->{op} if $1;
204 if (is_ArrayRef($value)) {
205 push @{$ret->{args}}, $self->value($_) for @{$value};
211 # field => { '!=' => [ 'a','b','c'] }
212 # field => { '<' => [ 'a','b','c'] }
214 # *not* when op is a work or function operator - basic cmp operator only
215 if (is_ArrayRef($value)) {
216 local $self->{cmp} = $op;
222 $self->field($key, $_)
229 push @{$ret->{args}}, $self->value($value);
233 # Handle [ { ... }, { ... } ]
234 method field_array(Str $key, ArrayRef $value) {
235 # Return an or clause, sort of.
240 $self->field($key, $_)
245 method field(Str $key, $value) returns (AST) {
247 if (is_HashRef($value)) {
248 return $self->field_hash($key, $value);
250 elsif (is_ArrayRef($value)) {
251 return $self->field_array($key, $value);
256 op => $CMP_MAP{$self->cmp} || $self->cmp,
258 $self->mk_name(1, $key),
266 method value($value) returns (AST) {
267 return $self->apply_convert( { -type => 'value', value => $value })
270 confess "Don't know how to handle terminal value " . dump($value);
273 method apply_convert(AST $ast) {
274 return $ast unless $self->has_field_convertor;
278 op => $self->convert,
288 SQL::Abstract::Compant - compatibility layer for SQL::Abstrct v 1.xx
292 This class attempts to maintain the original behaviour of version 1 of
293 SQL::Abstract. It does this by internally converting to an AST and then using
294 the standard AST visitor.
296 If so desired, you can get hold of this transformed AST somehow. This is aimed
297 at libraries such as L<DBIx::Class> that use SQL::Abstract-style arrays or
298 hashes as part of their public interface.
302 Ash Berlin C<< <ash@cpan.org> >>