rgviz 0.2 → 0.3
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.
- data/lib/rgviz/lexer.rb +605 -0
- data/lib/rgviz/nodes.rb +437 -0
- data/lib/rgviz/parser.rb +403 -0
- data/lib/rgviz/token.rb +83 -0
- data/lib/rgviz/visitor.rb +18 -0
- metadata +8 -3
data/lib/rgviz/nodes.rb
ADDED
@@ -0,0 +1,437 @@
|
|
1
|
+
module Rgviz
|
2
|
+
class Query
|
3
|
+
attr_accessor :select
|
4
|
+
attr_accessor :where
|
5
|
+
attr_accessor :group_by
|
6
|
+
attr_accessor :pivot
|
7
|
+
attr_accessor :order_by
|
8
|
+
attr_accessor :limit
|
9
|
+
attr_accessor :offset
|
10
|
+
attr_accessor :labels
|
11
|
+
attr_accessor :formats
|
12
|
+
attr_accessor :options
|
13
|
+
|
14
|
+
def accept(visitor)
|
15
|
+
if visitor.visitQuery self
|
16
|
+
select.accept visitor if select
|
17
|
+
where.accept visitor if where
|
18
|
+
group_by.accept visitor if group_by
|
19
|
+
pivot.accept visitor if pivot
|
20
|
+
order_by.accept visitor if order_by
|
21
|
+
labels.each{|x| x.accept visitor} if labels
|
22
|
+
formats.each{|x| x.accept visitor} if formats
|
23
|
+
options.each{|x| x.accept visitor} if options
|
24
|
+
end
|
25
|
+
visitor.endVisitQuery self
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
str = ''
|
30
|
+
if select
|
31
|
+
if select.empty?
|
32
|
+
str << "select * "
|
33
|
+
else
|
34
|
+
str << "select #{select.to_s} "
|
35
|
+
end
|
36
|
+
end
|
37
|
+
str << "where #{where} " if where
|
38
|
+
str << "group_by #{group_by} " if group_by
|
39
|
+
str << "pivot #{pivot} " if pivot
|
40
|
+
str << "order by #{order_by} " if order_by
|
41
|
+
str << "limit #{limit} " if limit
|
42
|
+
str << "offset #{offset} " if offset
|
43
|
+
str << "label #{labels.map(&:to_s).join(', ')} " if labels
|
44
|
+
str << "format #{formats.map(&:to_s).join(', ')} " if formats
|
45
|
+
str << "options #{options.map(&:to_s).join(', ')} " if options
|
46
|
+
str.strip
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class ColumnsContainer
|
51
|
+
attr_accessor :columns
|
52
|
+
|
53
|
+
def initialize
|
54
|
+
@columns = []
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
@columns.map(&:to_s).join(', ')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class Select < ColumnsContainer
|
63
|
+
def accept(visitor)
|
64
|
+
if visitor.visitSelect(self)
|
65
|
+
columns.each{|x| x.accept visitor}
|
66
|
+
end
|
67
|
+
visitor.endVisitSelect self
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class GroupBy < ColumnsContainer
|
72
|
+
def accept(visitor)
|
73
|
+
if visitor.visitGroupBy(self)
|
74
|
+
columns.each{|x| x.accept visitor}
|
75
|
+
end
|
76
|
+
visitor.endVisitGroupBy self
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class Pivot < ColumnsContainer
|
81
|
+
def accept(visitor)
|
82
|
+
if visitor.visitPivot(self)
|
83
|
+
columns.each{|x| x.accept visitor}
|
84
|
+
end
|
85
|
+
visitor.endVisitPivot self
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class OrderBy
|
90
|
+
attr_accessor :sorts
|
91
|
+
|
92
|
+
def initialize
|
93
|
+
@sorts = []
|
94
|
+
end
|
95
|
+
|
96
|
+
def accept(visitor)
|
97
|
+
if visitor.visitOrderBy(self)
|
98
|
+
sorts.each{|x| x.accept visitor}
|
99
|
+
end
|
100
|
+
visitor.endVisitOrderBy self
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_s
|
104
|
+
@sorts.map(&:to_s).join(', ')
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class Sort
|
109
|
+
|
110
|
+
Asc = :asc
|
111
|
+
Desc = :desc
|
112
|
+
|
113
|
+
attr_accessor :column
|
114
|
+
attr_accessor :order
|
115
|
+
|
116
|
+
def initialize(column, order)
|
117
|
+
@column = column
|
118
|
+
@order = order
|
119
|
+
end
|
120
|
+
|
121
|
+
def accept(visitor)
|
122
|
+
if visitor.visitSort(self)
|
123
|
+
column.accept visitor
|
124
|
+
end
|
125
|
+
visitor.endVisitSort self
|
126
|
+
end
|
127
|
+
|
128
|
+
def to_s
|
129
|
+
"#{column} #{order}"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
class Where
|
134
|
+
attr_accessor :expression
|
135
|
+
|
136
|
+
def initialize(expression)
|
137
|
+
@expression = expression
|
138
|
+
end
|
139
|
+
|
140
|
+
def accept(visitor)
|
141
|
+
if visitor.visitWhere(self)
|
142
|
+
expression.accept visitor
|
143
|
+
end
|
144
|
+
visitor.endVisitWhere self
|
145
|
+
end
|
146
|
+
|
147
|
+
def to_s
|
148
|
+
@expression.to_s
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
class Label
|
153
|
+
attr_accessor :column
|
154
|
+
attr_accessor :label
|
155
|
+
|
156
|
+
def initialize(column, label)
|
157
|
+
@column = column
|
158
|
+
@label = label
|
159
|
+
end
|
160
|
+
|
161
|
+
def accept(visitor)
|
162
|
+
if visitor.visitLabel(self)
|
163
|
+
column.accept visitor
|
164
|
+
end
|
165
|
+
visitor.endVisitLabel self
|
166
|
+
end
|
167
|
+
|
168
|
+
def to_s
|
169
|
+
"#{column} `#{label}`"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
class Format
|
174
|
+
attr_accessor :column
|
175
|
+
attr_accessor :pattern
|
176
|
+
|
177
|
+
def initialize(column, pattern)
|
178
|
+
@column = column
|
179
|
+
@pattern = pattern
|
180
|
+
end
|
181
|
+
|
182
|
+
def accept(visitor)
|
183
|
+
if visitor.visitFormat(self)
|
184
|
+
column.accept visitor
|
185
|
+
end
|
186
|
+
visitor.endVisitFormat self
|
187
|
+
end
|
188
|
+
|
189
|
+
def to_s
|
190
|
+
"#{column} `#{pattern}`"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
class Option
|
195
|
+
|
196
|
+
NoValues = :no_values
|
197
|
+
NoFormat = :no_format
|
198
|
+
|
199
|
+
attr_accessor :option
|
200
|
+
|
201
|
+
def initialize(option)
|
202
|
+
@option = option
|
203
|
+
end
|
204
|
+
|
205
|
+
def accept(visitor)
|
206
|
+
visitor.visitOption(self)
|
207
|
+
visitor.endVisitOption self
|
208
|
+
end
|
209
|
+
|
210
|
+
def to_s
|
211
|
+
@option.to_s
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
|
216
|
+
class BinaryExpression
|
217
|
+
And = :and
|
218
|
+
Contains = :contains
|
219
|
+
EndsWith = :ends_with
|
220
|
+
Eq = :EQ
|
221
|
+
Gt = :GT
|
222
|
+
Gte = :GTE
|
223
|
+
Like = :like
|
224
|
+
Lt = :LT
|
225
|
+
Lte = :LTE
|
226
|
+
Matches = :matches
|
227
|
+
Neq = :NEQ
|
228
|
+
Or = :or
|
229
|
+
StartsWith = :starts_with
|
230
|
+
|
231
|
+
attr_accessor :operator
|
232
|
+
attr_accessor :left
|
233
|
+
attr_accessor :right
|
234
|
+
|
235
|
+
def initialize(left, operator, right)
|
236
|
+
@left = left
|
237
|
+
@operator = operator
|
238
|
+
@right = right
|
239
|
+
end
|
240
|
+
|
241
|
+
def accept(visitor)
|
242
|
+
if visitor.visitBinaryExpression(self)
|
243
|
+
left.accept visitor
|
244
|
+
right.accept visitor
|
245
|
+
end
|
246
|
+
visitor.endVisitBinaryExpression self
|
247
|
+
end
|
248
|
+
|
249
|
+
def to_s
|
250
|
+
"#{left} #{operator} #{right}"
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
class UnaryExpression
|
255
|
+
Not = :not
|
256
|
+
IsNull = :is_null
|
257
|
+
IsNotNull = :is_not_null
|
258
|
+
|
259
|
+
attr_accessor :operand
|
260
|
+
attr_accessor :operator
|
261
|
+
|
262
|
+
def initialize(operand, operator)
|
263
|
+
@operand = operand
|
264
|
+
@operator = operator
|
265
|
+
end
|
266
|
+
|
267
|
+
def accept(visitor)
|
268
|
+
if visitor.visitUnaryExpression(self)
|
269
|
+
operand.accept visitor
|
270
|
+
end
|
271
|
+
visitor.endVisitUnaryExpression self
|
272
|
+
end
|
273
|
+
|
274
|
+
def to_s
|
275
|
+
"#{operand} #{operator}"
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
class IdColumn
|
280
|
+
attr_accessor :name
|
281
|
+
|
282
|
+
def initialize(name)
|
283
|
+
@name = name
|
284
|
+
end
|
285
|
+
|
286
|
+
def accept(visitor)
|
287
|
+
visitor.visitIdColumn(self)
|
288
|
+
visitor.endVisitIdColumn self
|
289
|
+
end
|
290
|
+
|
291
|
+
def to_s
|
292
|
+
@name
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
class ValueColumn
|
297
|
+
attr_accessor :value
|
298
|
+
|
299
|
+
def initialize(value)
|
300
|
+
@value = value
|
301
|
+
end
|
302
|
+
|
303
|
+
def to_s
|
304
|
+
value.to_s
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
class NumberColumn < ValueColumn
|
309
|
+
def accept(visitor)
|
310
|
+
visitor.visitNumberColumn(self)
|
311
|
+
visitor.endVisitNumberColumn self
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
class StringColumn < ValueColumn
|
316
|
+
def accept(visitor)
|
317
|
+
visitor.visitStringColumn(self)
|
318
|
+
visitor.endVisitStringColumn self
|
319
|
+
end
|
320
|
+
|
321
|
+
def to_s
|
322
|
+
"'#{value}'"
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
class BooleanColumn < ValueColumn
|
327
|
+
def accept(visitor)
|
328
|
+
visitor.visitBooleanColumn(self)
|
329
|
+
visitor.endVisitBooleanColumn self
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
class DateColumn < ValueColumn
|
334
|
+
def accept(visitor)
|
335
|
+
visitor.visitDateColumn(self)
|
336
|
+
visitor.endVisitDateColumn self
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
class DateTimeColumn < ValueColumn
|
341
|
+
def accept(visitor)
|
342
|
+
visitor.visitDateTimeColumn(self)
|
343
|
+
visitor.endVisitDateTimeColumn self
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
class TimeOfDayColumn < ValueColumn
|
348
|
+
def accept(visitor)
|
349
|
+
visitor.visitTimeOfDayColumn(self)
|
350
|
+
visitor.endVisitTimeOfDayColumn self
|
351
|
+
end
|
352
|
+
|
353
|
+
def to_s
|
354
|
+
"#{value.hour}:#{value.min}:#{value.sec}"
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
class ScalarFunctionColumn
|
359
|
+
|
360
|
+
DateDiff = :datediff
|
361
|
+
Day = :day
|
362
|
+
DayOfWeek = :dayofweek
|
363
|
+
Difference = :difference
|
364
|
+
Hour = :hour
|
365
|
+
Lower = :lower
|
366
|
+
Millisecond = :millisecond
|
367
|
+
Minute = :minute
|
368
|
+
Month = :month
|
369
|
+
Now = :now
|
370
|
+
Product = :product
|
371
|
+
Quarter = :quarter
|
372
|
+
Quotient = :quotient
|
373
|
+
Second = :second
|
374
|
+
Sum = :sum
|
375
|
+
ToDate = :todate
|
376
|
+
Upper = :upper
|
377
|
+
Year = :year
|
378
|
+
|
379
|
+
attr_accessor :function
|
380
|
+
attr_accessor :arguments
|
381
|
+
|
382
|
+
def initialize(function, *arguments)
|
383
|
+
@function = function
|
384
|
+
@arguments = arguments
|
385
|
+
end
|
386
|
+
|
387
|
+
def accept(visitor)
|
388
|
+
if visitor.visitScalarFunctionColumn(self)
|
389
|
+
arguments.each{|x| x.accept visitor}
|
390
|
+
end
|
391
|
+
visitor.endVisitScalarFunctionColumn self
|
392
|
+
end
|
393
|
+
|
394
|
+
def to_s
|
395
|
+
case function
|
396
|
+
when Sum
|
397
|
+
"#{arguments[0].to_s} + #{arguments[1].to_s}"
|
398
|
+
when Difference
|
399
|
+
"#{arguments[0].to_s} + #{arguments[1].to_s}"
|
400
|
+
when Product
|
401
|
+
"#{arguments[0].to_s} * #{arguments[1].to_s}"
|
402
|
+
when Quotient
|
403
|
+
"#{arguments[0].to_s} / #{arguments[1].to_s}"
|
404
|
+
else
|
405
|
+
"#{function}(#{arguments.map(&:to_s).join(', ')})"
|
406
|
+
end
|
407
|
+
end
|
408
|
+
end
|
409
|
+
|
410
|
+
class AggregateColumn
|
411
|
+
|
412
|
+
Avg = :avg
|
413
|
+
Count = :count
|
414
|
+
Max = :max
|
415
|
+
Min = :min
|
416
|
+
Sum = :sum
|
417
|
+
|
418
|
+
attr_accessor :function
|
419
|
+
attr_accessor :argument
|
420
|
+
|
421
|
+
def initialize(function, argument)
|
422
|
+
@function = function
|
423
|
+
@argument = argument
|
424
|
+
end
|
425
|
+
|
426
|
+
def accept(visitor)
|
427
|
+
if visitor.visitAggregateColumn(self)
|
428
|
+
argument.accept visitor
|
429
|
+
end
|
430
|
+
visitor.endVisitAggregateColumn self
|
431
|
+
end
|
432
|
+
|
433
|
+
def to_s
|
434
|
+
"#{function}(#{argument})"
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|