rasti-db 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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