rgviz 0.39 → 0.40
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|