activecube 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.idea/workspace.xml +45 -14
- data/Gemfile +5 -0
- data/Gemfile.lock +64 -0
- data/README.md +131 -3
- data/lib/activecube.rb +15 -2
- data/lib/activecube/active_record_extension.rb +0 -3
- data/lib/activecube/base.rb +3 -0
- data/lib/activecube/{clickhouse/metric → common}/count.rb +1 -1
- data/lib/activecube/{clickhouse/metric → common}/sum.rb +1 -1
- data/lib/activecube/dimension.rb +2 -0
- data/lib/activecube/dimension_definition_methods.rb +3 -0
- data/lib/activecube/metric.rb +2 -0
- data/lib/activecube/processor/composer.rb +5 -0
- data/lib/activecube/processor/optimizer.rb +2 -1
- data/lib/activecube/query/cube_query.rb +11 -0
- data/lib/activecube/query/or_selector.rb +2 -0
- data/lib/activecube/query/selector.rb +0 -2
- data/lib/activecube/query_methods.rb +2 -0
- data/lib/activecube/selector.rb +2 -0
- data/lib/activecube/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: baf4f5a3146bb1c03244f62328b0af901ae7882e41ff4234a86e1deb6cd881a9
|
4
|
+
data.tar.gz: 44ca0d2eefbf2b4cc38e95aa9ab2b352607b4817b5c5aaebce8b2a04022037f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac3b3dd34000d54054eba5a0fc7b6aa9803f7643f4f1cc67c88fc603c9e34d07a7ae7ef2eed755efca7bdcd60f532c25b67962b45f20550df98bcb2fc2e13a19
|
7
|
+
data.tar.gz: 408881f9f8f5c3c3b2af544f320846f8f9765cf3f9673e196c9d2f32555901c221539786eb4c3fa487a082f1d62bf2939442f836fe73cdf6e559bea4ba5f8945
|
data/.idea/workspace.xml
CHANGED
@@ -10,10 +10,7 @@
|
|
10
10
|
<select />
|
11
11
|
</component>
|
12
12
|
<component name="ChangeListManager">
|
13
|
-
<list default="true" id="77368870-4045-496a-9737-2c7f83086a16" name="Default Changelist" comment="initial implementation"
|
14
|
-
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
15
|
-
<change beforePath="$PROJECT_DIR$/activecube.gemspec" beforeDir="false" afterPath="$PROJECT_DIR$/activecube.gemspec" afterDir="false" />
|
16
|
-
</list>
|
13
|
+
<list default="true" id="77368870-4045-496a-9737-2c7f83086a16" name="Default Changelist" comment="initial implementation" />
|
17
14
|
<option name="SHOW_DIALOG" value="false" />
|
18
15
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
19
16
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
@@ -31,11 +28,20 @@
|
|
31
28
|
<component name="PropertiesComponent">
|
32
29
|
<property name="WebServerToolWindowFactoryState" value="false" />
|
33
30
|
<property name="last_opened_file_path" value="$PROJECT_DIR$/lib/activecube" />
|
31
|
+
<property name="node.js.detected.package.eslint" value="true" />
|
32
|
+
<property name="node.js.detected.package.tslint" value="true" />
|
33
|
+
<property name="node.js.path.for.package.eslint" value="project" />
|
34
|
+
<property name="node.js.path.for.package.tslint" value="project" />
|
35
|
+
<property name="node.js.selected.package.eslint" value="(autodetect)" />
|
36
|
+
<property name="node.js.selected.package.tslint" value="(autodetect)" />
|
34
37
|
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
|
35
38
|
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
|
36
39
|
<property name="settings.editor.selected.configurable" value="preferences.lookFeel" />
|
37
40
|
</component>
|
38
41
|
<component name="RecentsManager">
|
42
|
+
<key name="MoveFile.RECENT_KEYS">
|
43
|
+
<recent name="$PROJECT_DIR$/lib/activecube" />
|
44
|
+
</key>
|
39
45
|
<key name="CopyFile.RECENT_KEYS">
|
40
46
|
<recent name="$PROJECT_DIR$/lib/activecube" />
|
41
47
|
</key>
|
@@ -51,7 +57,7 @@
|
|
51
57
|
<option name="number" value="Default" />
|
52
58
|
<option name="presentableId" value="Default" />
|
53
59
|
<updated>1581885096407</updated>
|
54
|
-
<workItem from="1581885099890" duration="
|
60
|
+
<workItem from="1581885099890" duration="3547000" />
|
55
61
|
</task>
|
56
62
|
<task id="LOCAL-00001" summary="initial commit">
|
57
63
|
<created>1581885128091</created>
|
@@ -67,7 +73,28 @@
|
|
67
73
|
<option name="project" value="LOCAL" />
|
68
74
|
<updated>1581885329956</updated>
|
69
75
|
</task>
|
70
|
-
<
|
76
|
+
<task id="LOCAL-00003" summary="initial implementation">
|
77
|
+
<created>1581886068687</created>
|
78
|
+
<option name="number" value="00003" />
|
79
|
+
<option name="presentableId" value="LOCAL-00003" />
|
80
|
+
<option name="project" value="LOCAL" />
|
81
|
+
<updated>1581886068687</updated>
|
82
|
+
</task>
|
83
|
+
<task id="LOCAL-00004" summary="initial implementation">
|
84
|
+
<created>1581888304903</created>
|
85
|
+
<option name="number" value="00004" />
|
86
|
+
<option name="presentableId" value="LOCAL-00004" />
|
87
|
+
<option name="project" value="LOCAL" />
|
88
|
+
<updated>1581888304904</updated>
|
89
|
+
</task>
|
90
|
+
<task id="LOCAL-00005" summary="initial implementation">
|
91
|
+
<created>1581888510999</created>
|
92
|
+
<option name="number" value="00005" />
|
93
|
+
<option name="presentableId" value="LOCAL-00005" />
|
94
|
+
<option name="project" value="LOCAL" />
|
95
|
+
<updated>1581888510999</updated>
|
96
|
+
</task>
|
97
|
+
<option name="localTasksCounter" value="6" />
|
71
98
|
<servers />
|
72
99
|
</component>
|
73
100
|
<component name="TypeScriptGeneratedFilesManager">
|
@@ -90,22 +117,26 @@
|
|
90
117
|
<option name="LAST_COMMIT_MESSAGE" value="initial implementation" />
|
91
118
|
</component>
|
92
119
|
<component name="WindowStateProjectService">
|
93
|
-
<state width="1207" height="
|
120
|
+
<state width="1207" height="48" key="GridCell.Tab.0.bottom" timestamp="1581888894138">
|
121
|
+
<screen x="0" y="23" width="1440" height="786" />
|
122
|
+
</state>
|
123
|
+
<state width="1207" height="48" key="GridCell.Tab.0.bottom/0.23.1440.786@0.23.1440.786" timestamp="1581888894138" />
|
124
|
+
<state width="1207" height="48" key="GridCell.Tab.0.center" timestamp="1581888894135">
|
94
125
|
<screen x="0" y="23" width="1440" height="786" />
|
95
126
|
</state>
|
96
|
-
<state width="1207" height="
|
97
|
-
<state width="1207" height="
|
127
|
+
<state width="1207" height="48" key="GridCell.Tab.0.center/0.23.1440.786@0.23.1440.786" timestamp="1581888894135" />
|
128
|
+
<state width="1207" height="48" key="GridCell.Tab.0.left" timestamp="1581888894133">
|
98
129
|
<screen x="0" y="23" width="1440" height="786" />
|
99
130
|
</state>
|
100
|
-
<state width="1207" height="
|
101
|
-
<state width="1207" height="
|
131
|
+
<state width="1207" height="48" key="GridCell.Tab.0.left/0.23.1440.786@0.23.1440.786" timestamp="1581888894133" />
|
132
|
+
<state width="1207" height="48" key="GridCell.Tab.0.right" timestamp="1581888894136">
|
102
133
|
<screen x="0" y="23" width="1440" height="786" />
|
103
134
|
</state>
|
104
|
-
<state width="1207" height="
|
105
|
-
<state
|
135
|
+
<state width="1207" height="48" key="GridCell.Tab.0.right/0.23.1440.786@0.23.1440.786" timestamp="1581888894136" />
|
136
|
+
<state x="537" y="156" key="Vcs.Push.Dialog.v2" timestamp="1581888518182">
|
106
137
|
<screen x="0" y="23" width="1440" height="786" />
|
107
138
|
</state>
|
108
|
-
<state
|
139
|
+
<state x="537" y="156" key="Vcs.Push.Dialog.v2/0.23.1440.786@0.23.1440.786" timestamp="1581888518182" />
|
109
140
|
<state x="352" y="201" width="819" height="558" key="find.popup" timestamp="1581885294826">
|
110
141
|
<screen x="0" y="23" width="1440" height="786" />
|
111
142
|
</state>
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
GIT
|
2
|
+
remote: https://github.com/bitquery/clickhouse-activerecord.git
|
3
|
+
revision: 14e02bb475bb4974cc4d853b055b147fe4d59171
|
4
|
+
specs:
|
5
|
+
clickhouse-activerecord (0.3.9)
|
6
|
+
activerecord (>= 5.2)
|
7
|
+
bundler (>= 1.13.4)
|
8
|
+
|
9
|
+
PATH
|
10
|
+
remote: .
|
11
|
+
specs:
|
12
|
+
activecube (0.1.0)
|
13
|
+
activerecord (>= 5.2)
|
14
|
+
|
15
|
+
GEM
|
16
|
+
remote: https://rubygems.org/
|
17
|
+
specs:
|
18
|
+
activemodel (6.0.2.1)
|
19
|
+
activesupport (= 6.0.2.1)
|
20
|
+
activerecord (6.0.2.1)
|
21
|
+
activemodel (= 6.0.2.1)
|
22
|
+
activesupport (= 6.0.2.1)
|
23
|
+
activesupport (6.0.2.1)
|
24
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
25
|
+
i18n (>= 0.7, < 2)
|
26
|
+
minitest (~> 5.1)
|
27
|
+
tzinfo (~> 1.1)
|
28
|
+
zeitwerk (~> 2.2)
|
29
|
+
concurrent-ruby (1.1.6)
|
30
|
+
diff-lcs (1.3)
|
31
|
+
i18n (1.8.2)
|
32
|
+
concurrent-ruby (~> 1.0)
|
33
|
+
minitest (5.14.0)
|
34
|
+
rake (10.5.0)
|
35
|
+
rspec (3.9.0)
|
36
|
+
rspec-core (~> 3.9.0)
|
37
|
+
rspec-expectations (~> 3.9.0)
|
38
|
+
rspec-mocks (~> 3.9.0)
|
39
|
+
rspec-core (3.9.1)
|
40
|
+
rspec-support (~> 3.9.1)
|
41
|
+
rspec-expectations (3.9.0)
|
42
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
43
|
+
rspec-support (~> 3.9.0)
|
44
|
+
rspec-mocks (3.9.1)
|
45
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
46
|
+
rspec-support (~> 3.9.0)
|
47
|
+
rspec-support (3.9.2)
|
48
|
+
thread_safe (0.3.6)
|
49
|
+
tzinfo (1.2.6)
|
50
|
+
thread_safe (~> 0.1)
|
51
|
+
zeitwerk (2.2.2)
|
52
|
+
|
53
|
+
PLATFORMS
|
54
|
+
ruby
|
55
|
+
|
56
|
+
DEPENDENCIES
|
57
|
+
activecube!
|
58
|
+
bundler (~> 1.17)
|
59
|
+
clickhouse-activerecord!
|
60
|
+
rake (~> 10.0)
|
61
|
+
rspec (~> 3.0)
|
62
|
+
|
63
|
+
BUNDLED WITH
|
64
|
+
1.17.3
|
data/README.md
CHANGED
@@ -39,7 +39,124 @@ Or install it yourself as:
|
|
39
39
|
|
40
40
|
## Usage
|
41
41
|
|
42
|
-
|
42
|
+
Basic steps to use ActiveCube are:
|
43
|
+
|
44
|
+
1. Define your database schema in models, as you do with Rails
|
45
|
+
2. Setup connection properties to data warehouse in config/database.yml. You can use multiple connections
|
46
|
+
if you use Rails 6 or higher
|
47
|
+
3. Define cubes in models, sub-classed from Activecube::Base. Look
|
48
|
+
[spec/models/test/transfers_cube.rb](spec/models/test/transfers_cube.rb) as example
|
49
|
+
4. Make queries to the cubes
|
50
|
+
|
51
|
+
Check [spec/cases/activecube_spec.rb](spec/cases/activecube_spec.rb) for more examples.
|
52
|
+
|
53
|
+
|
54
|
+
### Cube definition
|
55
|
+
|
56
|
+
Cube defined using the following attributes:
|
57
|
+
|
58
|
+
- **table** specifies, which physical database tables can be considered to query
|
59
|
+
```ruby
|
60
|
+
table TransfersCurrency
|
61
|
+
table TransfersFrom
|
62
|
+
table TransfersTo
|
63
|
+
```
|
64
|
+
|
65
|
+
- **dimension** specifies classes used for slicing the cube
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
dimension date: Dimension::Date,
|
69
|
+
currency: Dimension::Currency
|
70
|
+
```
|
71
|
+
|
72
|
+
Or
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
dimension date: Dimension::Date
|
76
|
+
dimension currency: Dimension::Currency
|
77
|
+
```
|
78
|
+
|
79
|
+
- **metric** specifies which results expected from the cube queries
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
metric amount: Metric::Amount,
|
83
|
+
count: Metric::Count
|
84
|
+
```
|
85
|
+
|
86
|
+
Or
|
87
|
+
|
88
|
+
```ruby
|
89
|
+
metric amount: Metric::Amount
|
90
|
+
metric count: Metric::Count
|
91
|
+
```
|
92
|
+
|
93
|
+
- **selector** is a set of expressions, which can filter results
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
selector currency: CurrencySelector,
|
97
|
+
transfer_from: TransferFromSelector,
|
98
|
+
transfer_to: TransferToSelector
|
99
|
+
```
|
100
|
+
|
101
|
+
### Table definition
|
102
|
+
|
103
|
+
Tables are defined as regular active records, with additional optional attribute 'index':
|
104
|
+
```ruby
|
105
|
+
index 'currency_id', cardinality: 4
|
106
|
+
```
|
107
|
+
|
108
|
+
which means that the table has an index onm currency_id field, with average number of different entries
|
109
|
+
of 10,000 ( 10^4). This creates a hint for optimizer to build queries.
|
110
|
+
|
111
|
+
Indexes can span multiple fields, as
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
index ['currency_id','date'], cardinality: 6
|
115
|
+
```
|
116
|
+
|
117
|
+
Note, that if you created combined index in database, you most probable will need to define all
|
118
|
+
indexed combinations, for example:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
index ['currency_id'], cardinality: 4
|
122
|
+
index ['currency_id','date'], cardinality: 6
|
123
|
+
```
|
124
|
+
|
125
|
+
### Query language
|
126
|
+
|
127
|
+
You use the cube class to create and execute queries.
|
128
|
+
|
129
|
+
Queries can be expressed as Arel query, SQL or executed against the database, returning results.
|
130
|
+
|
131
|
+
The methods used to contruct the query:
|
132
|
+
|
133
|
+
- **slice** defines which dimensions slices the results
|
134
|
+
- **measure** defines what to measure
|
135
|
+
- **where** defines which selectors to apply
|
136
|
+
- **desc, asc, take, limit** are for ordering and limiting result set
|
137
|
+
|
138
|
+
After the query contructed, the following methods can be applied:
|
139
|
+
|
140
|
+
- **to_sql** to generate String SQL query from cube query
|
141
|
+
- **to_query** to generate Arel query
|
142
|
+
- **query** to execute query and return ResultSet
|
143
|
+
|
144
|
+
Note, that you can control the connection used to construct and execute query by
|
145
|
+
ActiveRecord standard API:
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
|
149
|
+
ApplicationRecord.connected_to(database: :data_warehouse) do
|
150
|
+
cube = My::TransfersCube
|
151
|
+
cube.slice(
|
152
|
+
date: cube.dimensions[:date][:date].format('%Y-%m'),
|
153
|
+
currency: cube.dimensions[:currency][:symbol]
|
154
|
+
).measure(:count).query
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
158
|
+
will query using data_warehouse configuraton.
|
159
|
+
|
43
160
|
|
44
161
|
## Development
|
45
162
|
|
@@ -47,9 +164,20 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
47
164
|
|
48
165
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
49
166
|
|
167
|
+
## RSPec tests
|
168
|
+
|
169
|
+
|
170
|
+
To run tests, you need clickhouse server installation.
|
171
|
+
Tests use database 'test' that have to be created in clickhouse as:
|
172
|
+
```sql
|
173
|
+
CREATE DATABASE test;
|
174
|
+
```
|
175
|
+
Check credentials for connection in [spec/spec_helper.rb](spec/spec_helper.rb) file.
|
176
|
+
By default clickhouse must reside on "clickhouse" server name, port 8123 with the default user access open.
|
177
|
+
|
50
178
|
## Contributing
|
51
179
|
|
52
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
180
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/bitquery/activecube. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
53
181
|
|
54
182
|
## License
|
55
183
|
|
@@ -57,4 +185,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
57
185
|
|
58
186
|
## Code of Conduct
|
59
187
|
|
60
|
-
Everyone interacting in the Activecube project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
188
|
+
Everyone interacting in the Activecube project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/bitquery/activecube/blob/master/CODE_OF_CONDUCT.md).
|
data/lib/activecube.rb
CHANGED
@@ -1,6 +1,19 @@
|
|
1
1
|
require "activecube/version"
|
2
|
+
require 'activecube/active_record_extension'
|
3
|
+
|
4
|
+
require 'activecube/base'
|
5
|
+
require 'activecube/dimension'
|
6
|
+
require 'activecube/metric'
|
7
|
+
require 'activecube/selector'
|
8
|
+
|
9
|
+
require 'activecube/common/count'
|
10
|
+
require 'activecube/common/sum'
|
11
|
+
|
12
|
+
require 'active_record'
|
2
13
|
|
3
14
|
module Activecube
|
4
|
-
|
5
|
-
#
|
15
|
+
|
16
|
+
# include the extension
|
17
|
+
ActiveRecord::Base.send(:include, Activecube::ActiveRecordExtension)
|
18
|
+
|
6
19
|
end
|
data/lib/activecube/base.rb
CHANGED
data/lib/activecube/dimension.rb
CHANGED
data/lib/activecube/metric.rb
CHANGED
@@ -8,11 +8,12 @@ module Activecube::Processor
|
|
8
8
|
attr_reader :tables_count, :metrics_count, :cost_matrix
|
9
9
|
def initialize cost_matrix
|
10
10
|
@cost_matrix = cost_matrix
|
11
|
+
@cache = ActiveSupport::Cache::MemoryStore.new
|
11
12
|
end
|
12
13
|
|
13
14
|
def optimize
|
14
15
|
|
15
|
-
|
16
|
+
@cache.fetch(cost_matrix, expires_in: 12.hours) do
|
16
17
|
|
17
18
|
@tables_count = cost_matrix.map(&:count).max
|
18
19
|
@metrics_count = cost_matrix.count
|
@@ -1,3 +1,14 @@
|
|
1
|
+
require 'activecube/query/chain_appender'
|
2
|
+
require 'activecube/query/item'
|
3
|
+
require 'activecube/query/limit'
|
4
|
+
require 'activecube/query/measure'
|
5
|
+
require 'activecube/query/or_selector'
|
6
|
+
require 'activecube/query/ordering'
|
7
|
+
require 'activecube/query/selector'
|
8
|
+
require 'activecube/query/slice'
|
9
|
+
|
10
|
+
require 'activecube/processor/composer'
|
11
|
+
|
1
12
|
module Activecube::Query
|
2
13
|
class CubeQuery
|
3
14
|
|
data/lib/activecube/selector.rb
CHANGED
data/lib/activecube/version.rb
CHANGED
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.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aleksey Studnev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-02-
|
11
|
+
date: 2020-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -81,6 +81,7 @@ files:
|
|
81
81
|
- ".travis.yml"
|
82
82
|
- CODE_OF_CONDUCT.md
|
83
83
|
- Gemfile
|
84
|
+
- Gemfile.lock
|
84
85
|
- LICENSE.txt
|
85
86
|
- README.md
|
86
87
|
- Rakefile
|
@@ -90,8 +91,8 @@ files:
|
|
90
91
|
- lib/activecube.rb
|
91
92
|
- lib/activecube/active_record_extension.rb
|
92
93
|
- lib/activecube/base.rb
|
93
|
-
- lib/activecube/
|
94
|
-
- lib/activecube/
|
94
|
+
- lib/activecube/common/count.rb
|
95
|
+
- lib/activecube/common/sum.rb
|
95
96
|
- lib/activecube/cube_definition.rb
|
96
97
|
- lib/activecube/dimension.rb
|
97
98
|
- lib/activecube/dimension_definition_methods.rb
|