Commit | Line | Data |
79d30ac3 |
1 | package SQL::Abstract::Reference; |
2 | |
3 | 1; |
4 | |
5 | __END__ |
6 | =head1 NAME |
7 | |
8 | SQL::Abstract::Reference - Reference documentation for L<SQL::Abstract> |
9 | |
10 | =head1 TERMS |
11 | |
12 | =head2 Expression (expr) |
13 | |
14 | The DWIM structure that's passed to most methods by default is referred to |
15 | as expression syntax. If you see a variable with C<expr> in the name, or a |
16 | comment before a code block saying C<# expr>, this is what's being described. |
17 | |
18 | =head2 Abstract Query Tree (aqt) |
19 | |
20 | The explicit structure that an expression is converted into before it's |
21 | rendered into SQL is referred to as an abstract query tree. If you see a |
22 | variable with C<aqt> in the name, or a comment before a code block saying |
23 | C<# aqt>#, this is what's being described. |
24 | |
25 | =head2 SQL and Bind Values (query) |
26 | |
27 | The final result of L<SQL::Abstract> rendering is generally an SQL statement |
28 | plus bind values for passing to DBI, ala: |
29 | |
30 | my ($sql, @bind) = $sqla->some_method(@args); |
31 | my @hashes = @{$dbh->do($sql, { Slice => {} }, @bind)}; |
32 | |
33 | If you see a comment before a code block saying C<# query>, the SQL + bind |
34 | array is what's being described. |
35 | |
36 | =head1 AQT node types |
37 | |
38 | An AQT node consists of a hashref with a single key, whose name is C<-type> |
39 | where 'type' is the node type, and whose value is the data for the node. |
40 | |
41 | =head2 literal |
42 | |
43 | # expr |
44 | { -literal => [ 'SPANG(?, ?)', 1, 27 ] } |
45 | |
46 | # query |
47 | SPANG(?, ?) |
48 | [ 1, 27 ] |
49 | |
50 | =head2 ident |
51 | |
52 | # expr |
53 | { -ident => 'foo' } |
54 | |
55 | # query |
56 | foo |
57 | [] |
58 | |
59 | # expr |
60 | { -ident => [ 'foo', 'bar' ] } |
61 | |
62 | # query |
63 | foo.bar |
64 | [] |
65 | |
66 | =head2 bind |
67 | |
68 | # expr |
69 | { -bind => [ 'colname', 'value' ] } |
70 | |
71 | # query |
72 | ? |
73 | [ 'value' ] |
74 | |
75 | =head2 row |
76 | |
77 | # expr |
78 | { |
79 | -row => [ { -bind => [ 'r', 1 ] }, { -ident => [ 'clown', 'car' ] } ] |
80 | } |
81 | |
82 | # query |
83 | (?, clown.car) |
84 | [ 1 ] |
85 | |
86 | =head2 func |
87 | |
88 | # expr |
89 | { |
90 | -func => [ 'foo', { -ident => [ 'bar' ] }, { -bind => [ undef, 7 ] } ] |
91 | } |
92 | |
93 | # query |
94 | FOO(bar, ?) |
95 | [ 7 ] |
96 | |
97 | =head2 op |
98 | |
99 | Standard binop: |
100 | |
101 | # expr |
102 | { -op => [ |
103 | '=', { -ident => [ 'bomb', 'status' ] }, |
104 | { -value => 'unexploded' }, |
105 | ] } |
106 | |
107 | # query |
108 | bomb.status = ? |
109 | [ 'unexploded' ] |
110 | |
111 | Not: |
112 | |
113 | # expr |
114 | { -op => [ 'not', { -ident => 'explosive' } ] } |
115 | |
116 | # query |
117 | (NOT explosive) |
118 | [] |
119 | |
120 | Postfix unop: (is_null, is_not_null, asc, desc) |
121 | |
122 | # expr |
123 | { -op => [ 'is_null', { -ident => [ 'bobby' ] } ] } |
124 | |
125 | # query |
126 | bobby IS NULL |
127 | [] |
128 | |
129 | AND and OR: |
130 | |
131 | # expr |
132 | { -op => |
133 | [ 'and', { -ident => 'x' }, { -ident => 'y' }, { -ident => 'z' } ] |
134 | } |
135 | |
136 | # query |
137 | ( x AND y AND z ) |
138 | [] |
139 | |
140 | IN (and NOT IN): |
141 | |
142 | # expr |
143 | { -op => [ |
144 | 'in', { -ident => 'card' }, { -bind => [ 'card', 3 ] }, |
145 | { -bind => [ 'card', 'J' ] }, |
146 | ] } |
147 | |
148 | # query |
149 | card IN ( ?, ? ) |
150 | [ 3, 'J' ] |
151 | |
152 | BETWEEN (and NOT BETWEEN): |
153 | |
154 | # expr |
155 | { -op => [ |
156 | 'between', { -ident => 'pints' }, { -bind => [ 'pints', 2 ] }, |
157 | { -bind => [ 'pints', 4 ] }, |
158 | ] } |
159 | |
160 | # query |
161 | ( pints BETWEEN ? AND ? ) |
162 | [ 2, 4 ] |
163 | |
164 | Comma (use -row for parens): |
165 | |
166 | # expr |
167 | { -op => [ ',', { -literal => [ 1 ] }, { -literal => [ 2 ] } ] } |
168 | |
169 | # query |
170 | 1, 2 |
171 | [] |
172 | |
173 | =head2 values |
174 | |
175 | # expr |
176 | { -values => |
177 | { -row => [ { -bind => [ undef, 1 ] }, { -bind => [ undef, 2 ] } ] } |
178 | } |
179 | |
180 | # query |
181 | VALUES (?, ?) |
182 | [ 1, 2 ] |
183 | |
184 | # expr |
185 | { -values => [ |
186 | { -row => [ { -literal => [ 1 ] }, { -literal => [ 2 ] } ] }, |
187 | { -row => [ { -literal => [ 3 ] }, { -literal => [ 4 ] } ] }, |
188 | ] } |
189 | |
190 | # query |
191 | VALUES (1, 2), (3, 4) |
192 | [] |
193 | |
194 | =head2 statement types |
195 | |
196 | AQT node types are also provided for C<select>, C<insert>, C<update> and |
197 | C<delete>. These types are handled by the clauses system as discussed later. |
198 | |
199 | =head1 Expressions |
200 | |
201 | The simplest expression is just an AQT node: |
202 | |
203 | # expr |
204 | { -ident => [ 'foo', 'bar' ] } |
205 | |
206 | # aqt |
207 | { -ident => [ 'foo', 'bar' ] } |
208 | |
209 | # query |
210 | foo.bar |
211 | [] |
212 | |
213 | However, even in the case of an AQT node, the node value will be expanded if |
214 | an expander has been registered for that node type: |
215 | |
216 | # expr |
217 | { -ident => 'foo.bar' } |
218 | |
219 | # aqt |
220 | { -ident => [ 'foo', 'bar' ] } |
221 | |
222 | # query |
223 | foo.bar |
224 | [] |
225 | |
226 | =head2 |