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 while (my ($key,$value) = each %$ast) {
125 if ($key =~ /^-(or|and)$/) {
126 my $val = $self->recurse_where($value, uc $1);
127 if ($val->{op} eq $ret->{op}) {
128 push @args, @{$val->{args}};
136 push @args, $self->field($key, $value);
139 return $args[0] if @args == 1;
144 method recurse_where_array(LogicEnum $logic, ArrayRef $ast) returns (AST) {
153 while (my $key = shift @nodes) {
154 if ($key =~ /^-(or|and)$/) {
155 my $value = shift @nodes
156 or confess "missing value after $key at " . dump($ast);
158 my $val = $self->recurse_where($value, uc $1);
159 if ($val->{op} eq $ret->{op}) {
160 push @args, @{$val->{args}};
168 push @args, $self->recurse_where($key);
171 return $args[0] if @args == 1;
176 method field(Str $key, $value) returns (AST) {
177 my $op = $CMP_MAP{$self->cmp} || $self->cmp;
182 $self->mk_name(1, $key)
186 if (is_HashRef($value)) {
187 my ($op, @rest) = keys %$value;
188 confess "Don't know how to handle " . dump($value) . " (too many keys)"
190 $value = $value->{$op};
192 # TODO: Validate the op?
193 if ($op =~ /^-?(?:(not)[_ ])?([a-z_]+)$/i) {
195 $ret->{op} = "not_" . $ret->{op} if $1;
197 if (is_ArrayRef($value)) {
198 push @{$ret->{args}}, $self->value($_)
207 if (is_ArrayRef($value)) {
208 local $self->{cmp} = $op;
212 # Handle e => { '!=', [qw(f g)] }.
213 # SQLA treats this as a 'DWIM'
214 op => $op eq '!=' ? 'or' : 'and',
216 $self->field($key, $_)
221 push @{$ret->{args}}, $self->value($value);
224 elsif (is_ArrayRef($value)) {
225 # Return an or clause, sort of.
230 $self->field($key, $_)
235 push @{$ret->{args}}, $self->value($value);
241 method value($value) returns (AST) {
242 return $self->apply_convert( { -type => 'value', value => $value })
245 confess "Don't know how to handle terminal value " . dump($value);
248 method apply_convert(AST $ast) {
249 return $ast unless $self->has_field_convertor;
253 op => $self->convert,
263 SQL::Abstract::Compant - compatibility layer for SQL::Abstrct v 1.xx
267 This class attempts to maintain the original behaviour of version 1 of
268 SQL::Abstract. It does this by internally converting to an AST and then using
269 the standard AST visitor.
271 If so desired, you can get hold of this transformed AST somehow. This is aimed
272 at libraries such as L<DBIx::Class> that use SQL::Abstract-style arrays or
273 hashes as part of their public interface.
277 Ash Berlin C<< <ash@cpan.org> >>