rossoc 0.9.0

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