rgviz-rails 0.10 → 0.11
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/rgviz_rails/executor.rb +155 -10
- data/spec/rgviz/executor_spec.rb +84 -0
- metadata +3 -3
data/lib/rgviz_rails/executor.rb
CHANGED
@@ -6,8 +6,12 @@ module Rgviz
|
|
6
6
|
def initialize(model_class, query)
|
7
7
|
@model_class = model_class
|
8
8
|
@query = query
|
9
|
+
@selects = []
|
9
10
|
@joins = {}
|
10
11
|
@labels = {}
|
12
|
+
@pivots = {}
|
13
|
+
@group_bys = {}
|
14
|
+
@original_columns = []
|
11
15
|
case ActiveRecord::Base.connection.adapter_name.downcase
|
12
16
|
when 'sqlite'
|
13
17
|
@adapter = SqliteAdapter.new
|
@@ -20,12 +24,15 @@ module Rgviz
|
|
20
24
|
@table = Table.new
|
21
25
|
@extra_conditions = options[:conditions]
|
22
26
|
|
27
|
+
process_pivot
|
23
28
|
process_labels
|
29
|
+
process_options
|
24
30
|
|
25
31
|
generate_columns
|
26
32
|
generate_conditions
|
27
33
|
generate_group
|
28
34
|
generate_order
|
35
|
+
|
29
36
|
generate_rows
|
30
37
|
|
31
38
|
@table
|
@@ -39,6 +46,33 @@ module Rgviz
|
|
39
46
|
end
|
40
47
|
end
|
41
48
|
|
49
|
+
def process_options
|
50
|
+
return unless @query.options.present?
|
51
|
+
|
52
|
+
@query.options.each do |option|
|
53
|
+
case option.option
|
54
|
+
when Option::NoValues
|
55
|
+
@no_values = true
|
56
|
+
when Option::NoFormat
|
57
|
+
@no_format = true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def process_pivot
|
63
|
+
if @query.pivot
|
64
|
+
@query.pivot.columns.each do |column|
|
65
|
+
@pivots[column.to_s] = true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
if @query.group_by
|
70
|
+
@query.group_by.columns.each do |column|
|
71
|
+
@group_bys[column.to_s] = true
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
42
76
|
def add_joins(joins)
|
43
77
|
map = @joins
|
44
78
|
joins.each do |join|
|
@@ -50,14 +84,15 @@ module Rgviz
|
|
50
84
|
end
|
51
85
|
|
52
86
|
def generate_columns
|
53
|
-
@selects = []
|
54
|
-
|
55
87
|
if @query.select && @query.select.columns.present?
|
56
88
|
# Select the specified columns
|
57
89
|
i = 0
|
58
90
|
@query.select.columns.each do |col|
|
59
|
-
|
91
|
+
col_to_s = col.to_s
|
92
|
+
|
93
|
+
@table.cols << (Column.new :id => column_id(col, i), :type => column_type(col), :label => column_label(col_to_s))
|
60
94
|
@selects << "(#{column_select(col)}) as c#{i}"
|
95
|
+
@original_columns << col_to_s
|
61
96
|
i += 1
|
62
97
|
end
|
63
98
|
else
|
@@ -66,6 +101,19 @@ module Rgviz
|
|
66
101
|
@model_class.send(:columns).each do |col|
|
67
102
|
@table.cols << (Column.new :id => col.name, :type => (rails_column_type col), :label => column_label(col.name))
|
68
103
|
@selects << "(#{col.name}) as c#{i}"
|
104
|
+
@original_columns << col_to_s
|
105
|
+
i += 1
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Select pivot columns
|
110
|
+
if @query.pivot
|
111
|
+
@query.pivot.columns.each do |col|
|
112
|
+
col_to_s = col.to_s
|
113
|
+
|
114
|
+
@table.cols << (Column.new :id => column_id(col, i), :type => column_type(col), :label => column_label(col_to_s))
|
115
|
+
@selects << "(#{column_select(col)}) as c#{i}"
|
116
|
+
@original_columns << col_to_s
|
69
117
|
i += 1
|
70
118
|
end
|
71
119
|
end
|
@@ -77,6 +125,15 @@ module Rgviz
|
|
77
125
|
|
78
126
|
def generate_group
|
79
127
|
@group = to_string @query.group_by, ColumnVisitor if @query.group_by
|
128
|
+
pivot = to_string @query.pivot, ColumnVisitor if @query.pivot
|
129
|
+
|
130
|
+
if pivot.present?
|
131
|
+
if @group.present?
|
132
|
+
@group += ',' + pivot
|
133
|
+
else
|
134
|
+
@group = pivot
|
135
|
+
end
|
136
|
+
end
|
80
137
|
end
|
81
138
|
|
82
139
|
def generate_order
|
@@ -106,14 +163,102 @@ module Rgviz
|
|
106
163
|
:offset => @query.offset,
|
107
164
|
:joins => @joins
|
108
165
|
|
109
|
-
|
110
|
-
|
111
|
-
|
166
|
+
if @pivots.empty?
|
167
|
+
# Simple, just convert the results to a table
|
168
|
+
results.each do |result|
|
169
|
+
row = Row.new
|
170
|
+
@table.rows << row
|
171
|
+
|
172
|
+
i = 0
|
173
|
+
@table.cols.each do |col|
|
174
|
+
hash = {}
|
175
|
+
hash[:v] = column_value(col, result.send("c#{i}")) unless @no_values
|
176
|
+
row.c << Cell.new(hash)
|
177
|
+
i += 1
|
178
|
+
end
|
179
|
+
end
|
180
|
+
else
|
181
|
+
# A little more complicated...
|
182
|
+
|
183
|
+
# This has the grouping as a key and the pivoted selection values as a key (in a list)
|
184
|
+
fin = ActiveSupport::OrderedHash.new
|
112
185
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
186
|
+
# The uniq pivot values
|
187
|
+
uniq_pivots = []
|
188
|
+
|
189
|
+
# Fill fin and uniq_pivots
|
190
|
+
results.each do |result|
|
191
|
+
|
192
|
+
# The grouping key of this result
|
193
|
+
grouped_by = []
|
194
|
+
|
195
|
+
# The pivots of this result
|
196
|
+
pivots = []
|
197
|
+
|
198
|
+
# The selections of this result
|
199
|
+
selections = []
|
200
|
+
|
201
|
+
# Fill grouped_by, pivots and selections, as well as uniq_pivots
|
202
|
+
@table.cols.each_with_index do |col, i|
|
203
|
+
val = column_value(col, result.send("c#{i}"))
|
204
|
+
if @group_bys.include?(@original_columns[i])
|
205
|
+
grouped_by << val
|
206
|
+
elsif @pivots.include?(@original_columns[i])
|
207
|
+
pivots << val
|
208
|
+
uniq_pivots << val unless uniq_pivots.include? val
|
209
|
+
else
|
210
|
+
selections << val
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# Now put all this info into fin
|
215
|
+
fin[grouped_by] = {} unless fin[grouped_by]
|
216
|
+
pivots.each do |pivot|
|
217
|
+
selections.each do |selection|
|
218
|
+
fin[grouped_by][pivot] = selection
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# Sort the uniq pivots so the results will be sorted for a human
|
224
|
+
uniq_pivots.sort!
|
225
|
+
|
226
|
+
# Regenerate the columns info: the current info has the values
|
227
|
+
# we needed to get the info we needed
|
228
|
+
col_i = 0
|
229
|
+
new_cols = []
|
230
|
+
@original_columns.each_with_index do |original_column, i|
|
231
|
+
old_col = @table.cols[i]
|
232
|
+
if @group_bys.include?(original_column)
|
233
|
+
old_col.id = "c#{col_i}"
|
234
|
+
new_cols << @table.cols[i]
|
235
|
+
col_i += 1
|
236
|
+
elsif !@pivots.include?(original_column)
|
237
|
+
uniq_pivots.each do |uniq_pivot|
|
238
|
+
new_cols << (Column.new :id => "c#{col_i}", :type => old_col.type, :label => "#{uniq_pivot} #{old_col.label}")
|
239
|
+
col_i += 1
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
@table.cols = new_cols
|
245
|
+
|
246
|
+
# Create the rows
|
247
|
+
fin.each do |key, value|
|
248
|
+
row = Row.new
|
249
|
+
@table.rows << row
|
250
|
+
|
251
|
+
group_i = 0
|
252
|
+
@original_columns.each_with_index do |original_column, i|
|
253
|
+
if @group_bys.include?(original_column)
|
254
|
+
row.c << (Cell.new :v => key[group_i])
|
255
|
+
group_i += 1
|
256
|
+
elsif !@pivots.include?(original_column)
|
257
|
+
uniq_pivots.each do |uniq_pivot|
|
258
|
+
row.c << (Cell.new :v => value[uniq_pivot])
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
117
262
|
end
|
118
263
|
end
|
119
264
|
end
|
data/spec/rgviz/executor_spec.rb
CHANGED
@@ -202,11 +202,21 @@ describe Executor do
|
|
202
202
|
Person.make :age => 3
|
203
203
|
|
204
204
|
table = exec 'select age where age > 1', :conditions => 'age < 3'
|
205
|
+
it "processes with conditions as string" do
|
206
|
+
Person.make :age => 1
|
207
|
+
Person.make :age => 2
|
208
|
+
Person.make :age => 3
|
209
|
+
|
210
|
+
table = exec 'select age', :conditions => 'age = 2'
|
205
211
|
|
206
212
|
table.rows.length.should == 1
|
207
213
|
table.rows[0].c.length.should == 1
|
208
214
|
table.rows[0].c[0].v.should == 2
|
209
215
|
end
|
216
|
+
table.rows.length.should == 1
|
217
|
+
table.rows[0].c.length.should == 1
|
218
|
+
table.rows[0].c[0].v.should == 2
|
219
|
+
end
|
210
220
|
|
211
221
|
it "processes with conditions as array" do
|
212
222
|
Person.make :age => 1
|
@@ -276,4 +286,78 @@ describe Executor do
|
|
276
286
|
Person.make :age => 2
|
277
287
|
end
|
278
288
|
|
289
|
+
it_processes_single_select_column "1 options no_values", 'c0', :number, nil, "1"
|
290
|
+
|
291
|
+
it "processes pivot" do
|
292
|
+
Person.make :name => 'Eng', :birthday => '2000-01-12', :age => 1000
|
293
|
+
Person.make :name => 'Eng', :birthday => '2000-01-12', :age => 500
|
294
|
+
Person.make :name => 'Eng', :birthday => '2000-01-13', :age => 600
|
295
|
+
Person.make :name => 'Sales', :birthday => '2000-01-12', :age => 400
|
296
|
+
Person.make :name => 'Sales', :birthday => '2000-01-12', :age => 350
|
297
|
+
Person.make :name => 'Marketing', :birthday => '2000-01-13', :age => 800
|
298
|
+
|
299
|
+
table = exec 'select name, sum(age) group by name pivot birthday'
|
300
|
+
|
301
|
+
table.cols.length.should == 3
|
302
|
+
|
303
|
+
i = 0
|
304
|
+
[['c0', :string, 'name'],
|
305
|
+
['c1', :number, '2000-01-12 sum(age)'],
|
306
|
+
['c2', :number, '2000-01-13 sum(age)']].each do |id, type, label|
|
307
|
+
table.cols[i].id.should == id
|
308
|
+
table.cols[i].type.should == type
|
309
|
+
table.cols[i].label.should == label
|
310
|
+
i += 1
|
311
|
+
end
|
312
|
+
|
313
|
+
table.rows.length.should == 3
|
314
|
+
|
315
|
+
i = 0
|
316
|
+
[['Eng', 1500, 600],
|
317
|
+
['Marketing', nil, 800],
|
318
|
+
['Sales', 750, nil]].each do |values|
|
319
|
+
table.rows[i].c.length.should == 3
|
320
|
+
values.each_with_index do |v, j|
|
321
|
+
table.rows[i].c[j].v.should == v
|
322
|
+
end
|
323
|
+
i += 1
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
it "processes pivot2" do
|
328
|
+
Person.make :name => 'Eng', :birthday => '2000-01-12', :age => 1000
|
329
|
+
Person.make :name => 'Eng', :birthday => '2000-01-12', :age => 500
|
330
|
+
Person.make :name => 'Eng', :birthday => '2000-01-13', :age => 600
|
331
|
+
Person.make :name => 'Sales', :birthday => '2000-01-12', :age => 400
|
332
|
+
Person.make :name => 'Sales', :birthday => '2000-01-12', :age => 350
|
333
|
+
Person.make :name => 'Marketing', :birthday => '2000-01-13', :age => 800
|
334
|
+
|
335
|
+
table = exec 'select sum(age), name group by name pivot birthday'
|
336
|
+
|
337
|
+
table.cols.length.should == 3
|
338
|
+
|
339
|
+
i = 0
|
340
|
+
[['c0', :number, '2000-01-12 sum(age)'],
|
341
|
+
['c1', :number, '2000-01-13 sum(age)'],
|
342
|
+
['c2', :string, 'name']].each do |id, type, label|
|
343
|
+
table.cols[i].id.should == id
|
344
|
+
table.cols[i].type.should == type
|
345
|
+
table.cols[i].label.should == label
|
346
|
+
i += 1
|
347
|
+
end
|
348
|
+
|
349
|
+
table.rows.length.should == 3
|
350
|
+
|
351
|
+
i = 0
|
352
|
+
[[1500, 600, 'Eng'],
|
353
|
+
[nil, 800, 'Marketing'],
|
354
|
+
[750, nil, 'Sales']].each do |values|
|
355
|
+
table.rows[i].c.length.should == 3
|
356
|
+
values.each_with_index do |v, j|
|
357
|
+
table.rows[i].c[j].v.should == v
|
358
|
+
end
|
359
|
+
i += 1
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
279
363
|
end
|
metadata
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rgviz-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 29
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: "0.
|
8
|
+
- 11
|
9
|
+
version: "0.11"
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ary Borenszweig
|