activecube 0.1.40 → 0.1.43

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b5e229585093009dd0f27fc13fb03f4c47800af504431125d6924cec518e5933
4
- data.tar.gz: b0f733fc1f6152715c679bbf023648837687f6c835e41163076b6d3840c7c4b2
3
+ metadata.gz: aec3cd5d380f65b797c530930d4cfaac15b39918527b7c90e2ec54a064207729
4
+ data.tar.gz: 14c6c81f226ed03143e84478b52a056ed63de31be67bc5f5bbed98fb4004490f
5
5
  SHA512:
6
- metadata.gz: 1059e6c2ca73b04b25e5c820e57d1a6e4c37131079b864eccc6b5a5d55e31553ba53b2098d32c27588088c8b922eb8b98da1d59afe65129ba1437696832451c5
7
- data.tar.gz: 1b25987ebc1638fc745e8730ef6d9eb89468514466df59e6784e442996656aef54c1f8fbc5237ed78f81e1124018813b6ad9dbca4c3e9a553dab303f3137b04b
6
+ metadata.gz: 508fc6bf05c575b0f7417a3e56a03eb306deafcc9655c166e34233fd98e6ec42321409c0a30a6143195e4eddee352e1114d01d6cce305a0cfb9ca9f6ba243732
7
+ data.tar.gz: edc18eadd6d0bee5d96423f141e70f480dced3b38afd8f0a05e31112c8ced58fe8ec33b4924790101706cfcf9c5f9364da6be41e31164b5f58f6b4b7fff08b9f
data/Gemfile.lock CHANGED
@@ -9,7 +9,7 @@ GIT
9
9
  PATH
10
10
  remote: .
11
11
  specs:
12
- activecube (0.1.39)
12
+ activecube (0.1.43)
13
13
  activerecord (>= 5.2)
14
14
 
15
15
  GEM
@@ -75,13 +75,11 @@ module Activecube::Processor
75
75
  measures_by_tables = measure_tables.group_by(&:table)
76
76
  measures_by_tables.each_pair do |table, list|
77
77
  @models << table.model
78
- reduce_options = measures_by_tables.count==1 ? cube_query.options : []
79
- reduced = cube_query.reduced list.map(&:measure), reduce_options
80
- table_query = table.query reduced
78
+ table_query = table.query cube_query, list.map(&:measure)
81
79
  composed_query = composed_query ? table.join(cube_query, composed_query, table_query) : table_query
82
80
  end
83
81
  composed_query
84
82
  end
85
83
 
86
84
  end
87
- end
85
+ end
@@ -6,6 +6,7 @@ module Activecube::Processor
6
6
  MAX_ITERATIONS = 3
7
7
 
8
8
  attr_reader :tables_count, :metrics_count, :cost_matrix
9
+
9
10
  def initialize cost_matrix
10
11
  @cost_matrix = cost_matrix
11
12
  @cache = ActiveSupport::Cache::MemoryStore.new
@@ -18,10 +19,9 @@ module Activecube::Processor
18
19
  @tables_count = cost_matrix.map(&:count).max
19
20
  @metrics_count = cost_matrix.count
20
21
 
21
- (tables_count==1 || metrics_count==0) ? [0]*metrics_count : do_optimize
22
-
23
- end
22
+ (tables_count == 1 || metrics_count == 0) ? [0] * metrics_count : do_optimize
24
23
 
24
+ end
25
25
 
26
26
  end
27
27
 
@@ -29,42 +29,96 @@ module Activecube::Processor
29
29
 
30
30
  def generate_variants vs, metric_i
31
31
 
32
- return vs if metric_i==metrics_count
32
+ return vs if metric_i == metrics_count
33
33
 
34
34
  metric_tables = cost_matrix[metric_i].map.with_index do |c, index|
35
35
  [index] if c
36
36
  end.compact
37
37
 
38
- vsnew = if metric_i==0
39
- metric_tables
40
- else
41
- arry = []
42
- vs.each do |v|
43
- metric_tables.each{|newv|
44
- arry << (v + newv)
45
- }
46
- end
47
- arry
48
- end
38
+ vsnew = if metric_i == 0
39
+ metric_tables
40
+ else
41
+ arry = []
42
+ vs.each do |v|
43
+ metric_tables.each { |newv|
44
+ arry << (v + newv)
45
+ }
46
+ end
47
+ arry
48
+ end
49
49
 
50
- generate_variants vsnew, metric_i+1
50
+ generate_variants vsnew, metric_i + 1
51
51
 
52
52
  end
53
53
 
54
54
  def cost_for variant
55
55
  variant.each_with_index.group_by(&:first).collect do |table_index, arry|
56
- arry.map(&:second).map{|metric_index| cost_matrix[metric_index][table_index] }.max
56
+ arry.map(&:second).map { |metric_index| cost_matrix[metric_index][table_index] }.max
57
57
  end.sum
58
58
  end
59
59
 
60
60
  def do_optimize
61
61
 
62
- variants = generate_variants [], 0
63
- variant_costs = variants.map{|v| cost_for v}
62
+ # variants = generate_variants [], 0
63
+ variants = gen_reduced_variants
64
+ variant_costs = variants.map { |v| cost_for v }
64
65
  variants[variant_costs.each_with_index.min.second]
65
66
 
66
67
  end
67
68
 
68
- end
69
+ def gen_permutations(n, k)
70
+ seq = *(0...n)
71
+ perm = seq.slice(0, k)
72
+ perms = []
73
+
74
+ while true
75
+ perms.push perm.dup
76
+ flag = true
77
+ i = 0
78
+ ((k - 1)...-1).step(-1).each do |ii|
79
+ i = ii
80
+ if perm[ii] < n - 1
81
+ flag = false
82
+ break
83
+ end
84
+ end
85
+ return perms if flag
86
+
87
+ perm[i] += 1
88
+ ((i + 1)...k).each { |j| perm[j] = 0 }
89
+ end
90
+ end
69
91
 
92
+ def gen_reduced_variants
93
+ # reduce size of cost_matrix deleting duplicates
94
+ uniq_rows = []
95
+ rows_indices = {}
96
+ cost_matrix.each_with_index do |row, i|
97
+ flag = false
98
+
99
+ uniq_rows.each_with_index do |u_row, j|
100
+ if u_row.eql? row
101
+ flag = true
102
+ rows_indices[i] = j
103
+ end
104
+ end
105
+
106
+ unless flag
107
+ rows_indices[i] = uniq_rows.length
108
+ uniq_rows.push(row)
109
+ end
110
+ end
111
+
112
+ # generating variants for reduced matrix
113
+ vars = gen_permutations(tables_count, uniq_rows.length)
114
+
115
+ # restore variants for full matrix
116
+ vars.map do |variant|
117
+ full_v = Array.new(metrics_count)
118
+ rows_indices.each { |k, v| full_v[k] = variant[v] }
119
+
120
+ full_v
121
+ end
122
+ end
123
+ end
70
124
  end
@@ -20,12 +20,12 @@ module Activecube::Processor
20
20
  (measure.required_column_names - model.attribute_types.keys).empty?
21
21
  end
22
22
 
23
- def query cube_query
23
+ def query cube_query, measures = cube_query.measures
24
24
 
25
25
  table = model.arel_table
26
26
  query = table
27
27
 
28
- (cube_query.slices + cube_query.measures + cube_query.selectors + cube_query.options).each do |s|
28
+ (cube_query.slices + measures + cube_query.selectors + cube_query.options).each do |s|
29
29
  query = s.append_query model, cube_query, table, query
30
30
  end
31
31
 
@@ -52,4 +52,4 @@ module Activecube::Processor
52
52
 
53
53
 
54
54
  end
55
- end
55
+ end
@@ -61,6 +61,14 @@ module Activecube::Query
61
61
  self
62
62
  end
63
63
 
64
+ def desc_by_integer *args
65
+ clear_sql
66
+ args.each{|arg|
67
+ options << Ordering.new(arg, :desc, options = {with_length: true})
68
+ }
69
+ self
70
+ end
71
+
64
72
  def asc *args
65
73
  clear_sql
