rgviz 0.39 → 0.40
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 +10 -10
- data/lib/rgviz/nodes.rb +106 -52
- data/lib/rgviz/parser.rb +84 -81
- data/lib/rgviz/table.rb +15 -7
- data/lib/rgviz.rb +4 -1
- metadata +5 -5
data/lib/rgviz/lexer.rb
CHANGED
@@ -7,14 +7,14 @@ module Rgviz
|
|
7
7
|
@token = Token.new
|
8
8
|
@extensions = options[:extensions]
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def next_token
|
12
12
|
@token.start = pos
|
13
13
|
@token.string = nil
|
14
14
|
@token.value = nil
|
15
|
-
|
15
|
+
|
16
16
|
skip /\s*/
|
17
|
-
|
17
|
+
|
18
18
|
if eos?
|
19
19
|
@token.value = Token::EOF
|
20
20
|
elsif scan /"([^"]*)"/
|
@@ -31,10 +31,10 @@ module Rgviz
|
|
31
31
|
@token.number = matched.to_f
|
32
32
|
elsif scan /\d+/
|
33
33
|
@token.value = Token::INTEGER
|
34
|
-
@token.number = matched.
|
34
|
+
@token.number = matched.to_i
|
35
35
|
else
|
36
36
|
@token.value = if scan /\+/ then Token::PLUS
|
37
|
-
elsif scan /\-/ then Token::MINUS
|
37
|
+
elsif scan /\-/ then Token::MINUS
|
38
38
|
elsif scan /\*/ then Token::STAR
|
39
39
|
elsif scan /\// then Token::SLASH
|
40
40
|
elsif scan /\,/ then Token::COMMA
|
@@ -43,7 +43,7 @@ module Rgviz
|
|
43
43
|
elsif scan /\=/ then Token::EQ
|
44
44
|
elsif scan /\!\=/ or scan /\<\>/ then Token::NEQ
|
45
45
|
elsif scan /\>\=/ then Token::GTE
|
46
|
-
elsif scan /\>/ then Token::GT
|
46
|
+
elsif scan /\>/ then Token::GT
|
47
47
|
elsif scan /\<\=/ then Token::LTE
|
48
48
|
elsif scan /\</ then Token::LT
|
49
49
|
elsif scan /and\b/i then Token::And
|
@@ -55,9 +55,9 @@ module Rgviz
|
|
55
55
|
elsif scan /count\b/i then Token::Count
|
56
56
|
elsif scan /date\b/i then Token::Date
|
57
57
|
elsif scan /datediff\b/i then Token::DateDiff
|
58
|
-
elsif scan /datetime\b/i then Token::DateTime
|
58
|
+
elsif scan /datetime\b/i then Token::DateTime
|
59
59
|
elsif scan /day\b/i then Token::Day
|
60
|
-
elsif scan /dayofweek\b/i then Token::DayOfWeek
|
60
|
+
elsif scan /dayofweek\b/i then Token::DayOfWeek
|
61
61
|
elsif scan /desc\b/i then Token::Desc
|
62
62
|
elsif scan /ends\b/i then Token::Ends
|
63
63
|
elsif scan /false\b/i then Token::False
|
@@ -100,14 +100,14 @@ module Rgviz
|
|
100
100
|
elsif scan /year\b/i then Token::Year
|
101
101
|
elsif scan /[a-zA-Z_]\w*\b/ then Token::ID
|
102
102
|
end
|
103
|
-
|
103
|
+
|
104
104
|
if @token.value
|
105
105
|
@token.string = matched
|
106
106
|
else
|
107
107
|
raise ParseException.new("Unexpected character #{string[pos].chr}")
|
108
108
|
end
|
109
109
|
end
|
110
|
-
|
110
|
+
|
111
111
|
return @token
|
112
112
|
end
|
113
113
|
end
|
data/lib/rgviz/nodes.rb
CHANGED
@@ -10,7 +10,11 @@ module Rgviz
|
|
10
10
|
attr_accessor :labels
|
11
11
|
attr_accessor :formats
|
12
12
|
attr_accessor :options
|
13
|
-
|
13
|
+
|
14
|
+
def select?
|
15
|
+
@select && @select.columns && @select.columns.length > 0
|
16
|
+
end
|
17
|
+
|
14
18
|
def accept(visitor)
|
15
19
|
if visitor.visit_query self
|
16
20
|
select.accept visitor if select
|
@@ -23,7 +27,7 @@ module Rgviz
|
|
23
27
|
end
|
24
28
|
visitor.end_visit_query self
|
25
29
|
end
|
26
|
-
|
30
|
+
|
27
31
|
def to_s
|
28
32
|
str = ''
|
29
33
|
if select
|
@@ -48,11 +52,11 @@ module Rgviz
|
|
48
52
|
|
49
53
|
class ColumnsContainer
|
50
54
|
attr_accessor :columns
|
51
|
-
|
55
|
+
|
52
56
|
def initialize
|
53
57
|
@columns = []
|
54
58
|
end
|
55
|
-
|
59
|
+
|
56
60
|
def to_s
|
57
61
|
@columns.map(&:to_s).join(', ')
|
58
62
|
end
|
@@ -87,18 +91,18 @@ module Rgviz
|
|
87
91
|
|
88
92
|
class OrderBy
|
89
93
|
attr_accessor :sorts
|
90
|
-
|
94
|
+
|
91
95
|
def initialize
|
92
96
|
@sorts = []
|
93
97
|
end
|
94
|
-
|
98
|
+
|
95
99
|
def accept(visitor)
|
96
100
|
if visitor.visit_order_by(self)
|
97
101
|
sorts.each{|x| x.accept visitor}
|
98
102
|
end
|
99
103
|
visitor.end_visit_order_by self
|
100
104
|
end
|
101
|
-
|
105
|
+
|
102
106
|
def to_s
|
103
107
|
@sorts.map(&:to_s).join(', ')
|
104
108
|
end
|
@@ -111,19 +115,19 @@ module Rgviz
|
|
111
115
|
|
112
116
|
attr_accessor :column
|
113
117
|
attr_accessor :order
|
114
|
-
|
118
|
+
|
115
119
|
def initialize(column, order)
|
116
120
|
@column = column
|
117
121
|
@order = order
|
118
122
|
end
|
119
|
-
|
123
|
+
|
120
124
|
def accept(visitor)
|
121
125
|
if visitor.visit_sort(self)
|
122
126
|
column.accept visitor
|
123
127
|
end
|
124
128
|
visitor.end_visit_sort self
|
125
129
|
end
|
126
|
-
|
130
|
+
|
127
131
|
def to_s
|
128
132
|
"#{column} #{order}"
|
129
133
|
end
|
@@ -131,18 +135,18 @@ module Rgviz
|
|
131
135
|
|
132
136
|
class Where
|
133
137
|
attr_accessor :expression
|
134
|
-
|
138
|
+
|
135
139
|
def initialize(expression)
|
136
140
|
@expression = expression
|
137
141
|
end
|
138
|
-
|
142
|
+
|
139
143
|
def accept(visitor)
|
140
144
|
if visitor.visit_where(self)
|
141
145
|
expression.accept visitor
|
142
146
|
end
|
143
147
|
visitor.end_visit_where self
|
144
148
|
end
|
145
|
-
|
149
|
+
|
146
150
|
def to_s
|
147
151
|
@expression.to_s
|
148
152
|
end
|
@@ -151,50 +155,50 @@ module Rgviz
|
|
151
155
|
class Label
|
152
156
|
attr_accessor :column
|
153
157
|
attr_accessor :label
|
154
|
-
|
158
|
+
|
155
159
|
def initialize(column, label)
|
156
160
|
@column = column
|
157
161
|
@label = label
|
158
162
|
end
|
159
|
-
|
163
|
+
|
160
164
|
def accept(visitor)
|
161
165
|
if visitor.visit_label(self)
|
162
166
|
column.accept visitor
|
163
167
|
end
|
164
168
|
visitor.end_visit_label self
|
165
169
|
end
|
166
|
-
|
170
|
+
|
167
171
|
def to_s
|
168
|
-
"#{column} `#{label}`"
|
172
|
+
"#{column} `#{label}`"
|
169
173
|
end
|
170
174
|
end
|
171
|
-
|
175
|
+
|
172
176
|
class Format
|
173
177
|
attr_accessor :column
|
174
178
|
attr_accessor :pattern
|
175
|
-
|
179
|
+
|
176
180
|
def initialize(column, pattern)
|
177
181
|
@column = column
|
178
182
|
@pattern = pattern
|
179
183
|
end
|
180
|
-
|
184
|
+
|
181
185
|
def accept(visitor)
|
182
186
|
if visitor.visit_format(self)
|
183
187
|
column.accept visitor
|
184
188
|
end
|
185
189
|
visitor.end_visit_format self
|
186
190
|
end
|
187
|
-
|
191
|
+
|
188
192
|
def to_s
|
189
|
-
"#{column} `#{pattern}`"
|
193
|
+
"#{column} `#{pattern}`"
|
190
194
|
end
|
191
195
|
end
|
192
196
|
|
193
197
|
class Options
|
194
|
-
|
198
|
+
|
195
199
|
attr_accessor :no_values
|
196
200
|
attr_accessor :no_format
|
197
|
-
|
201
|
+
|
198
202
|
def to_s
|
199
203
|
s = ''
|
200
204
|
s += 'no_values ' if @no_values
|
@@ -203,30 +207,30 @@ module Rgviz
|
|
203
207
|
end
|
204
208
|
|
205
209
|
end
|
206
|
-
|
210
|
+
|
207
211
|
class LogicalExpression
|
208
212
|
And = Token::And
|
209
213
|
Or = Token::Or
|
210
|
-
|
214
|
+
|
211
215
|
attr_accessor :operator
|
212
216
|
attr_accessor :operands
|
213
|
-
|
217
|
+
|
214
218
|
def initialize(operator, operands)
|
215
219
|
@operator = operator
|
216
220
|
@operands = operands
|
217
221
|
end
|
218
|
-
|
222
|
+
|
219
223
|
def accept(visitor)
|
220
224
|
if visitor.visit_logical_expression(self)
|
221
225
|
operands.each{|x| x.accept visitor}
|
222
226
|
end
|
223
227
|
visitor.end_visit_logical_expression self
|
224
228
|
end
|
225
|
-
|
229
|
+
|
226
230
|
def to_s
|
227
231
|
operands.map(&:to_s).join(" #{operator} ")
|
228
232
|
end
|
229
|
-
|
233
|
+
|
230
234
|
end
|
231
235
|
|
232
236
|
class BinaryExpression
|
@@ -240,19 +244,19 @@ module Rgviz
|
|
240
244
|
Lte = Token::LTE
|
241
245
|
Matches = Token::Matches
|
242
246
|
Neq = Token::NEQ
|
243
|
-
|
247
|
+
|
244
248
|
StartsWith = :'starts with'
|
245
249
|
|
246
250
|
attr_accessor :operator
|
247
251
|
attr_accessor :left
|
248
252
|
attr_accessor :right
|
249
|
-
|
253
|
+
|
250
254
|
def initialize(left, operator, right)
|
251
255
|
@left = left
|
252
256
|
@operator = operator
|
253
257
|
@right = right
|
254
258
|
end
|
255
|
-
|
259
|
+
|
256
260
|
def accept(visitor)
|
257
261
|
if visitor.visit_binary_expression(self)
|
258
262
|
left.accept visitor
|
@@ -260,7 +264,7 @@ module Rgviz
|
|
260
264
|
end
|
261
265
|
visitor.end_visit_binary_expression self
|
262
266
|
end
|
263
|
-
|
267
|
+
|
264
268
|
def to_s
|
265
269
|
"#{left} #{operator} #{right}"
|
266
270
|
end
|
@@ -270,22 +274,22 @@ module Rgviz
|
|
270
274
|
Not = Token::Not
|
271
275
|
IsNull = :'is null'
|
272
276
|
IsNotNull = :'is not null'
|
273
|
-
|
277
|
+
|
274
278
|
attr_accessor :operand
|
275
279
|
attr_accessor :operator
|
276
|
-
|
280
|
+
|
277
281
|
def initialize(operator, operand)
|
278
282
|
@operator = operator
|
279
283
|
@operand = operand
|
280
284
|
end
|
281
|
-
|
285
|
+
|
282
286
|
def accept(visitor)
|
283
287
|
if visitor.visit_unary_expression(self)
|
284
288
|
operand.accept visitor
|
285
289
|
end
|
286
290
|
visitor.end_visit_unary_expression self
|
287
291
|
end
|
288
|
-
|
292
|
+
|
289
293
|
def to_s
|
290
294
|
if operator == Not
|
291
295
|
"not #{operand}"
|
@@ -297,16 +301,26 @@ module Rgviz
|
|
297
301
|
|
298
302
|
class IdColumn
|
299
303
|
attr_accessor :name
|
300
|
-
|
304
|
+
|
301
305
|
def initialize(name)
|
302
306
|
@name = name
|
303
307
|
end
|
304
|
-
|
308
|
+
|
305
309
|
def accept(visitor)
|
306
310
|
visitor.visit_id_column(self)
|
307
311
|
visitor.end_visit_id_column self
|
308
312
|
end
|
309
|
-
|
313
|
+
|
314
|
+
def hash
|
315
|
+
@name.hash
|
316
|
+
end
|
317
|
+
|
318
|
+
def eql?(other)
|
319
|
+
other.class == IdColumn && other.name == @name
|
320
|
+
end
|
321
|
+
|
322
|
+
alias_method :==, :eql?
|
323
|
+
|
310
324
|
def to_s
|
311
325
|
@name
|
312
326
|
end
|
@@ -314,11 +328,21 @@ module Rgviz
|
|
314
328
|
|
315
329
|
class ValueColumn
|
316
330
|
attr_accessor :value
|
317
|
-
|
331
|
+
|
318
332
|
def initialize(value)
|
319
333
|
@value = value
|
320
334
|
end
|
321
|
-
|
335
|
+
|
336
|
+
def hash
|
337
|
+
@value.hash
|
338
|
+
end
|
339
|
+
|
340
|
+
def eql?(other)
|
341
|
+
other.class == self.class && other.value == @value
|
342
|
+
end
|
343
|
+
|
344
|
+
alias_method :==, :eql?
|
345
|
+
|
322
346
|
def to_s
|
323
347
|
value.to_s
|
324
348
|
end
|
@@ -336,7 +360,7 @@ module Rgviz
|
|
336
360
|
visitor.visit_string_column(self)
|
337
361
|
visitor.end_visit_string_column self
|
338
362
|
end
|
339
|
-
|
363
|
+
|
340
364
|
def to_s
|
341
365
|
"'#{value}'"
|
342
366
|
end
|
@@ -354,7 +378,7 @@ module Rgviz
|
|
354
378
|
visitor.visit_date_column(self)
|
355
379
|
visitor.end_visit_date_column self
|
356
380
|
end
|
357
|
-
|
381
|
+
|
358
382
|
def to_s
|
359
383
|
"date '#{value.to_s}'"
|
360
384
|
end
|
@@ -365,7 +389,7 @@ module Rgviz
|
|
365
389
|
visitor.visit_date_time_column(self)
|
366
390
|
visitor.end_visit_date_time_column self
|
367
391
|
end
|
368
|
-
|
392
|
+
|
369
393
|
def to_s
|
370
394
|
"datetime '" + value.strftime("%Y-%m-%d %H:%M:%S") + "'"
|
371
395
|
end
|
@@ -376,7 +400,7 @@ module Rgviz
|
|
376
400
|
visitor.visit_time_of_day_column(self)
|
377
401
|
visitor.end_visit_time_of_day_column self
|
378
402
|
end
|
379
|
-
|
403
|
+
|
380
404
|
def to_s
|
381
405
|
"timeofday '" + value.strftime("%H:%M:%S") + "'"
|
382
406
|
end
|
@@ -406,19 +430,35 @@ module Rgviz
|
|
406
430
|
|
407
431
|
attr_accessor :function
|
408
432
|
attr_accessor :arguments
|
409
|
-
|
433
|
+
|
410
434
|
def initialize(function, *arguments)
|
411
435
|
@function = function
|
412
436
|
@arguments = arguments
|
413
437
|
end
|
414
|
-
|
438
|
+
|
415
439
|
def accept(visitor)
|
416
440
|
if visitor.visit_scalar_function_column(self)
|
417
441
|
arguments.each{|x| x.accept visitor}
|
418
442
|
end
|
419
443
|
visitor.end_visit_scalar_function_column self
|
420
444
|
end
|
421
|
-
|
445
|
+
|
446
|
+
def hash
|
447
|
+
return @hash if @hash
|
448
|
+
@hash = 1
|
449
|
+
@hash = @hash * 31 + @function.hash
|
450
|
+
@arguments.each do |arg|
|
451
|
+
@hash = @hash * 31 + arg.hash
|
452
|
+
end
|
453
|
+
@hash
|
454
|
+
end
|
455
|
+
|
456
|
+
def eql?(other)
|
457
|
+
other.class == ScalarFunctionColumn && other.function == @function && other.arguments == @arguments
|
458
|
+
end
|
459
|
+
|
460
|
+
alias_method :==, :eql?
|
461
|
+
|
422
462
|
def to_s
|
423
463
|
case function
|
424
464
|
when Sum, Difference, Product, Quotient
|
@@ -439,12 +479,12 @@ module Rgviz
|
|
439
479
|
|
440
480
|
attr_accessor :function
|
441
481
|
attr_accessor :argument
|
442
|
-
|
482
|
+
|
443
483
|
def initialize(function, argument)
|
444
484
|
@function = function
|
445
485
|
@argument = argument
|
446
486
|
end
|
447
|
-
|
487
|
+
|
448
488
|
def accept(visitor)
|
449
489
|
if visitor.visit_aggregate_column(self)
|
450
490
|
argument.accept visitor
|
@@ -452,6 +492,20 @@ module Rgviz
|
|
452
492
|
visitor.end_visit_aggregate_column self
|
453
493
|
end
|
454
494
|
|
495
|
+
def hash
|
496
|
+
return @hash if @hash
|
497
|
+
@hash = 1
|
498
|
+
@hash = @hash * 31 + @function.hash
|
499
|
+
@hash = @hash * 31 + @argument.hash
|
500
|
+
@hash
|
501
|
+
end
|
502
|
+
|
503
|
+
def eql?(other)
|
504
|
+
other.class == ScalarFunctionColumn && other.function == @function && other.arguments == @arguments
|
505
|
+
end
|
506
|
+
|
507
|
+
alias_method :==, :eql?
|
508
|
+
|
455
509
|
def to_s
|
456
510
|
"#{function}(#{argument})"
|
457
511
|
end
|
data/lib/rgviz/parser.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'date'
|
3
|
+
|
1
4
|
module Rgviz
|
2
5
|
class Parser < Lexer
|
3
6
|
def initialize(string, options = {})
|
@@ -5,11 +8,11 @@ module Rgviz
|
|
5
8
|
@query = Query.new
|
6
9
|
next_token
|
7
10
|
end
|
8
|
-
|
11
|
+
|
9
12
|
def self.parse(string, options = {})
|
10
13
|
Parser.new(string, options).parse
|
11
14
|
end
|
12
|
-
|
15
|
+
|
13
16
|
def parse
|
14
17
|
parse_select
|
15
18
|
parse_where
|
@@ -21,129 +24,129 @@ module Rgviz
|
|
21
24
|
parse_label
|
22
25
|
parse_format
|
23
26
|
parse_options
|
24
|
-
|
27
|
+
|
25
28
|
raise ParseException.new("Expecting end of query, got: #{@token.string}") if @token.value != Token::EOF
|
26
29
|
@query
|
27
30
|
end
|
28
|
-
|
31
|
+
|
29
32
|
def parse_select
|
30
33
|
return if not token_is! Token::Select
|
31
|
-
|
34
|
+
|
32
35
|
@query.select = Select.new
|
33
|
-
|
36
|
+
|
34
37
|
return if token_is! Token::STAR
|
35
|
-
|
38
|
+
|
36
39
|
parse_columns @query.select.columns
|
37
|
-
|
40
|
+
|
38
41
|
raise ParseException.new("Expecting select columns") if @query.select.columns.empty?
|
39
42
|
end
|
40
|
-
|
43
|
+
|
41
44
|
def parse_where
|
42
45
|
return if not token_is! Token::Where
|
43
|
-
|
46
|
+
|
44
47
|
@query.where = Where.new parse_expression
|
45
48
|
end
|
46
|
-
|
49
|
+
|
47
50
|
def parse_group_by
|
48
51
|
return if not token_is! Token::Group
|
49
52
|
check! Token::By
|
50
|
-
|
53
|
+
|
51
54
|
@query.group_by = GroupBy.new
|
52
55
|
@query.group_by.columns = parse_columns
|
53
|
-
|
56
|
+
|
54
57
|
raise ParseException.new("Expecting group by columns") if @query.group_by.columns.empty?
|
55
58
|
end
|
56
|
-
|
59
|
+
|
57
60
|
def parse_pivot
|
58
61
|
return if not token_is! Token::Pivot
|
59
|
-
|
62
|
+
|
60
63
|
@query.pivot = Pivot.new
|
61
64
|
@query.pivot.columns = parse_columns
|
62
|
-
|
65
|
+
|
63
66
|
raise ParseException.new("Expecting pivot columns") if @query.pivot.columns.empty?
|
64
67
|
end
|
65
|
-
|
68
|
+
|
66
69
|
def parse_order_by
|
67
70
|
return if not token_is! Token::Order
|
68
71
|
check! Token::By
|
69
|
-
|
72
|
+
|
70
73
|
@query.order_by = OrderBy.new
|
71
74
|
@query.order_by.sorts = parse_sorts
|
72
|
-
|
75
|
+
|
73
76
|
raise ParseException.new("Expecting order by columns") if @query.order_by.sorts.empty?
|
74
77
|
end
|
75
|
-
|
78
|
+
|
76
79
|
def parse_limit
|
77
80
|
return if not token_is! Token::Limit
|
78
|
-
|
81
|
+
|
79
82
|
check Token::INTEGER
|
80
|
-
|
83
|
+
|
81
84
|
@query.limit = @token.number
|
82
85
|
next_token
|
83
86
|
end
|
84
|
-
|
87
|
+
|
85
88
|
def parse_offset
|
86
89
|
return if not token_is! Token::Offset
|
87
|
-
|
90
|
+
|
88
91
|
check Token::INTEGER
|
89
|
-
|
92
|
+
|
90
93
|
@query.offset = @token.number
|
91
94
|
next_token
|
92
95
|
end
|
93
|
-
|
96
|
+
|
94
97
|
def parse_label
|
95
98
|
return if not token_is! Token::Label
|
96
|
-
|
99
|
+
|
97
100
|
@query.labels = []
|
98
|
-
|
101
|
+
|
99
102
|
column = parse_column
|
100
103
|
raise ParseException.new("Expecting label") unless column
|
101
|
-
|
102
|
-
check Token::STRING
|
103
|
-
@query.labels << Label.new(column, @token.string)
|
104
|
+
|
105
|
+
check Token::STRING
|
106
|
+
@query.labels << Label.new(column, @token.string)
|
104
107
|
next_token
|
105
|
-
|
108
|
+
|
106
109
|
while token_is! Token::COMMA
|
107
110
|
column = parse_column
|
108
111
|
break unless column
|
109
|
-
|
110
|
-
check Token::STRING
|
111
|
-
@query.labels << Label.new(column, @token.string)
|
112
|
+
|
113
|
+
check Token::STRING
|
114
|
+
@query.labels << Label.new(column, @token.string)
|
112
115
|
next_token
|
113
116
|
end
|
114
|
-
|
117
|
+
|
115
118
|
raise ParseException.new("Expecting label") if @query.labels.empty?
|
116
119
|
end
|
117
|
-
|
120
|
+
|
118
121
|
def parse_format
|
119
122
|
return if not token_is! Token::Format
|
120
|
-
|
123
|
+
|
121
124
|
@query.formats = []
|
122
|
-
|
125
|
+
|
123
126
|
column = parse_column
|
124
127
|
raise ParseException.new("Expecting format") unless column
|
125
|
-
|
126
|
-
check Token::STRING
|
127
|
-
@query.formats << Format.new(column, @token.string)
|
128
|
+
|
129
|
+
check Token::STRING
|
130
|
+
@query.formats << Format.new(column, @token.string)
|
128
131
|
next_token
|
129
|
-
|
132
|
+
|
130
133
|
while token_is! Token::COMMA
|
131
134
|
column = parse_column
|
132
135
|
break unless column
|
133
|
-
|
134
|
-
check Token::STRING
|
135
|
-
@query.formats << Format.new(column, @token.string)
|
136
|
+
|
137
|
+
check Token::STRING
|
138
|
+
@query.formats << Format.new(column, @token.string)
|
136
139
|
next_token
|
137
140
|
end
|
138
|
-
|
141
|
+
|
139
142
|
raise ParseException.new("Expecting format") if @query.formats.empty?
|
140
143
|
end
|
141
|
-
|
144
|
+
|
142
145
|
def parse_options
|
143
146
|
return if not token_is! Token::Options
|
144
|
-
|
147
|
+
|
145
148
|
@query.options = Options.new
|
146
|
-
|
149
|
+
|
147
150
|
while true
|
148
151
|
case @token.value
|
149
152
|
when Token::NoFormat
|
@@ -156,30 +159,30 @@ module Rgviz
|
|
156
159
|
break
|
157
160
|
end
|
158
161
|
end
|
159
|
-
|
160
|
-
raise ParseException.new("Expecting option") if !@query.options.no_format && !@query.options.no_values
|
162
|
+
|
163
|
+
raise ParseException.new("Expecting option") if !@query.options.no_format && !@query.options.no_values
|
161
164
|
raise ParseException.new("Unknown option #{@token.string}") if @token.value != Token::EOF
|
162
165
|
end
|
163
|
-
|
166
|
+
|
164
167
|
def parse_sorts
|
165
168
|
sorts = []
|
166
|
-
|
169
|
+
|
167
170
|
column = parse_column
|
168
171
|
return sorts unless column
|
169
|
-
|
172
|
+
|
170
173
|
order = parse_sort_order
|
171
|
-
|
174
|
+
|
172
175
|
sorts << Sort.new(column, order)
|
173
176
|
while token_is! Token::COMMA
|
174
177
|
column = parse_column
|
175
178
|
break unless column
|
176
|
-
|
179
|
+
|
177
180
|
order = parse_sort_order
|
178
181
|
sorts << Sort.new(column, order)
|
179
182
|
end
|
180
183
|
sorts
|
181
184
|
end
|
182
|
-
|
185
|
+
|
183
186
|
def parse_sort_order
|
184
187
|
if token_is! Token::Asc
|
185
188
|
Sort::Asc
|
@@ -189,15 +192,15 @@ module Rgviz
|
|
189
192
|
Sort::Asc
|
190
193
|
end
|
191
194
|
end
|
192
|
-
|
195
|
+
|
193
196
|
def parse_expression
|
194
197
|
parse_or_expression
|
195
198
|
end
|
196
|
-
|
199
|
+
|
197
200
|
def parse_or_expression
|
198
201
|
left = parse_and_expression
|
199
202
|
return left unless token_is? Token::Or
|
200
|
-
|
203
|
+
|
201
204
|
operands = [left]
|
202
205
|
while true
|
203
206
|
if token_is! Token::Or
|
@@ -207,11 +210,11 @@ module Rgviz
|
|
207
210
|
end
|
208
211
|
end
|
209
212
|
end
|
210
|
-
|
213
|
+
|
211
214
|
def parse_and_expression
|
212
215
|
left = parse_not_expression
|
213
216
|
return left unless token_is? Token::And
|
214
|
-
|
217
|
+
|
215
218
|
operands = [left]
|
216
219
|
while true
|
217
220
|
if token_is! Token::And
|
@@ -221,7 +224,7 @@ module Rgviz
|
|
221
224
|
end
|
222
225
|
end
|
223
226
|
end
|
224
|
-
|
227
|
+
|
225
228
|
def parse_not_expression
|
226
229
|
if token_is! Token::Not
|
227
230
|
operand = parse_primary_expression
|
@@ -230,7 +233,7 @@ module Rgviz
|
|
230
233
|
parse_primary_expression
|
231
234
|
end
|
232
235
|
end
|
233
|
-
|
236
|
+
|
234
237
|
def parse_primary_expression
|
235
238
|
case @token.value
|
236
239
|
when Token::LPAREN
|
@@ -241,7 +244,7 @@ module Rgviz
|
|
241
244
|
else
|
242
245
|
left = parse_column
|
243
246
|
raise ParseException.new("Expecting left exp") unless left
|
244
|
-
|
247
|
+
|
245
248
|
case @token.value
|
246
249
|
when Token::Is
|
247
250
|
next_token
|
@@ -270,11 +273,11 @@ module Rgviz
|
|
270
273
|
end
|
271
274
|
end
|
272
275
|
end
|
273
|
-
|
276
|
+
|
274
277
|
def parse_columns(columns = [])
|
275
278
|
column = parse_column
|
276
279
|
return columns unless column
|
277
|
-
|
280
|
+
|
278
281
|
columns << column
|
279
282
|
while token_is! Token::COMMA
|
280
283
|
column = parse_column
|
@@ -283,15 +286,15 @@ module Rgviz
|
|
283
286
|
end
|
284
287
|
columns
|
285
288
|
end
|
286
|
-
|
289
|
+
|
287
290
|
def parse_column
|
288
291
|
parse_arithmetic_expression
|
289
292
|
end
|
290
|
-
|
293
|
+
|
291
294
|
def parse_arithmetic_expression
|
292
295
|
parse_summation_or_substraction
|
293
296
|
end
|
294
|
-
|
297
|
+
|
295
298
|
def parse_summation_or_substraction
|
296
299
|
left = parse_multiplication_or_divition
|
297
300
|
while true
|
@@ -309,7 +312,7 @@ module Rgviz
|
|
309
312
|
end
|
310
313
|
end
|
311
314
|
end
|
312
|
-
|
315
|
+
|
313
316
|
def parse_multiplication_or_divition
|
314
317
|
left = parse_atomic_column
|
315
318
|
while true
|
@@ -327,9 +330,9 @@ module Rgviz
|
|
327
330
|
end
|
328
331
|
end
|
329
332
|
end
|
330
|
-
|
333
|
+
|
331
334
|
def parse_atomic_column
|
332
|
-
case @token.value
|
335
|
+
case @token.value
|
333
336
|
when Token::ID
|
334
337
|
return value_column(IdColumn.new(@token.string))
|
335
338
|
when Token::Contains, Token::Starts, Token::Ends, Token::With,
|
@@ -380,7 +383,7 @@ module Rgviz
|
|
380
383
|
else
|
381
384
|
return IdColumn.new(string)
|
382
385
|
end
|
383
|
-
when Token::Year, Token::Month, Token::Day,
|
386
|
+
when Token::Year, Token::Month, Token::Day,
|
384
387
|
Token::Hour, Token::Minute, Token::Second, Token::Millisecond,
|
385
388
|
Token::Now, Token::DateDiff, Token::Lower, Token::Upper,
|
386
389
|
Token::Quarter, Token::DayOfWeek, Token::ToDate, Token::Concat
|
@@ -397,17 +400,17 @@ module Rgviz
|
|
397
400
|
end
|
398
401
|
nil
|
399
402
|
end
|
400
|
-
|
403
|
+
|
401
404
|
def value_column(col)
|
402
405
|
column = col
|
403
406
|
next_token
|
404
407
|
return column
|
405
408
|
end
|
406
|
-
|
409
|
+
|
407
410
|
def token_is?(token_value)
|
408
|
-
@token.value == token_value
|
411
|
+
@token.value == token_value
|
409
412
|
end
|
410
|
-
|
413
|
+
|
411
414
|
def token_is!(token_value)
|
412
415
|
if @token.value == token_value
|
413
416
|
next_token
|
@@ -416,11 +419,11 @@ module Rgviz
|
|
416
419
|
false
|
417
420
|
end
|
418
421
|
end
|
419
|
-
|
422
|
+
|
420
423
|
def check(*token_values)
|
421
424
|
raise ParseException.new("Expecting token #{token_values}") unless token_values.any?{|value| @token.value == value}
|
422
425
|
end
|
423
|
-
|
426
|
+
|
424
427
|
def check!(*token_values)
|
425
428
|
check *token_values
|
426
429
|
next_token
|
data/lib/rgviz/table.rb
CHANGED
@@ -2,40 +2,48 @@ module Rgviz
|
|
2
2
|
class Table
|
3
3
|
attr_accessor :cols
|
4
4
|
attr_accessor :rows
|
5
|
-
|
5
|
+
|
6
6
|
def initialize
|
7
7
|
@cols = []
|
8
8
|
@rows = []
|
9
9
|
end
|
10
|
+
|
11
|
+
def to_csv
|
12
|
+
CsvRenderer.render self
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_html
|
16
|
+
HtmlRenderer.render self
|
17
|
+
end
|
10
18
|
end
|
11
|
-
|
19
|
+
|
12
20
|
class Column
|
13
21
|
attr_accessor :id
|
14
22
|
attr_accessor :label
|
15
23
|
attr_accessor :type
|
16
24
|
attr_accessor :pattern
|
17
25
|
attr_accessor :p
|
18
|
-
|
26
|
+
|
19
27
|
def initialize(attributes = {})
|
20
28
|
attributes.each do |key, value|
|
21
29
|
self.send "#{key}=", value
|
22
30
|
end
|
23
31
|
end
|
24
32
|
end
|
25
|
-
|
33
|
+
|
26
34
|
class Row
|
27
35
|
attr_accessor :c
|
28
|
-
|
36
|
+
|
29
37
|
def initialize
|
30
38
|
@c = []
|
31
39
|
end
|
32
40
|
end
|
33
|
-
|
41
|
+
|
34
42
|
class Cell
|
35
43
|
attr_accessor :v
|
36
44
|
attr_accessor :f
|
37
45
|
attr_accessor :p
|
38
|
-
|
46
|
+
|
39
47
|
def initialize(attributes = {})
|
40
48
|
attributes.each do |key, value|
|
41
49
|
self.send "#{key}=", value
|
data/lib/rgviz.rb
CHANGED
@@ -6,6 +6,9 @@ require File.dirname(__FILE__) + '/rgviz/visitor'
|
|
6
6
|
require File.dirname(__FILE__) + '/rgviz/table'
|
7
7
|
require File.dirname(__FILE__) + '/rgviz/csv_renderer'
|
8
8
|
require File.dirname(__FILE__) + '/rgviz/html_renderer'
|
9
|
+
require File.dirname(__FILE__) + '/rgviz/memory_executor'
|
9
10
|
|
10
|
-
|
11
|
+
module Rgviz
|
12
|
+
class ParseException < Exception
|
13
|
+
end
|
11
14
|
end
|
metadata
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rgviz
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 91
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: "0.
|
8
|
+
- 40
|
9
|
+
version: "0.40"
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ary Borenszweig
|
@@ -68,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
68
|
requirements: []
|
69
69
|
|
70
70
|
rubyforge_project:
|
71
|
-
rubygems_version: 1.
|
71
|
+
rubygems_version: 1.4.2
|
72
72
|
signing_key:
|
73
73
|
specification_version: 3
|
74
74
|
summary: Google Visualization API Query Language written in Ruby.
|