rossoc 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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