2 use MooseX::Method::Signatures;
10 use Moose::Util::TypeConstraints;
11 use MooseX::Types -declare => [qw/NameSeparator/];
12 use MooseX::Types::Moose qw/ArrayRef Str Int/;
13 use MooseX::AttributeHelpers;
17 subtype NameSeparator,
19 #where { @$_ == 1 ||| @$_ == 2 },
20 #message { "Name separator must be one or two elements" };
22 coerce NameSeparator, from Str, via { [ $_ ] };
24 our $VERSION = '2.000000';
26 our $AST_VERSION = '1';
28 # Operator precedence for bracketing
47 has name_separator => (
50 default => sub { ['.'] },
55 has list_separator => (
65 default => sub { [ ] },
66 metaclass => 'Collection::Array',
69 clear => '_clear_binds',
73 method BUILD( $ast ) {
74 croak "AST version @{[$self->ast_version]} is greater than supported version of $AST_VERSION"
75 if $self->ast_version > $AST_VERSION;
79 method generate(ClassName $class: ArrayRef $ast) {
80 croak "SQL::Abstract AST version not specified"
81 unless ($ast->[0] eq '-ast_version');
83 my (undef, $ver) = splice(@$ast, 0, 2);
85 my $self = $class->new(ast_version => $ver);
87 return ($self->dispatch($ast), $self->binds);
90 method dispatch (ArrayRef $ast) {
93 s/^-/_/g or croak "Unknown type tag '$_'";
94 my $meth = $self->can($_) || \&_generic_func;
95 return $meth->($self, $ast);
98 method _select(ArrayRef $ast) {
102 method _where(ArrayRef $ast) {
103 my (undef, @clauses) = @$ast;
105 return 'WHERE ' . $self->_recurse_where(\@clauses);
108 method _order_by(ArrayRef $ast) {
109 my (undef, @clauses) = @$ast;
114 if ($_->[0] =~ /^-(asc|desc)$/) {
116 push @output, $self->dispatch($_->[1]) . " " . uc($o);
119 push @output, $self->dispatch($_);
122 return "ORDER BY " . join(", ", @output);
125 method _name(ArrayRef $ast) {
126 my (undef, @names) = @$ast;
128 my $sep = $self->name_separator;
131 join( $sep->[1] . $sep->[0], @names ) .
135 return join($sep->[0], @names);
138 method _join(ArrayRef $ast) {
142 method _list(ArrayRef $ast) {
143 my (undef, @items) = @$ast;
146 $self->list_separator,
147 map { $self->dispatch($_) } @items);
150 method _alias(ArrayRef $ast) {
151 my (undef, $alias, $as) = @$ast;
153 return $self->dispatch($alias) . " AS $as";
157 method _value(ArrayRef $ast) {
158 my ($undef, $value) = @$ast;
160 $self->add_bind($value);
164 method _recurse_where($clauses) {
167 my $prio = $PRIO{and};
168 my $first = $clauses->[0];
170 if (!ref $first && $first =~ /^-(and|or)$/) {
177 foreach (@$clauses) {
178 croak "invalid component in where clause" unless ArrayRef->check($_);
181 unless (substr($op, 0, 1) eq '-') {
182 # A simple comparison op (==, >, etc.)
184 push @output, $self->_binop(@$_);
186 } elsif ($op =~ /^-(and|or)$/) {
187 my $sub_prio = $PRIO{$1};
189 if ($sub_prio <= $prio) {
190 push @output, $self->_recurse_where($_);
192 push @output, '(' . $self->_recurse_where($_) . ')';
195 push @output, $self->dispatch($_);
199 return join(" $OP ", @output);
202 method _binop($op, $lhs, $rhs) {
203 join (' ', $self->dispatch($lhs),
204 $OP_MAP{$op} || croak("Unknown binary operator $op"),
205 $self->dispatch($rhs)
210 my (undef, $field, @values) = @$ast;
212 return $self->dispatch($field) .
214 join(", ", map { $self->dispatch($_) } @values ) .
218 method _generic_func(ArrayRef $ast) {