sql-parser-vlad 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,366 @@
1
+ module SQLParser
2
+
3
+ class SQLVisitor
4
+
5
+ def initialize
6
+ @negated = false
7
+ end
8
+
9
+ def visit(node)
10
+ node.accept(self)
11
+ end
12
+
13
+ def visit_Insert(o)
14
+ name = visit(o.table_reference)
15
+ columns = ' ' + visit(o.column_list) if o.column_list
16
+ values = ' VALUES ' + visit(o.in_value_list)
17
+ "INSERT INTO #{name}#{columns}#{values}"
18
+ end
19
+
20
+ def visit_DirectSelect(o)
21
+ [
22
+ o.query_expression,
23
+ o.order_by
24
+ ].compact.collect { |e| visit(e) }.join(' ')
25
+ end
26
+
27
+ def visit_OrderBy(o)
28
+ "ORDER BY #{arrayize(o.sort_specification)}"
29
+ end
30
+
31
+ def visit_Subquery(o)
32
+ "(#{visit(o.query_specification)})"
33
+ end
34
+
35
+ def visit_Select(o)
36
+ # FIXME: This feels like a hack
37
+ initialize
38
+
39
+ if o.filter.nil?
40
+ "SELECT #{visit_all([o.list, o.table_expression].compact).join(' ')}"
41
+ else
42
+ "SELECT #{o.filter} #{visit_all([o.list, o.table_expression].compact).join(' ')}"
43
+ end
44
+ end
45
+
46
+ def visit_SelectList(o)
47
+ arrayize(o.columns)
48
+ end
49
+
50
+ def visit_Distinct(o)
51
+ "DISTINCT(#{visit(o.column)})"
52
+ end
53
+
54
+ def visit_All(o)
55
+ '*'
56
+ end
57
+
58
+ def visit_TableExpression(o)
59
+ [
60
+ o.from_clause,
61
+ o.where_clause,
62
+ o.group_by_clause,
63
+ o.having_clause
64
+ ].compact.collect { |e| visit(e) }.join(' ')
65
+ end
66
+
67
+ def visit_FromClause(o)
68
+ "FROM #{arrayize(o.tables)}"
69
+ end
70
+
71
+ def visit_OrderClause(o)
72
+ "ORDER BY #{arrayize(o.columns)}"
73
+ end
74
+
75
+ def visit_Ascending(o)
76
+ "#{visit(o.column)} ASC"
77
+ end
78
+
79
+ def visit_Descending(o)
80
+ "#{visit(o.column)} DESC"
81
+ end
82
+
83
+ def visit_HavingClause(o)
84
+ "HAVING #{visit(o.search_condition)}"
85
+ end
86
+
87
+ def visit_GroupByClause(o)
88
+ "GROUP BY #{arrayize(o.columns)}"
89
+ end
90
+
91
+ def visit_WhereClause(o)
92
+ "WHERE #{visit(o.search_condition)}"
93
+ end
94
+
95
+ def visit_On(o)
96
+ "ON #{visit(o.search_condition)}"
97
+ end
98
+
99
+ def visit_Using(o)
100
+ "USING (#{arrayize(o.columns)})"
101
+ end
102
+
103
+ def visit_Or(o)
104
+ search_condition('OR', o)
105
+ end
106
+
107
+ def visit_And(o)
108
+ search_condition('AND', o)
109
+ end
110
+
111
+ def visit_Exists(o)
112
+ if @negated
113
+ "NOT EXISTS #{visit(o.table_subquery)}"
114
+ else
115
+ "EXISTS #{visit(o.table_subquery)}"
116
+ end
117
+ end
118
+
119
+ def visit_Is(o)
120
+ if @negated
121
+ comparison('IS NOT', o)
122
+ else
123
+ comparison('IS', o)
124
+ end
125
+ end
126
+
127
+ def visit_Like(o)
128
+ if @negated
129
+ comparison('NOT LIKE', o)
130
+ else
131
+ comparison('LIKE', o)
132
+ end
133
+ end
134
+
135
+ def visit_In(o)
136
+ if @negated
137
+ comparison('NOT IN', o)
138
+ else
139
+ comparison('IN', o)
140
+ end
141
+ end
142
+
143
+ def visit_InColumnList(o)
144
+ "(#{arrayize(o.columns)})"
145
+ end
146
+
147
+ def visit_InValueList(o)
148
+ "(#{arrayize(o.values)})"
149
+ end
150
+
151
+ def visit_Between(o)
152
+ if @negated
153
+ "#{visit(o.left)} NOT BETWEEN #{visit(o.min)} AND #{visit(o.max)}"
154
+ else
155
+ "#{visit(o.left)} BETWEEN #{visit(o.min)} AND #{visit(o.max)}"
156
+ end
157
+ end
158
+
159
+ def visit_GreaterOrEquals(o)
160
+ comparison('>=', o)
161
+ end
162
+
163
+ def visit_LessOrEquals(o)
164
+ comparison('<=', o)
165
+ end
166
+
167
+ def visit_Greater(o)
168
+ comparison('>', o)
169
+ end
170
+
171
+ def visit_Less(o)
172
+ comparison('<', o)
173
+ end
174
+
175
+ def visit_Equals(o)
176
+ if @negated
177
+ comparison('<>', o)
178
+ else
179
+ comparison('=', o)
180
+ end
181
+ end
182
+
183
+ def visit_Sum(o)
184
+ aggregate('SUM', o)
185
+ end
186
+
187
+ def visit_Minimum(o)
188
+ aggregate('MIN', o)
189
+ end
190
+
191
+ def visit_Maximum(o)
192
+ aggregate('MAX', o)
193
+ end
194
+
195
+ def visit_Average(o)
196
+ aggregate('AVG', o)
197
+ end
198
+
199
+ def visit_Count(o)
200
+ aggregate('COUNT', o)
201
+ end
202
+
203
+ def visit_CrossJoin(o)
204
+ "#{visit(o.left)} CROSS JOIN #{visit(o.right)}"
205
+ end
206
+
207
+ def visit_InnerJoin(o)
208
+ qualified_join('INNER', o)
209
+ end
210
+
211
+ def visit_LeftJoin(o)
212
+ qualified_join('LEFT', o)
213
+ end
214
+
215
+ def visit_LeftOuterJoin(o)
216
+ qualified_join('LEFT OUTER', o)
217
+ end
218
+
219
+ def visit_RightJoin(o)
220
+ qualified_join('RIGHT', o)
221
+ end
222
+
223
+ def visit_RightOuterJoin(o)
224
+ qualified_join('RIGHT OUTER', o)
225
+ end
226
+
227
+ def visit_FullJoin(o)
228
+ qualified_join('FULL', o)
229
+ end
230
+
231
+ def visit_FullOuterJoin(o)
232
+ qualified_join('FULL OUTER', o)
233
+ end
234
+
235
+ def visit_Table(o)
236
+ quote(o.name)
237
+ end
238
+
239
+ def visit_QualifiedColumn(o)
240
+ "#{visit(o.table)}.#{visit(o.column)}"
241
+ end
242
+
243
+ def visit_Column(o)
244
+ quote(o.name)
245
+ end
246
+
247
+ def visit_As(o)
248
+ "#{visit(o.value)} AS #{visit(o.column)}"
249
+ end
250
+
251
+ def visit_Multiply(o)
252
+ arithmetic('*', o)
253
+ end
254
+
255
+ def visit_Divide(o)
256
+ arithmetic('/', o)
257
+ end
258
+
259
+ def visit_Add(o)
260
+ arithmetic('+', o)
261
+ end
262
+
263
+ def visit_Subtract(o)
264
+ arithmetic('-', o)
265
+ end
266
+
267
+ def visit_Not(o)
268
+ negate { visit(o.value) }
269
+ end
270
+
271
+ def visit_UnaryPlus(o)
272
+ "+#{visit(o.value)}"
273
+ end
274
+
275
+ def visit_UnaryMinus(o)
276
+ "-#{visit(o.value)}"
277
+ end
278
+
279
+ def visit_True(o)
280
+ 'TRUE'
281
+ end
282
+
283
+ def visit_False(o)
284
+ 'FALSE'
285
+ end
286
+
287
+ def visit_Null(o)
288
+ 'NULL'
289
+ end
290
+
291
+ def visit_CurrentUser(o)
292
+ 'CURRENT_USER'
293
+ end
294
+
295
+ def visit_DateTime(o)
296
+ "'%s'" % escape(o.value.strftime('%Y-%m-%d %H:%M:%S'))
297
+ end
298
+
299
+ def visit_Date(o)
300
+ "DATE '%s'" % escape(o.value.strftime('%Y-%m-%d'))
301
+ end
302
+
303
+ def visit_String(o)
304
+ "'%s'" % escape(o.value)
305
+ end
306
+
307
+ def visit_ApproximateFloat(o)
308
+ "#{visit(o.mantissa)}E#{visit(o.exponent)}"
309
+ end
310
+
311
+ def visit_Float(o)
312
+ o.value.to_s
313
+ end
314
+
315
+ def visit_Integer(o)
316
+ o.value.to_s
317
+ end
318
+
319
+ private
320
+
321
+ def negate
322
+ @negated = true
323
+ yield
324
+ ensure
325
+ @negated = false
326
+ end
327
+
328
+ def quote(str)
329
+ "`#{str}`"
330
+ end
331
+
332
+ def escape(str)
333
+ str.gsub(/'/, "''")
334
+ end
335
+
336
+ def arithmetic(operator, o)
337
+ search_condition(operator, o)
338
+ end
339
+
340
+ def comparison(operator, o)
341
+ [visit(o.left), operator, visit(o.right)].join(' ')
342
+ end
343
+
344
+ def search_condition(operator, o)
345
+ "(#{visit(o.left)} #{operator} #{visit(o.right)})"
346
+ end
347
+
348
+ def visit_all(nodes)
349
+ nodes.collect { |e| visit(e) }
350
+ end
351
+
352
+ def arrayize(arr)
353
+ visit_all(arr).join(', ')
354
+ end
355
+
356
+ def aggregate(function_name, o)
357
+ "#{function_name}(#{visit(o.column)})"
358
+ end
359
+
360
+ def qualified_join(join_type, o)
361
+ "#{visit(o.left)} #{join_type} JOIN #{visit(o.right)} #{visit(o.search_condition)}"
362
+ end
363
+
364
+ end
365
+
366
+ end