rasti-db 1.0.0 → 1.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 +4 -4
- data/README.md +1 -0
- data/lib/rasti/db/collection.rb +2 -2
- data/lib/rasti/db/helpers.rb +1 -3
- data/lib/rasti/db/query.rb +8 -1
- data/lib/rasti/db/relations/base.rb +10 -2
- data/lib/rasti/db/relations/graph_builder.rb +32 -3
- data/lib/rasti/db/relations/many_to_many.rb +23 -4
- data/lib/rasti/db/relations/many_to_one.rb +12 -0
- data/lib/rasti/db/relations/one_to_many.rb +13 -1
- data/lib/rasti/db/version.rb +1 -1
- data/spec/query_spec.rb +54 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3f0307b5b603e80d0dad4b261c1fa3a47c0f0266
|
4
|
+
data.tar.gz: 6c511dc77b55344abe59dcdddfcccf303cced89d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6d538a0b19fc8fe8f9d86bd94c4bceae526be7894e2045f61239b1378f40ba07512d970071bfec613abe045373246fedbc837d871107f32523f65e2aaa27f81
|
7
|
+
data.tar.gz: 83bf69890058e2da151cc3d5429e63c8374ea816b1ce9e28d2f9780c3129a7cb7940055bebcf258c191ae4d9e82f763f940d2eca3d45a3f2479efcd529eaabc2
|
data/README.md
CHANGED
@@ -172,6 +172,7 @@ posts.where(id: [1,2]).raw # => [{id:1, ...}, {id:2, ...}]
|
|
172
172
|
posts.where(id: [1,2]).primary_keys # => [1,2]
|
173
173
|
posts.where(id: [1,2]).pluck(:id) # => [1,2]
|
174
174
|
posts.where(id: [1,2]).pluck(:id, :title) # => [[1, ...], [2, ...]]
|
175
|
+
posts.join(:user).where(name: 'User 4') # => [Post, ...]
|
175
176
|
```
|
176
177
|
|
177
178
|
## Contributing
|
data/lib/rasti/db/collection.rb
CHANGED
@@ -2,7 +2,7 @@ module Rasti
|
|
2
2
|
module DB
|
3
3
|
class Collection
|
4
4
|
|
5
|
-
QUERY_METHODS = (Query::DATASET_CHAINED_METHODS + [:graph, :count, :all, :each, :first, :pluck, :primary_keys, :any?, :empty?, :raw]).freeze
|
5
|
+
QUERY_METHODS = (Query::DATASET_CHAINED_METHODS + [:graph, :join, :count, :all, :each, :first, :pluck, :primary_keys, :any?, :empty?, :raw]).freeze
|
6
6
|
|
7
7
|
include Enumerable
|
8
8
|
include Helpers::WithSchema
|
@@ -192,7 +192,7 @@ module Rasti
|
|
192
192
|
end
|
193
193
|
|
194
194
|
def qualified_collection_name
|
195
|
-
schema.nil? ? self.class.collection_name : Sequel
|
195
|
+
schema.nil? ? Sequel[self.class.collection_name] : Sequel[schema][self.class.collection_name]
|
196
196
|
end
|
197
197
|
|
198
198
|
def query
|
data/lib/rasti/db/helpers.rb
CHANGED
@@ -1,18 +1,16 @@
|
|
1
1
|
module Rasti
|
2
2
|
module DB
|
3
3
|
module Helpers
|
4
|
-
|
5
4
|
module WithSchema
|
6
5
|
|
7
6
|
private
|
8
7
|
|
9
8
|
def with_schema(table, field=nil)
|
10
|
-
qualified_table = schema ? Sequel
|
9
|
+
qualified_table = schema ? Sequel[schema][table] : Sequel[table]
|
11
10
|
field ? Sequel[qualified_table][field] : qualified_table
|
12
11
|
end
|
13
12
|
|
14
13
|
end
|
15
|
-
|
16
14
|
end
|
17
15
|
end
|
18
16
|
end
|
data/lib/rasti/db/query.rb
CHANGED
@@ -19,7 +19,7 @@ module Rasti
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def pluck(*attributes)
|
22
|
-
ds = dataset.select(*attributes.map { |attr| Sequel
|
22
|
+
ds = dataset.select(*attributes.map { |attr| Sequel[collection_class.collection_name][attr] })
|
23
23
|
attributes.count == 1 ? ds.map { |r| r[attributes.first] } : ds.map(&:values)
|
24
24
|
end
|
25
25
|
|
@@ -54,6 +54,13 @@ module Rasti
|
|
54
54
|
schema
|
55
55
|
end
|
56
56
|
|
57
|
+
def join(*rels)
|
58
|
+
Query.new collection_class,
|
59
|
+
Relations::GraphBuilder.joins_to(dataset, rels, collection_class, schema),
|
60
|
+
relations,
|
61
|
+
schema
|
62
|
+
end
|
63
|
+
|
57
64
|
def count
|
58
65
|
dataset.count
|
59
66
|
end
|
@@ -33,16 +33,24 @@ module Rasti
|
|
33
33
|
self.class == OneToOne
|
34
34
|
end
|
35
35
|
|
36
|
+
def join_relation_name(prefix)
|
37
|
+
with_prefix prefix, name
|
38
|
+
end
|
39
|
+
|
36
40
|
private
|
37
41
|
|
38
42
|
attr_reader :options
|
39
43
|
|
40
44
|
def qualified_source_collection_name(schema=nil)
|
41
|
-
schema.nil? ? source_collection_class.collection_name : Sequel
|
45
|
+
schema.nil? ? Sequel[source_collection_class.collection_name] : Sequel[schema][source_collection_class.collection_name]
|
42
46
|
end
|
43
47
|
|
44
48
|
def qualified_target_collection_name(schema=nil)
|
45
|
-
schema.nil? ? target_collection_class.collection_name : Sequel
|
49
|
+
schema.nil? ? Sequel[target_collection_class.collection_name] : Sequel[schema][target_collection_class.collection_name]
|
50
|
+
end
|
51
|
+
|
52
|
+
def with_prefix(prefix, name)
|
53
|
+
[prefix, name].compact.join('__').to_sym
|
46
54
|
end
|
47
55
|
|
48
56
|
end
|
@@ -7,14 +7,25 @@ module Rasti
|
|
7
7
|
def graph_to(rows, relations, collection_class, db, schema=nil)
|
8
8
|
return if rows.empty?
|
9
9
|
|
10
|
-
parse(relations).each do |
|
11
|
-
|
12
|
-
|
10
|
+
parse(relations).each do |relation_name, nested_relations|
|
11
|
+
relation = get_relation collection_class, relation_name
|
12
|
+
relation.graph_to rows, db, schema, nested_relations
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
def joins_to(dataset, relations, collection_class, schema=nil)
|
17
|
+
ds = recusrive_joins dataset, recursive_parse(relations), collection_class, schema
|
18
|
+
qualified_collection_name = schema ? Sequel[schema][collection_class.collection_name] : Sequel[collection_class.collection_name]
|
19
|
+
ds.distinct.select_all(qualified_collection_name)
|
20
|
+
end
|
21
|
+
|
16
22
|
private
|
17
23
|
|
24
|
+
def get_relation(collection_class, relation_name)
|
25
|
+
raise "Undefined relation #{relation_name} for #{collection_class}" unless collection_class.relations.key? relation_name
|
26
|
+
collection_class.relations[relation_name]
|
27
|
+
end
|
28
|
+
|
18
29
|
def parse(relations)
|
19
30
|
relations.each_with_object({}) do |relation, hash|
|
20
31
|
tail = relation.to_s.split '.'
|
@@ -24,6 +35,24 @@ module Rasti
|
|
24
35
|
end
|
25
36
|
end
|
26
37
|
|
38
|
+
def recursive_parse(relations)
|
39
|
+
parse(relations).each_with_object({}) do |(key, value), hash|
|
40
|
+
hash[key] = recursive_parse value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def recusrive_joins(dataset, joins, collection_class, schema, prefix=nil)
|
45
|
+
joins.each do |relation_name, nested_joins|
|
46
|
+
relation = get_relation collection_class, relation_name
|
47
|
+
|
48
|
+
dataset = relation.join_to dataset, schema, prefix
|
49
|
+
|
50
|
+
dataset = recusrive_joins dataset, nested_joins, relation.target_collection_class, schema, relation.join_relation_name(prefix) unless nested_joins.empty?
|
51
|
+
end
|
52
|
+
|
53
|
+
dataset
|
54
|
+
end
|
55
|
+
|
27
56
|
end
|
28
57
|
end
|
29
58
|
end
|
@@ -16,7 +16,7 @@ module Rasti
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def qualified_relation_collection_name(schema=nil)
|
19
|
-
schema.nil? ? relation_collection_name : Sequel
|
19
|
+
schema.nil? ? Sequel[relation_collection_name] : Sequel[schema][relation_collection_name]
|
20
20
|
end
|
21
21
|
|
22
22
|
def graph_to(rows, db, schema=nil, relations=[])
|
@@ -28,9 +28,9 @@ module Rasti
|
|
28
28
|
|
29
29
|
join_rows = target_collection.dataset
|
30
30
|
.join(relation_name, target_foreign_key => target_collection_class.primary_key)
|
31
|
-
.where(Sequel
|
31
|
+
.where(Sequel[relation_name][source_foreign_key] => pks)
|
32
32
|
.select_all(qualified_target_collection_name(schema))
|
33
|
-
.select_append(Sequel
|
33
|
+
.select_append(Sequel[relation_name][source_foreign_key].as(:source_foreign_key))
|
34
34
|
.all
|
35
35
|
|
36
36
|
GraphBuilder.graph_to join_rows, relations, target_collection_class, db, schema
|
@@ -45,11 +45,30 @@ module Rasti
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
def join_to(dataset, schema=nil, prefix=nil)
|
49
|
+
many_to_many_relation_alias = with_prefix prefix, relation_collection_name
|
50
|
+
|
51
|
+
qualified_relation_source = prefix ? Sequel[prefix] : qualified_source_collection_name(schema)
|
52
|
+
|
53
|
+
many_to_many_condition = {
|
54
|
+
Sequel[many_to_many_relation_alias][source_foreign_key] => qualified_relation_source[source_collection_class.primary_key]
|
55
|
+
}
|
56
|
+
|
57
|
+
relation_alias = join_relation_name prefix
|
58
|
+
|
59
|
+
relation_condition = {
|
60
|
+
Sequel[relation_alias][target_collection_class.primary_key] => Sequel[many_to_many_relation_alias][target_foreign_key]
|
61
|
+
}
|
62
|
+
|
63
|
+
dataset.join(qualified_relation_collection_name(schema).as(many_to_many_relation_alias), many_to_many_condition)
|
64
|
+
.join(qualified_target_collection_name(schema).as(relation_alias), relation_condition)
|
65
|
+
end
|
66
|
+
|
48
67
|
def apply_filter(dataset, schema=nil, primary_keys=[])
|
49
68
|
relation_name = qualified_relation_collection_name schema
|
50
69
|
|
51
70
|
dataset.join(relation_name, source_foreign_key => target_collection_class.primary_key)
|
52
|
-
.where(Sequel
|
71
|
+
.where(Sequel[relation_name][target_foreign_key] => primary_keys)
|
53
72
|
.select_all(qualified_source_collection_name(schema))
|
54
73
|
.distinct
|
55
74
|
end
|
@@ -23,6 +23,18 @@ module Rasti
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
def join_to(dataset, schema=nil, prefix=nil)
|
27
|
+
relation_alias = join_relation_name prefix
|
28
|
+
|
29
|
+
qualified_relation_source = prefix ? Sequel[prefix] : qualified_source_collection_name(schema)
|
30
|
+
|
31
|
+
relation_condition = {
|
32
|
+
Sequel[relation_alias][target_collection_class.primary_key] => qualified_relation_source[foreign_key]
|
33
|
+
}
|
34
|
+
|
35
|
+
dataset.join(qualified_target_collection_name(schema).as(relation_alias), relation_condition)
|
36
|
+
end
|
37
|
+
|
26
38
|
def apply_filter(dataset, schema=nil, primary_keys=[])
|
27
39
|
dataset.where(foreign_key => primary_keys)
|
28
40
|
end
|
@@ -21,11 +21,23 @@ module Rasti
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
def join_to(dataset, schema=nil, prefix=nil)
|
25
|
+
relation_alias = join_relation_name prefix
|
26
|
+
|
27
|
+
qualified_relation_source = prefix ? Sequel[prefix] : qualified_source_collection_name(schema)
|
28
|
+
|
29
|
+
relation_condition = {
|
30
|
+
Sequel[relation_alias][foreign_key] => qualified_relation_source[source_collection_class.primary_key]
|
31
|
+
}
|
32
|
+
|
33
|
+
dataset.join(qualified_target_collection_name(schema).as(relation_alias), relation_condition)
|
34
|
+
end
|
35
|
+
|
24
36
|
def apply_filter(dataset, schema=nil, primary_keys=[])
|
25
37
|
target_name = qualified_target_collection_name schema
|
26
38
|
|
27
39
|
dataset.join(target_name, foreign_key => source_collection_class.primary_key)
|
28
|
-
.where(Sequel
|
40
|
+
.where(Sequel[target_name][target_collection_class.primary_key] => primary_keys)
|
29
41
|
.select_all(qualified_source_collection_name(schema))
|
30
42
|
.distinct
|
31
43
|
end
|
data/lib/rasti/db/version.rb
CHANGED
data/spec/query_spec.rb
CHANGED
@@ -4,6 +4,7 @@ describe 'Query' do
|
|
4
4
|
|
5
5
|
before do
|
6
6
|
1.upto(10) { |i| db[:users].insert name: "User #{i}" }
|
7
|
+
|
7
8
|
db[:posts].insert user_id: 2, title: 'Sample post', body: '...'
|
8
9
|
db[:posts].insert user_id: 1, title: 'Another post', body: '...'
|
9
10
|
db[:posts].insert user_id: 4, title: 'Best post', body: '...'
|
@@ -123,4 +124,57 @@ describe 'Query' do
|
|
123
124
|
|
124
125
|
end
|
125
126
|
|
127
|
+
describe 'Join' do
|
128
|
+
|
129
|
+
before do
|
130
|
+
1.upto(10) do |i|
|
131
|
+
db[:people].insert user_id: i,
|
132
|
+
document_number: i,
|
133
|
+
first_name: "Name #{i}",
|
134
|
+
last_name: "Last Name #{i}",
|
135
|
+
birth_date: Time.now
|
136
|
+
end
|
137
|
+
|
138
|
+
1.upto(3) { |i| db[:categories].insert name: "Category #{i}" }
|
139
|
+
|
140
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'Comment 1'
|
141
|
+
db[:comments].insert post_id: 1, user_id: 7, text: 'Comment 2'
|
142
|
+
db[:comments].insert post_id: 2, user_id: 2, text: 'Comment 3'
|
143
|
+
|
144
|
+
db[:categories_posts].insert post_id: 1, category_id: 1
|
145
|
+
db[:categories_posts].insert post_id: 1, category_id: 2
|
146
|
+
db[:categories_posts].insert post_id: 2, category_id: 2
|
147
|
+
db[:categories_posts].insert post_id: 2, category_id: 3
|
148
|
+
db[:categories_posts].insert post_id: 3, category_id: 3
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'One to Many' do
|
152
|
+
users_query.join(:posts).where(title: 'Sample post').all.must_equal [User.new(id: 2, name: 'User 2')]
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'Many to One' do
|
156
|
+
posts_query.join(:user).where(name: 'User 4').all.must_equal [Post.new(id: 3, user_id: 4, title: 'Best post', body: '...')]
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'One to One' do
|
160
|
+
users_query.join(:person).where(document_number: 1).all.must_equal [User.new(id: 1, name: 'User 1')]
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'Many to Many' do
|
164
|
+
posts_query.join(:categories).where(name: 'Category 3').order(:id).all.must_equal [
|
165
|
+
Post.new(id: 2, user_id: 1, title: 'Another post', body: '...'),
|
166
|
+
Post.new(id: 3, user_id: 4, title: 'Best post', body: '...'),
|
167
|
+
]
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'Nested' do
|
171
|
+
posts_query.join('categories', 'comments.user.person')
|
172
|
+
.where(Sequel[:categories][:name] => 'Category 2')
|
173
|
+
.where(Sequel[:comments__user__person][:document_number] => 7)
|
174
|
+
.all
|
175
|
+
.must_equal [Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...')]
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
|
126
180
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rasti-db
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gabriel Naiman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-09-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|