rgviz-rails 0.10 → 0.11
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_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
|