Commit | Line | Data |
a0185af2 |
1 | use MooseX::Declare; |
a0185af2 |
2 | |
a0185af2 |
3 | class SQL::Abstract { |
4 | |
5 | use Carp qw/croak/; |
6 | use Data::Dump qw/pp/; |
7 | |
8 | use Moose::Util::TypeConstraints; |
0c371882 |
9 | use MooseX::Types::Moose qw/ArrayRef Str Int HashRef CodeRef/; |
4769c837 |
10 | use MooseX::AttributeHelpers; |
bad761ba |
11 | use SQL::Abstract::Types qw/NameSeparator QuoteChars AST/; |
747f7c21 |
12 | use Devel::PartialDump qw/dump/; |
4769c837 |
13 | |
a0185af2 |
14 | our $VERSION = '2.000000'; |
15 | |
16 | our $AST_VERSION = '1'; |
17 | |
3e63a4d5 |
18 | # Operator precedence for bracketing |
19 | our %PRIO = ( |
20 | and => 10, |
21 | or => 50 |
22 | ); |
23 | |
0bf8a8c4 |
24 | our %BINOP_MAP = ( |
fc20481d |
25 | |
26 | '+' => '+', |
27 | '-' => '-', |
28 | '/' => '/', |
29 | '*' => '*', |
30 | |
3e63a4d5 |
31 | '>' => '>', |
64f3d05e |
32 | '>=' => '>=', |
3e63a4d5 |
33 | '<' => '<', |
64f3d05e |
34 | '<=' => '<=', |
3e63a4d5 |
35 | '==' => '=', |
36 | '!=' => '!=', |
0bf8a8c4 |
37 | # LIKE is always "field LIKE <value>" |
db861e66 |
38 | 'like' => 'LIKE', |
39 | 'not_like' => 'NOT LIKE', |
3e63a4d5 |
40 | ); |
41 | |
ef0d6124 |
42 | has expr_dispatch_table => ( |
0bf8a8c4 |
43 | is => 'ro', |
eb22ecd3 |
44 | lazy => 1, |
ef0d6124 |
45 | builder => '_build_expr_dispatch_table', |
0c371882 |
46 | isa => HashRef[CodeRef], |
47 | metaclass => 'Collection::ImmutableHash', |
48 | provides => { |
ef0d6124 |
49 | get => 'lookup_expr_dispatch' |
0c371882 |
50 | } |
0bf8a8c4 |
51 | ); |
52 | |
53 | has binop_map => ( |
54 | is => 'ro', |
eb22ecd3 |
55 | lazy => 1, |
56 | builder => '_build_binops', |
0bf8a8c4 |
57 | isa => HashRef, |
58 | metaclass => 'Collection::ImmutableHash', |
59 | provides => { |
60 | exists => 'is_valid_binop', |
61 | get => 'binop_mapping', |
62 | keys => 'binary_operators' |
63 | } |
64 | ); |
65 | |
eb22ecd3 |
66 | # List of default binary operators (for in where clauses) |
67 | sub _build_binops { return {%BINOP_MAP} }; |
0bf8a8c4 |
68 | |
ef0d6124 |
69 | method _build_expr_dispatch_table { |
0c371882 |
70 | my $binop = $self->can('_binop') or croak "InternalError: $self can't do _binop!"; |
0bf8a8c4 |
71 | return { |
72 | map { $_ => $binop } $self->binary_operators |
73 | } |
74 | } |
75 | |
c314b35d |
76 | has ast_version => ( |
77 | is => 'ro', |
78 | isa => Int, |
79 | required => 1 |
80 | ); |
81 | |
627dcb62 |
82 | has ident_separator => ( |
a0185af2 |
83 | is => 'rw', |
84 | isa => NameSeparator, |
4ee32f41 |
85 | default => '.', |
a0185af2 |
86 | required => 1, |
87 | ); |
88 | |
89 | has list_separator => ( |
90 | is => 'rw', |
91 | isa => Str, |
92 | default => ', ', |
93 | required => 1, |
94 | ); |
95 | |
4ee32f41 |
96 | has quote_chars => ( |
97 | is => 'rw', |
98 | isa => QuoteChars, |
4ee32f41 |
99 | predicate => 'is_quoting', |
100 | clearer => 'disable_quoting', |
8eda2119 |
101 | coerce => 1, |
4ee32f41 |
102 | ); |
103 | |
4769c837 |
104 | has binds => ( |
105 | isa => ArrayRef, |
5bf8c024 |
106 | is => 'ro', |
0bf8a8c4 |
107 | clearer => '_clear_binds', |
108 | lazy => 1, |
4769c837 |
109 | default => sub { [ ] }, |
110 | metaclass => 'Collection::Array', |
111 | provides => { |
112 | push => 'add_bind', |
4769c837 |
113 | } |
114 | ); |
115 | |
14774be0 |
116 | # TODO: once MXMS supports %args, use that here |
e76b9ff7 |
117 | # TODO: improve this so you can pass other args |
14774be0 |
118 | method create(ClassName $class: Int $ver) { |
119 | croak "AST version $ver is greater than supported version of $AST_VERSION" |
120 | if $ver > $AST_VERSION; |
121 | |
122 | my $name = "${class}::AST::v$ver"; |
123 | Class::MOP::load_class($name); |
124 | |
125 | return $name->new(ast_version => $ver); |
c314b35d |
126 | } |
127 | |
128 | # Main entry point |
bad761ba |
129 | method generate(ClassName $class: AST $ast) { |
a464be15 |
130 | my $ver = $ast->{-ast_version}; |
c314b35d |
131 | croak "SQL::Abstract AST version not specified" |
a464be15 |
132 | unless defined $ver; |
c314b35d |
133 | |
14774be0 |
134 | # TODO: once MXMS supports %args, use that here |
135 | my $self = $class->create($ver); |
c314b35d |
136 | |
137 | return ($self->dispatch($ast), $self->binds); |
138 | } |
139 | |
0bf8a8c4 |
140 | method reset() { |
141 | $self->_clear_binds(); |
142 | } |
143 | |
cbcfedc1 |
144 | method dispatch (AST $ast) { |
f7dc4536 |
145 | |
bad761ba |
146 | my $tag = "_" . $ast->{-type}; |
0bf8a8c4 |
147 | |
cbcfedc1 |
148 | my $meth = $self->can($tag) || croak "Unknown tag '$tag'"; |
0bf8a8c4 |
149 | return $meth->($self, $ast); |
150 | } |
4769c837 |
151 | |
a0185af2 |
152 | }; |
c8c2694a |
153 | |
154 | __END__ |
155 | |
156 | =head1 NAME |
157 | |
158 | SQL::Abstract - AST based re-implementation of SQL::Abstract |
159 | |
160 | =head1 LICENSE |
161 | |
162 | =head1 AUTHORS |
163 | |
164 | Ash Berlin C<< <ash@cpan.org> >> |
165 | |
166 | =head1 LICENSE |
167 | |
168 | This program is free software; you can redistribute it and/or modify it under |
169 | the same terms as Perl itself. |
170 | |