activecube 0.1.0
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 +7 -0
- data/.gitignore +11 -0
- data/.idea/workspace.xml +114 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +60 -0
- data/Rakefile +6 -0
- data/activecube.gemspec +32 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/activecube.rb +6 -0
- data/lib/activecube/active_record_extension.rb +20 -0
- data/lib/activecube/base.rb +6 -0
- data/lib/activecube/clickhouse/metric/count.rb +10 -0
- data/lib/activecube/clickhouse/metric/sum.rb +11 -0
- data/lib/activecube/cube_definition.rb +62 -0
- data/lib/activecube/dimension.rb +5 -0
- data/lib/activecube/dimension_definition_methods.rb +32 -0
- data/lib/activecube/field.rb +12 -0
- data/lib/activecube/metric.rb +5 -0
- data/lib/activecube/processor/composer.rb +76 -0
- data/lib/activecube/processor/index.rb +17 -0
- data/lib/activecube/processor/measure_tables.rb +42 -0
- data/lib/activecube/processor/optimizer.rb +123 -0
- data/lib/activecube/processor/table.rb +54 -0
- data/lib/activecube/query/chain_appender.rb +25 -0
- data/lib/activecube/query/cube_query.rb +112 -0
- data/lib/activecube/query/item.rb +22 -0
- data/lib/activecube/query/limit.rb +17 -0
- data/lib/activecube/query/measure.rb +40 -0
- data/lib/activecube/query/or_selector.rb +20 -0
- data/lib/activecube/query/ordering.rb +17 -0
- data/lib/activecube/query/selector.rb +84 -0
- data/lib/activecube/query/slice.rb +57 -0
- data/lib/activecube/query_methods.rb +11 -0
- data/lib/activecube/selector.rb +11 -0
- data/lib/activecube/version.rb +3 -0
- metadata +140 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
module Activecube::Query
|
2
|
+
class Item
|
3
|
+
|
4
|
+
include ChainAppender
|
5
|
+
|
6
|
+
attr_reader :cube, :key, :definition
|
7
|
+
def initialize cube, key, definition
|
8
|
+
@key = key
|
9
|
+
@cube = cube
|
10
|
+
@definition = definition
|
11
|
+
end
|
12
|
+
|
13
|
+
def required_column_names
|
14
|
+
definition.class.column_names || []
|
15
|
+
end
|
16
|
+
|
17
|
+
def alias! new_key
|
18
|
+
self.class.new cube, new_key, definition
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Activecube
|
2
|
+
module Query
|
3
|
+
class Limit
|
4
|
+
|
5
|
+
attr_reader :argument, :option
|
6
|
+
def initialize argument, option
|
7
|
+
@argument = argument
|
8
|
+
@option = option
|
9
|
+
end
|
10
|
+
|
11
|
+
def append_query _cube_query, _table, query
|
12
|
+
query.send(option,argument)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Activecube::Query
|
2
|
+
class Measure < Item
|
3
|
+
|
4
|
+
attr_reader :selectors
|
5
|
+
|
6
|
+
def initialize cube, key, definition, selectors = []
|
7
|
+
super cube, key, definition
|
8
|
+
@selectors = selectors
|
9
|
+
end
|
10
|
+
|
11
|
+
def required_column_names
|
12
|
+
((definition.class.column_names || []) + selectors.map(&:required_column_names)).flatten.uniq
|
13
|
+
end
|
14
|
+
|
15
|
+
def when *args
|
16
|
+
append *args, @selectors, Selector, cube.selectors
|
17
|
+
end
|
18
|
+
|
19
|
+
def alias! new_key
|
20
|
+
self.class.new cube, new_key, definition, selectors
|
21
|
+
end
|
22
|
+
|
23
|
+
def condition_query arel_table, cube_query
|
24
|
+
condition = nil
|
25
|
+
selectors.each do |selector|
|
26
|
+
condition = condition ?
|
27
|
+
condition.and(selector.expression(arel_table, cube_query)) :
|
28
|
+
selector.expression(arel_table, cube_query)
|
29
|
+
end
|
30
|
+
condition
|
31
|
+
end
|
32
|
+
|
33
|
+
def append_query cube_query, table, query
|
34
|
+
attr_alias = "`#{key.to_s}`"
|
35
|
+
expr = definition.expression table, self, cube_query
|
36
|
+
query.project expr.as(attr_alias)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Activecube
|
2
|
+
module Query
|
3
|
+
class OrSelector < Selector
|
4
|
+
|
5
|
+
attr_reader :selectors
|
6
|
+
def initialize selectors
|
7
|
+
@selectors = selectors
|
8
|
+
end
|
9
|
+
|
10
|
+
def append_query cube_query, table, query
|
11
|
+
expr = nil
|
12
|
+
selectors.each do |s|
|
13
|
+
expr = expr ? expr.or(s.expression table, cube_query) : s.expression(table, cube_query)
|
14
|
+
end
|
15
|
+
query.where(expr)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Activecube
|
2
|
+
module Query
|
3
|
+
class Ordering
|
4
|
+
|
5
|
+
attr_reader :argument, :direction
|
6
|
+
def initialize argument, direction
|
7
|
+
@argument = argument
|
8
|
+
@direction = direction
|
9
|
+
end
|
10
|
+
|
11
|
+
def append_query _cube_query, _table, query
|
12
|
+
query.order(::Arel.sql(argument.to_s).send(direction))
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Activecube::Query
|
2
|
+
class Selector < Item
|
3
|
+
|
4
|
+
OPERATORS = ['eq','ne','gt','lt','ge','le','in','not_in']
|
5
|
+
ARRAY_OPERATORS = ['in','not_in']
|
6
|
+
|
7
|
+
class Operator
|
8
|
+
|
9
|
+
attr_reader :operation, :argument
|
10
|
+
|
11
|
+
def initialize operation, argument
|
12
|
+
@operation = operation
|
13
|
+
@argument = argument
|
14
|
+
end
|
15
|
+
|
16
|
+
def expression left, right
|
17
|
+
left.send(operation, right)
|
18
|
+
end
|
19
|
+
|
20
|
+
def eql?(other)
|
21
|
+
return other.kind_of?(Operator) &&
|
22
|
+
self.operation==other.operation &&
|
23
|
+
self.argument == other.argument
|
24
|
+
end
|
25
|
+
|
26
|
+
def == other
|
27
|
+
eql? other
|
28
|
+
end
|
29
|
+
|
30
|
+
def hash
|
31
|
+
self.operation.hash + self.argument.hash
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_reader :operator
|
37
|
+
def initialize cube, key, definition, operator = nil
|
38
|
+
super cube, key, definition
|
39
|
+
@operator = operator
|
40
|
+
end
|
41
|
+
|
42
|
+
OPERATORS.each do |method|
|
43
|
+
define_method(method) do |*args|
|
44
|
+
if ARRAY_OPERATORS.include? method
|
45
|
+
@operator = Operator.new(method, args)
|
46
|
+
else
|
47
|
+
raise ArgumentError, "Unexpected size of arguments" unless args.size==1
|
48
|
+
@operator = Operator.new(method, args.first)
|
49
|
+
end
|
50
|
+
self
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def alias! new_key
|
55
|
+
self.class.new cube, new_key, definition, operator
|
56
|
+
end
|
57
|
+
|
58
|
+
def append_query cube_query, table, query
|
59
|
+
query.where(expression table, cube_query)
|
60
|
+
end
|
61
|
+
|
62
|
+
def expression arel_table, cube_query
|
63
|
+
definition.expression arel_table, self, cube_query
|
64
|
+
end
|
65
|
+
|
66
|
+
def eql?(other)
|
67
|
+
return other.kind_of?(Selector) &&
|
68
|
+
self.cube==other.cube &&
|
69
|
+
self.operator == other.operator &&
|
70
|
+
self.definition.class == other.definition.class
|
71
|
+
end
|
72
|
+
|
73
|
+
def == other
|
74
|
+
eql? other
|
75
|
+
end
|
76
|
+
|
77
|
+
def hash
|
78
|
+
self.definition.class.hash + self.operator.hash
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
Arel::Nodes::SqlLiteral
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Activecube::Query
|
2
|
+
class Slice < Item
|
3
|
+
|
4
|
+
attr_reader :field, :modifier
|
5
|
+
def initialize cube, key, dimension, field = nil, modifier = nil
|
6
|
+
super cube, key, dimension
|
7
|
+
@field = field
|
8
|
+
@modifier = modifier
|
9
|
+
field_methods! if field.try(:definition).kind_of?(Hash)
|
10
|
+
end
|
11
|
+
|
12
|
+
def [] key
|
13
|
+
unless (definition.kind_of? Activecube::Dimension) && !self.field && (field = definition.class.fields[key])
|
14
|
+
raise "Field #{key} is not defined for #{definition.name}"
|
15
|
+
end
|
16
|
+
Slice.new cube, key, definition, field
|
17
|
+
end
|
18
|
+
|
19
|
+
def alias! new_key
|
20
|
+
self.class.new cube, new_key, definition, field, modifier
|
21
|
+
end
|
22
|
+
|
23
|
+
def dimension_class
|
24
|
+
definition.class
|
25
|
+
end
|
26
|
+
|
27
|
+
def append_query _cube_query, table, query
|
28
|
+
|
29
|
+
attr_alias = "`#{key.to_s}`"
|
30
|
+
expr = field ? Arel.sql( modifier || field.definition ) : table[dimension_class.column_name]
|
31
|
+
query = query.project(expr.as(attr_alias))
|
32
|
+
|
33
|
+
if identity = dimension_class.identity
|
34
|
+
query = query.project(table[identity]).group(table[identity])
|
35
|
+
else
|
36
|
+
query = query.group(attr_alias).order(attr_alias)
|
37
|
+
end
|
38
|
+
|
39
|
+
query
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def field_methods!
|
45
|
+
field.definition.each_pair do |k,v|
|
46
|
+
if v.kind_of? Proc
|
47
|
+
define_singleton_method k, ((proc {|x| @modifier = x; self}) << v)
|
48
|
+
elsif v.kind_of? String
|
49
|
+
define_singleton_method k do @modifier = v; self end
|
50
|
+
else
|
51
|
+
raise "Unexpected type #{k.class.name} for definition of #{name}[#{k}]"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activecube
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Aleksey Studnev
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-02-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.17'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.17'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
description: |-
|
70
|
+
Activecube is the library to make multi-dimensional queries to data.Cube, dimensions, metrics and selectors are defined in the Model, similary to ActiveRecord.
|
71
|
+
Activecube uses Rails ActiveRecord in implementation. In particular, you have to define all tables, used in Activecube, as ActiveRecord tables.
|
72
|
+
email:
|
73
|
+
- astudnev@gmail.com
|
74
|
+
executables: []
|
75
|
+
extensions: []
|
76
|
+
extra_rdoc_files: []
|
77
|
+
files:
|
78
|
+
- ".gitignore"
|
79
|
+
- ".idea/workspace.xml"
|
80
|
+
- ".rspec"
|
81
|
+
- ".travis.yml"
|
82
|
+
- CODE_OF_CONDUCT.md
|
83
|
+
- Gemfile
|
84
|
+
- LICENSE.txt
|
85
|
+
- README.md
|
86
|
+
- Rakefile
|
87
|
+
- activecube.gemspec
|
88
|
+
- bin/console
|
89
|
+
- bin/setup
|
90
|
+
- lib/activecube.rb
|
91
|
+
- lib/activecube/active_record_extension.rb
|
92
|
+
- lib/activecube/base.rb
|
93
|
+
- lib/activecube/clickhouse/metric/count.rb
|
94
|
+
- lib/activecube/clickhouse/metric/sum.rb
|
95
|
+
- lib/activecube/cube_definition.rb
|
96
|
+
- lib/activecube/dimension.rb
|
97
|
+
- lib/activecube/dimension_definition_methods.rb
|
98
|
+
- lib/activecube/field.rb
|
99
|
+
- lib/activecube/metric.rb
|
100
|
+
- lib/activecube/processor/composer.rb
|
101
|
+
- lib/activecube/processor/index.rb
|
102
|
+
- lib/activecube/processor/measure_tables.rb
|
103
|
+
- lib/activecube/processor/optimizer.rb
|
104
|
+
- lib/activecube/processor/table.rb
|
105
|
+
- lib/activecube/query/chain_appender.rb
|
106
|
+
- lib/activecube/query/cube_query.rb
|
107
|
+
- lib/activecube/query/item.rb
|
108
|
+
- lib/activecube/query/limit.rb
|
109
|
+
- lib/activecube/query/measure.rb
|
110
|
+
- lib/activecube/query/or_selector.rb
|
111
|
+
- lib/activecube/query/ordering.rb
|
112
|
+
- lib/activecube/query/selector.rb
|
113
|
+
- lib/activecube/query/slice.rb
|
114
|
+
- lib/activecube/query_methods.rb
|
115
|
+
- lib/activecube/selector.rb
|
116
|
+
- lib/activecube/version.rb
|
117
|
+
homepage: https://github.com/bitquery/activecube
|
118
|
+
licenses:
|
119
|
+
- MIT
|
120
|
+
metadata: {}
|
121
|
+
post_install_message:
|
122
|
+
rdoc_options: []
|
123
|
+
require_paths:
|
124
|
+
- lib
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
requirements: []
|
136
|
+
rubygems_version: 3.0.4
|
137
|
+
signing_key:
|
138
|
+
specification_version: 4
|
139
|
+
summary: Multi-Dimensional Queries with Rails
|
140
|
+
test_files: []
|