66
74
  args.each{|arg|
@@ -69,6 +77,14 @@ module Activecube::Query
69
77
  self
70
78
  end
71
79
 
80
+ def asc_by_integer *args
81
+ clear_sql
82
+ args.each{|arg|
83
+ options << Ordering.new(arg, :asc, options = {with_length: true})
84
+ }
85
+ self
86
+ end
87
+
72
88
  def offset *args
73
89
  clear_sql
74
90
  args.each{|arg|
@@ -124,36 +140,6 @@ module Activecube::Query
124
140
  (measures.map(&:selectors) + slices.map(&:selectors) + selectors).flatten.map(&:required_column_names).flatten.uniq
125
141
  end
126
142
 
127
- def reduced other_measures, other_options
128
-
129
- common_selectors = []
130
- other_measures.each_with_index do |m,i|
131
- if i==0
132
- common_selectors += m.selectors
133
- else
134
- common_selectors &= m.selectors
135
- end
136
- end
137
-
138
- if common_selectors.empty?
139
- reduced_measures = other_measures
140
- reduced_selectors = self.selectors
141
- else
142
- reduced_measures = other_measures.collect{|m|
143
- Measure.new m.cube, m.key, m.definition, (m.selectors - common_selectors), m.modifications
144
- }
145
- reduced_selectors = self.selectors + common_selectors
146
- end
147
-
148
- unless reduced_measures.detect{|rm| rm.selectors.empty? }
149
- reduced_selectors += [Selector.or(reduced_measures.map(&:selectors).flatten.uniq)]
150
- end
151
-
152
- return self if (reduced_measures == self.measures) && (reduced_selectors == self.selectors)
153
-
154
- CubeQuery.new cube, slices, reduced_measures, reduced_selectors, other_options, tables
155
- end
156
-
157
143
  def join_fields
158
144
  slices.map(&:group_by_columns).flatten.uniq
159
145
  end
@@ -168,4 +154,4 @@ module Activecube::Query
168
154
  @composed = nil
169
155
  end
170
156
  end
171
- end
157
+ end
@@ -2,15 +2,21 @@ module Activecube
2
2
  module Query
3
3
  class Ordering
4
4
 
5
- attr_reader :argument, :direction
6
- def initialize argument, direction
5
+ attr_reader :argument, :direction, :options
6
+ def initialize argument, direction, options = {}
7
7
  @argument = argument
8
8
  @direction = direction
9
+ @options = options
9
10
  end
10
11
 
11
12
  def append_query _model, _cube_query, _table, query
12
- text = argument.to_s.split(',').map{|s| quote s}.join(',')
13
- query.order(::Arel.sql(text).send(direction))
13
+ @text = argument.to_s.split(',').map{|s| quote s}.join(',')
14
+
15
+ if options[:with_length]
16
+ return by_length_order(query)
17
+ end
18
+
19
+ simple_order(query)
14
20
  end
15
21
 
16
22
  def quote s
@@ -21,6 +27,21 @@ module Activecube
21
27
  end
22
28
  end
23
29
 
30
+ private
31
+
32
+ attr_reader :text
33
+
34
+ def simple_order(query)
35
+ query.order(::Arel.sql(text).send(direction))
36
+ end
37
+
38
+ def by_length_order(query)
39
+ query.order(
40
+ ::Arel.sql("LENGTH(#{text})").send(direction),
41
+ ::Arel.sql(text).send(direction)
42
+ )
43
+ end
44
+
24
45
  end
25
46
  end
26
- end
47
+ end
@@ -5,7 +5,7 @@ module Activecube
5
5
 
6
6
  attr_reader :database, :role
7
7
 
8
- [:slice, :measure, :when, :desc, :asc, :limit, :offset].each do |method|
8
+ [:slice, :measure, :when, :desc, :desc_by_integer, :asc, :asc_by_integer, :limit, :offset].each do |method|
9
9
  define_method(method) do |*args|
10
10
  Query::CubeQuery.new(self).send method, *args
11
11
  end
@@ -1,3 +1,3 @@
1
1
  module Activecube
2
- VERSION = "0.1.40"
2
+ VERSION = "0.1.43"
3
3
  end
@@ -22,7 +22,7 @@ module Activecube
22
22
  true
23
23
  end
24
24
 
25
- def query _cube_query
25
+ def query _cube_query, measures = _cube_query.measures
26
26
  raise "query method have to be implemented in #{name}"
27
27
  end
28
28
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activecube
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.40
4
+ version: 0.1.43
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aleksey Studnev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-10 00:00:00.000000000 Z
11
+ date: 2022-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord