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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 01b5188397b357e5b8414eebd556115131bb8c46
4
- data.tar.gz: 84d1beb743f8a8ff07247724013bb8c0f9394ede
3
+ metadata.gz: 3f0307b5b603e80d0dad4b261c1fa3a47c0f0266
4
+ data.tar.gz: 6c511dc77b55344abe59dcdddfcccf303cced89d
5
5
  SHA512:
6
- metadata.gz: 10563c028636028583d1205b0c999ad82e5281180ba16367442b1f5804510b09184db8930145e9937e2a82e675879aa9f56a8eea8f399ab6346eb6f40a6df1eb
7
- data.tar.gz: a8ba4affb905f24c39cfab601b51cd263ccf2ab3c34c22494e4fc53475e96530e73df7e2759af381e7d1f2f288b2f168408432138a37042b40823a1697c64a46
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
@@ -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.qualify(schema, self.class.collection_name)
195
+ schema.nil? ? Sequel[self.class.collection_name] : Sequel[schema][self.class.collection_name]
196
196
  end
197
197
 
198
198
  def query
@@ -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.qualify(schema, table) : table
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
@@ -19,7 +19,7 @@ module Rasti
19
19
  end
20
20
 
21
21
  def pluck(*attributes)
22
- ds = dataset.select(*attributes.map { |attr| Sequel.qualify(collection_class.collection_name, attr) })
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.qualify(schema, source_collection_class.collection_name)
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.qualify(schema, target_collection_class.collection_name)
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 |relation, nested_relations|
11
- raise "Undefined relation #{relation} for #{collection_class}" unless collection_class.relations.key? relation
12
- collection_class.relations[relation].graph_to rows, db, schema, nested_relations
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.qualify(schema, relation_collection_name)
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.qualify(relation_name, source_foreign_key) => pks)
31
+ .where(Sequel[relation_name][source_foreign_key] => pks)
32
32
  .select_all(qualified_target_collection_name(schema))
33
- .select_append(Sequel.qualify(relation_name, source_foreign_key).as(:source_foreign_key))
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.qualify(relation_name, target_foreign_key) => primary_keys)
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.qualify(target_name, target_collection_class.primary_key) => primary_keys)
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
@@ -1,5 +1,5 @@
1
1
  module Rasti
2
2
  module DB
3
- VERSION = '1.0.0'
3
+ VERSION = '1.1.0'
4
4
  end
5
5
  end
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.0.0
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-08-21 00:00:00.000000000 Z
11
+ date: 2019-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel