activecube 0.1.41 → 0.1.44

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: 566db205500299f766f3971b9692e876926ca5ff1f65fbfea78a8c19ed4c501d
4
- data.tar.gz: 33c2890756ea8fba2d4dc28a877fcf21891a56783d63a996d5bf3c5cfde14033
3
+ metadata.gz: f4657cc9edb63bf6760180e758e985d47bbd452b479d17a9dea044a5030ca83a
4
+ data.tar.gz: ce8fe2944bccabb655d76924a677f1a7a0324d5b7a6d88e2ed33d10813923d00
5
5
  SHA512:
6
- metadata.gz: 54316348e68e897854789e8a7dd3ac628fbab5b1c1b4e4fa877faff72ecbe42ebe2a589c77f31b2287af0c40dc03efd8da9467bba6eaa59466c4951cb9c6d638
7
- data.tar.gz: aed6fcd142c56ef9f56a84b9efb00bab50a7b96090d9d4379653991dc387b6ae1d7249da5170389422d57ca683b4e9f853eb3549559d1e160db5583be8dcc2bc
6
+ metadata.gz: 1edc0deb21fac6290515851e11c678e2a4f1c65db5c760163b3f37566680f6318c8e91e0d6e72d672a21dca59aac4c6f16fe722d59302cde3e65804d9ccf7a86
7
+ data.tar.gz: 17198fbc0d5b0d0879d194e62e32b3906eadc3bd86ff8684fccc8c2ed220bcf066c79277b67ec181e9a61e52ed1a9b274f9d4edd1e6ed9f741120cae010a45d9
data/Gemfile.lock CHANGED
@@ -9,7 +9,7 @@ GIT
9
9
  PATH
10
10
  remote: .
11
11
  specs:
12
- activecube (0.1.40)
12
+ activecube (0.1.44)
13
13
  activerecord (>= 5.2)
14
14
 
15
15
  GEM
@@ -75,11 +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
- table_query = table.query cube_query
78
+ table_query = table.query cube_query, list.map(&:measure)
79
79
  composed_query = composed_query ? table.join(cube_query, composed_query, table_query) : table_query
80
80
  end
81
81
  composed_query
82
82
  end
83
83
 
84
84
  end
85
- 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,103 @@ 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
91
+
92
+ def gen_reduced_variants
93
+ # reduce size of cost_matrix deleting duplicates
94
+ uniq_rows = []
95
+ rows_indices = {}
96
+ possible_tables = {}
97
+ cost_matrix.each_with_index do |row, i|
98
+ flag = false
99
+
100
+ uniq_rows.each_with_index do |u_row, j|
101
+ if u_row.eql? row
102
+ flag = true
103
+ rows_indices[i] = j
104
+ end
105
+ end
106
+
107
+ unless flag
108
+ rows_indices[i] = uniq_rows.length
109
+ possible_tables[i] = Hash[row.map.with_index { |c, index| [index, true] if c }.compact]
110
+ uniq_rows.push(row)
111
+ end
112
+ end
113
+
114
+ # generating variants for reduced matrix
115
+ vars = gen_permutations(tables_count, uniq_rows.length)
69
116
 
117
+ # filter possible variants
118
+ vars = vars.filter do |v|
119
+ v.map.with_index.all? {|t_n, i| possible_tables[i][t_n]}
120
+ end
121
+
122
+ # restore variants for full matrix
123
+ vars.map do |variant|
124
+ full_v = Array.new(metrics_count)
125
+ rows_indices.each { |k, v| full_v[k] = variant[v] }
126
+
127
+ full_v
128
+ end
129
+ end
130
+ end
70
131
  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|
@@ -138,4 +154,4 @@ module Activecube::Query
138
154
  @composed = nil
139
155
  end
140
156
  end
141
- 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.41"
2
+ VERSION = "0.1.44"
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.41
4
+ version: 0.1.44
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-03-03 00:00:00.000000000 Z
11
+ date: 2022-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord