rasti-db 1.4.0 → 2.2.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -3
  3. data/README.md +88 -24
  4. data/lib/rasti/db.rb +2 -1
  5. data/lib/rasti/db/collection.rb +79 -46
  6. data/lib/rasti/db/computed_attribute.rb +22 -0
  7. data/lib/rasti/db/data_source.rb +18 -0
  8. data/lib/rasti/db/environment.rb +32 -0
  9. data/lib/rasti/db/nql/nodes/attribute.rb +37 -0
  10. data/lib/rasti/db/nql/nodes/binary_node.rb +4 -0
  11. data/lib/rasti/db/nql/nodes/comparisons/base.rb +5 -1
  12. data/lib/rasti/db/nql/nodes/comparisons/equal.rb +2 -2
  13. data/lib/rasti/db/nql/nodes/comparisons/greater_than.rb +2 -2
  14. data/lib/rasti/db/nql/nodes/comparisons/greater_than_or_equal.rb +2 -2
  15. data/lib/rasti/db/nql/nodes/comparisons/include.rb +2 -2
  16. data/lib/rasti/db/nql/nodes/comparisons/less_than.rb +2 -2
  17. data/lib/rasti/db/nql/nodes/comparisons/less_than_or_equal.rb +2 -2
  18. data/lib/rasti/db/nql/nodes/comparisons/like.rb +2 -2
  19. data/lib/rasti/db/nql/nodes/comparisons/not_equal.rb +2 -2
  20. data/lib/rasti/db/nql/nodes/comparisons/not_include.rb +2 -2
  21. data/lib/rasti/db/nql/nodes/conjunction.rb +2 -2
  22. data/lib/rasti/db/nql/nodes/disjunction.rb +2 -2
  23. data/lib/rasti/db/nql/nodes/parenthesis_sentence.rb +6 -2
  24. data/lib/rasti/db/nql/nodes/sentence.rb +6 -2
  25. data/lib/rasti/db/nql/syntax.rb +33 -33
  26. data/lib/rasti/db/nql/syntax.treetop +12 -12
  27. data/lib/rasti/db/query.rb +107 -43
  28. data/lib/rasti/db/relations/base.rb +22 -8
  29. data/lib/rasti/db/relations/graph.rb +129 -0
  30. data/lib/rasti/db/relations/many_to_many.rb +58 -24
  31. data/lib/rasti/db/relations/many_to_one.rb +17 -12
  32. data/lib/rasti/db/relations/one_to_many.rb +27 -16
  33. data/lib/rasti/db/version.rb +1 -1
  34. data/rasti-db.gemspec +3 -7
  35. data/spec/collection_spec.rb +223 -52
  36. data/spec/computed_attribute_spec.rb +32 -0
  37. data/spec/minitest_helper.rb +76 -15
  38. data/spec/model_spec.rb +4 -2
  39. data/spec/nql/computed_attributes_spec.rb +29 -0
  40. data/spec/nql/filter_condition_spec.rb +4 -2
  41. data/spec/nql/syntax_parser_spec.rb +12 -5
  42. data/spec/query_spec.rb +319 -85
  43. data/spec/relations_spec.rb +27 -7
  44. metadata +41 -7
  45. data/lib/rasti/db/helpers.rb +0 -16
  46. data/lib/rasti/db/nql/nodes/field.rb +0 -23
  47. data/lib/rasti/db/relations/graph_builder.rb +0 -60
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed5332eda8adfde54d7465d8f3f631d9b542f54d17c78644703d2f9054cb1bca
4
- data.tar.gz: 5452a867c32c4083f10149c3496093e731d6f8d64a6b13fafd57ebcc0d7e38c8
3
+ metadata.gz: d9da5c8d1c2a7912585a7b1f43e9f3ded9dc859e362ce071c692659e4f98b4ba
4
+ data.tar.gz: fa12eafca7db2b3b540871e8701218d3bb176a7cbd3b1c36d57b8fef4884064f
5
5
  SHA512:
6
- metadata.gz: 31a039adaeb64c98fa7f5c38b2155a009f78e2a824d9c8d4e9969bd2d9ff7599afc899d5b10c3864694a22540061cf0f439f681792f2f89e9eb9da030aa7c28e
7
- data.tar.gz: 393c7b91108ff8ab2c8effed2016b4ea912747baf65194c05614a01ef9d4d4447d41f350e996f0bdf8b14b9de102ced09bd023ce9cef590306068c28a8ae051c
6
+ metadata.gz: cd5dbacac1bf5afe377e2c3078691e8b77afed7c1fe0fa55a25e1c446f698c91630bb07045791d1aacaad45fef2967c27b2a316368083a4e27d0fd45f36c6955
7
+ data.tar.gz: 83a7a7048def925647078c13cfe241ca3f082cb0ab41a377d9d58fef69de1ffc06fcd781f62e51b7677bf3ffb1d60889a8d88941bc3e44c3127f656e1af720d9
@@ -1,7 +1,6 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - 2.0
5
4
  - 2.1
6
5
  - 2.2
7
6
  - 2.3
@@ -9,8 +8,7 @@ rvm:
9
8
  - 2.5
10
9
  - 2.6
11
10
  - 2.7
12
- - jruby-9.1.7.0
13
- - jruby-9.1.16.0
11
+ - jruby-9.2.9.0
14
12
  - ruby-head
15
13
  - jruby-head
16
14
 
data/README.md CHANGED
@@ -4,7 +4,6 @@
4
4
  [![Build Status](https://travis-ci.org/gabynaiman/rasti-db.svg?branch=master)](https://travis-ci.org/gabynaiman/rasti-db)
5
5
  [![Coverage Status](https://coveralls.io/repos/github/gabynaiman/rasti-db/badge.svg?branch=master)](https://coveralls.io/github/gabynaiman/rasti-db?branch=master)
6
6
  [![Code Climate](https://codeclimate.com/github/gabynaiman/rasti-db.svg)](https://codeclimate.com/github/gabynaiman/rasti-db)
7
- [![Dependency Status](https://gemnasium.com/gabynaiman/rasti-db.svg)](https://gemnasium.com/gabynaiman/rasti-db)
8
7
 
9
8
  Database collections and relations
10
9
 
@@ -29,49 +28,62 @@ Or install it yourself as:
29
28
  ### Database connection
30
29
 
31
30
  ```ruby
32
- DB = Sequel.connect ...
31
+ DB_1 = Sequel.connect ...
32
+ DB_2 = Sequel.connect ...
33
33
  ```
34
34
 
35
35
  ### Database schema
36
36
 
37
37
  ```ruby
38
- DB.create_table :users do
38
+ DB_1.create_table :users do
39
39
  primary_key :id
40
40
  String :name, null: false, unique: true
41
41
  end
42
42
 
43
- DB.create_table :posts do
43
+ DB_1.create_table :posts do
44
44
  primary_key :id
45
45
  String :title, null: false, unique: true
46
46
  String :body, null: false
47
+ Integer :language_id, null: false, index: true
47
48
  foreign_key :user_id, :users, null: false, index: true
48
49
  end
49
50
 
50
- DB.create_table :comments do
51
+ DB_1.create_table :comments do
51
52
  primary_key :id
52
53
  String :text, null: false
53
54
  foreign_key :user_id, :users, null: false, index: true
54
55
  foreign_key :post_id, :posts, null: false, index: true
55
56
  end
56
57
 
57
- DB.create_table :categories do
58
+ DB_1.create_table :categories do
58
59
  primary_key :id
59
60
  String :name, null: false, unique: true
60
61
  end
61
62
 
62
- DB.create_table :categories_posts do
63
+ DB_1.create_table :categories_posts do
63
64
  foreign_key :category_id, :categories, null: false, index: true
64
65
  foreign_key :post_id, :posts, null: false, index: true
65
66
  primary_key [:category_id, :post_id]
66
67
  end
67
68
 
68
- DB.create_table :people do
69
+ DB_1.create_table :people do
69
70
  String :document_number, null: false, primary_key: true
70
71
  String :first_name, null: false
71
72
  String :last_name, null: false
72
73
  Date :birth_date, null: false
73
74
  foreign_key :user_id, :users, null: false, unique: true
74
75
  end
76
+
77
+ DB_1.create_table :languages_people do
78
+ Integer :language_id, null: false, index: true
79
+ foreign_key :document_number, :people, type: String, null: false, index: true
80
+ primary_key [:language_id, :document_number]
81
+ end
82
+
83
+ DB_2.create_table :languages do
84
+ primary_key :id
85
+ String :name, null: false, unique: true
86
+ end
75
87
  ```
76
88
 
77
89
  ### Models
@@ -81,7 +93,8 @@ User = Rasti::DB::Model[:id, :name, :posts, :comments, :person]
81
93
  Post = Rasti::DB::Model[:id, :title, :body, :user_id, :user, :comments, :categories]
82
94
  Comment = Rasti::DB::Model[:id, :text, :user_id, :user, :post_id, :post]
83
95
  Category = Rasti::DB::Model[:id, :name, :posts]
84
- Person = Rasti::DB::Model[:document_number, :first_name, :last_name, :birth_date, :user_id, :user]
96
+ Person = Rasti::DB::Model[:document_number, :first_name, :last_name, :full_name, :birth_date, :user_id, :user]
97
+ Language = Rasti::DB::Model[:id, :name, :people]
85
98
  ```
86
99
 
87
100
  ### Collections
@@ -98,17 +111,17 @@ class Posts < Rasti::DB::Collection
98
111
  many_to_many :categories
99
112
  one_to_many :comments
100
113
 
101
- query :created_by do |user_id|
114
+ query :created_by do |user_id|
102
115
  where user_id: user_id
103
116
  end
104
-
117
+
105
118
  query :entitled, -> (title) { where title: title }
106
119
 
107
120
  query :commented_by do |user_id|
108
121
  chainable do
109
- dataset.join(with_schema(:comments), post_id: :id)
110
- .where(with_schema(:comments, :user_id) => user_id)
111
- .select_all(with_schema(:posts))
122
+ dataset.join(qualify(:comments), post_id: :id)
123
+ .where(Sequel[:comments][:user_id] => user_id)
124
+ .select_all(:posts)
112
125
  .distinct
113
126
  end
114
127
  end
@@ -130,19 +143,34 @@ class People < Rasti::DB::Collection
130
143
  set_model Person
131
144
 
132
145
  many_to_one :user
146
+ many_to_many :languages
147
+
148
+ computed_attribute :full_name do
149
+ Rasti::DB::ComputedAttribute.new Sequel.join([:first_name, ' ', :last_name])
150
+ end
151
+ end
152
+
153
+ class Languages < Rasti::DB::Collection
154
+ set_data_source_name :other
155
+
156
+ one_to_many :posts
157
+ many_to_many :people, collection: People, relation_data_source_name: :default
133
158
  end
134
159
 
135
- users = Users.new DB
136
- posts = Posts.new DB
137
- comments = Comments.new DB
138
- categories = Categories.new DB
139
- people = People.new DB
160
+ environment = Rasti::DB::Environment.new default: Rasti::DB::DataSource.new(DB_1),
161
+ other: Rasti::DB::DataSource.new(DB_2, 'custom_schema')
162
+
163
+ users = Users.new environment
164
+ posts = Posts.new environment
165
+ comments = Comments.new environment
166
+ categories = Categories.new environment
167
+ people = People.new environment
140
168
  ```
141
169
 
142
170
  ### Persistence
143
171
 
144
172
  ```ruby
145
- DB.transaction do
173
+ DB_1.transaction do
146
174
  id = users.insert name: 'User 1'
147
175
  users.update id, name: 'User updated'
148
176
  users.delete id
@@ -162,17 +190,53 @@ end
162
190
  posts.all # => [Post, ...]
163
191
  posts.first # => Post
164
192
  posts.count # => 1
193
+
165
194
  posts.where(id: [1,2]) # => [Post, ...]
166
195
  posts.where{id > 1}.limit(10).offset(20) } # => [Post, ...]
167
- posts.graph(:user, :categories, 'comments.user') # => [Post(User, [Categories, ...], [Comments(User)]), ...]
168
- posts.created_by(1) # => [Post, ...]
169
- posts.created_by(1).entitled('...').commented_by(2) # => [Post, ...]
170
- posts.with_categories([1,2]) # => [Post, ...]
196
+
171
197
  posts.where(id: [1,2]).raw # => [{id:1, ...}, {id:2, ...}]
172
198
  posts.where(id: [1,2]).primary_keys # => [1,2]
173
199
  posts.where(id: [1,2]).pluck(:id) # => [1,2]
174
200
  posts.where(id: [1,2]).pluck(:id, :title) # => [[1, ...], [2, ...]]
201
+
202
+ posts.created_by(1) # => [Post, ...]
203
+ posts.created_by(1).entitled('...').commented_by(2) # => [Post, ...]
204
+ posts.with_categories([1,2]) # => [Post, ...]
205
+
206
+ posts.graph(:user, :language, :categories, 'comments.user') # => [Post(User, Language, [Categories, ...], [Comments(User)]), ...]
207
+
175
208
  posts.join(:user).where(name: 'User 4') # => [Post, ...]
209
+
210
+ posts.select_attributes(:id, :title) # => [Post, ...]
211
+ posts.exclude_attributes(:id, :title) # => [Post, ...]
212
+ posts.all_attributes # => [Post, ...]
213
+
214
+ posts.graph('user.person').select_graph_attributes(user: [:id], 'user.person': [:last_name, :user_id]) # => [Post, ...]
215
+ posts.graph('user.person').exclude_graph_attributes(user: [:name], 'user.person': [:first_name, :last_name]) # => [Post, ...]
216
+ posts.graph('user.person').all_graph_attributes('user.person') # => [Post, ...]
217
+
218
+ posts.each { |post| do_something post } # Iterate posts loading all at first
219
+ posts.each(batch_size: 1000) { |post| do_something post } # Iterate posts loading in batches
220
+ posts.each_batch(size: 1000) { |posts| do_something posts } # Iterate batches of posts
221
+ ```
222
+ ### Natural Query Language
223
+
224
+ ```ruby
225
+ posts.nql('id = 1') # => Equal
226
+ posts.nql('id != 1') # => Not equal
227
+ posts.nql('title: My post') # => Include
228
+ posts.nql('title !: My post') # => Not include
229
+ posts.nql('title ~ My post') # => Insensitive like
230
+ posts.nql('id > 1') # => Greater
231
+ posts.nql('id >= 1') # => Greater or equal
232
+ posts.nql('id < 10') # => Less
233
+ posts.nql('id <= 10') # => Less or equal
234
+
235
+ posts.nql('id = 1 | id = 2') # => Or
236
+ posts.nql('id > 1 & title: "My post"') # => And
237
+ posts.nql('(id > 3 & id < 10) | title: "My post"') # => Precedence
238
+
239
+ posts.nql('comments.user.person.document_number = 7') # => Nested
176
240
  ```
177
241
 
178
242
  ## Development
@@ -3,7 +3,9 @@ require 'consty'
3
3
  require 'time'
4
4
  require 'timing'
5
5
  require 'treetop'
6
+ require 'hierarchical_graph'
6
7
  require 'class_config'
8
+ require 'hash_ext'
7
9
  require 'multi_require'
8
10
 
9
11
  module Rasti
@@ -12,7 +14,6 @@ module Rasti
12
14
  extend MultiRequire
13
15
  extend ClassConfig
14
16
 
15
- require_relative 'db/helpers'
16
17
  require_relative 'db/query'
17
18
  require_relative_pattern 'db/relations/*'
18
19
  require_relative_pattern 'db/type_converters/postgres_types/*'
@@ -2,10 +2,7 @@ module Rasti
2
2
  module DB
3
3
  class Collection
4
4
 
5
- QUERY_METHODS = (Query::DATASET_CHAINED_METHODS + [:graph, :join, :count, :all, :each, :first, :pluck, :primary_keys, :any?, :empty?, :raw, :nql]).freeze
6
-
7
- include Enumerable
8
- include Helpers::WithSchema
5
+ QUERY_METHODS = Query.public_instance_methods - Object.public_instance_methods
9
6
 
10
7
  class << self
11
8
 
@@ -16,8 +13,8 @@ module Rasti
16
13
  @collection_name ||= underscore(demodulize(name)).to_sym
17
14
  end
18
15
 
19
- def collection_fields
20
- @collection_fields ||= model.attributes - relations.keys
16
+ def collection_attributes
17
+ @collection_attributes ||= model.attributes - relations.keys - computed_attributes.keys
21
18
  end
22
19
 
23
20
  def primary_key
@@ -38,12 +35,20 @@ module Rasti
38
35
  end
39
36
  end
40
37
 
38
+ def data_source_name
39
+ @data_source_name ||= superclass.respond_to?(:data_source_name) ? superclass.data_source_name : :default
40
+ end
41
+
41
42
  def relations
42
- @relations ||= {}
43
+ @relations ||= Hash::Indifferent.new
43
44
  end
44
45
 
45
46
  def queries
46
- @queries ||= {}
47
+ @queries ||= Hash::Indifferent.new
48
+ end
49
+
50
+ def computed_attributes
51
+ @computed_attributes ||= Hash::Indifferent.new
47
52
  end
48
53
 
49
54
  private
@@ -64,11 +69,17 @@ module Rasti
64
69
  @model = model
65
70
  end
66
71
 
72
+ def set_data_source_name(name)
73
+ @data_source_name = name.to_sym
74
+ end
75
+
67
76
  [Relations::OneToMany, Relations::ManyToOne, Relations::ManyToMany, Relations::OneToOne].each do |relation_class|
68
77
  define_method underscore(demodulize(relation_class.name)) do |name, options={}|
69
78
  relations[name] = relation_class.new name, self, options
70
79
 
71
- query "with_#{pluralize(name)}".to_sym do |primary_keys|
80
+ query_name = relations[name].to_many? ? name : pluralize(name)
81
+
82
+ query "with_#{query_name}" do |primary_keys|
72
83
  with_related name, primary_keys
73
84
  end
74
85
  end
@@ -80,25 +91,29 @@ module Rasti
80
91
  queries[name] = lambda || block
81
92
 
82
93
  define_method name do |*args|
83
- query.instance_exec(*args, &self.class.queries[name])
94
+ default_query.instance_exec(*args, &self.class.queries.fetch(name))
84
95
  end
85
96
  end
86
97
 
87
- end
98
+ def computed_attribute(name, &block)
99
+ raise "Computed Attribute #{name} already exists" if computed_attributes.key? name
100
+ computed_attributes[name] = block.call
101
+ end
88
102
 
89
- attr_reader :db, :schema
103
+ end
90
104
 
91
- def initialize(db, schema=nil)
92
- @db = db
93
- @schema = schema ? schema.to_sym : nil
105
+ def initialize(environment)
106
+ @environment = environment
94
107
  end
95
108
 
96
- def dataset
97
- db[qualified_collection_name]
109
+ QUERY_METHODS.each do |method|
110
+ define_method method do |*args, &block|
111
+ default_query.public_send method, *args, &block
112
+ end
98
113
  end
99
114
 
100
115
  def insert(attributes)
101
- db.transaction do
116
+ data_source.db.transaction do
102
117
  db_attributes = transform_attributes_to_db attributes
103
118
  collection_attributes, relations_primary_keys = split_related_attributes db_attributes
104
119
  primary_key = dataset.insert collection_attributes
@@ -121,7 +136,7 @@ module Rasti
121
136
  end
122
137
 
123
138
  def update(primary_key, attributes)
124
- db.transaction do
139
+ data_source.db.transaction do
125
140
  db_attributes = transform_attributes_to_db attributes
126
141
  collection_attributes, relations_primary_keys = split_related_attributes db_attributes
127
142
  dataset.where(self.class.primary_key => primary_key).update(collection_attributes) unless collection_attributes.empty?
@@ -147,7 +162,7 @@ module Rasti
147
162
  end
148
163
 
149
164
  def delete_relations(primary_key, relations)
150
- db.transaction do
165
+ data_source.db.transaction do
151
166
  relations.each do |relation_name, relation_primary_keys|
152
167
  relation = self.class.relations[relation_name]
153
168
  delete_relation_table relation, primary_key, relation_primary_keys
@@ -157,7 +172,7 @@ module Rasti
157
172
  end
158
173
 
159
174
  def delete_cascade(*primary_keys)
160
- db.transaction do
175
+ data_source.db.transaction do
161
176
  delete_cascade_relations primary_keys
162
177
  bulk_delete { |q| q.where self.class.primary_key => primary_keys }
163
178
  end
@@ -172,12 +187,6 @@ module Rasti
172
187
  where(self.class.primary_key => primary_key).graph(*relations).first
173
188
  end
174
189
 
175
- QUERY_METHODS.each do |method|
176
- define_method method do |*args, &block|
177
- query.public_send method, *args, &block
178
- end
179
- end
180
-
181
190
  def exists?(filter=nil, &block)
182
191
  build_query(filter, &block).any?
183
192
  end
@@ -188,27 +197,45 @@ module Rasti
188
197
 
189
198
  private
190
199
 
191
- def transform_attributes_to_db(attributes)
192
- attributes.each_with_object({}) do |(attribute_name, value), result|
193
- transformed_value = Rasti::DB.to_db db, qualified_collection_name, attribute_name, value
194
- result[attribute_name] = transformed_value
195
- end
200
+ attr_reader :environment
201
+
202
+ def data_source
203
+ @data_source ||= environment.data_source_of self.class
204
+ end
205
+
206
+ def dataset
207
+ data_source.db[qualified_collection_name]
196
208
  end
197
209
 
198
210
  def qualified_collection_name
199
- schema.nil? ? Sequel[self.class.collection_name] : Sequel[schema][self.class.collection_name]
211
+ data_source.qualify self.class.collection_name
200
212
  end
201
213
 
202
- def query
203
- Query.new self.class, dataset, [], schema
214
+ def qualify(collection_name, data_source_name: nil)
215
+ data_source_name ||= self.class.data_source_name
216
+ environment.qualify data_source_name, collection_name
217
+ end
218
+
219
+ def default_query
220
+ Query.new collection_class: self.class,
221
+ dataset: dataset.select_all(self.class.collection_name),
222
+ environment: environment
204
223
  end
205
224
 
206
225
  def build_query(filter=nil, &block)
207
226
  raise ArgumentError, 'must specify filter hash or block' if filter.nil? && block.nil?
227
+
208
228
  if filter
209
- query.where filter
229
+ default_query.where(filter)
210
230
  else
211
- block.arity == 0 ? query.instance_eval(&block) : block.call(query)
231
+ block.arity == 0 ? default_query.instance_eval(&block) : block.call(default_query)
232
+ end
233
+ end
234
+
235
+ def transform_attributes_to_db(attributes)
236
+ attributes.each_with_object({}) do |(attribute_name, value), result|
237
+ transformed_value = Rasti::DB.to_db data_source.db, qualified_collection_name, attribute_name, value
238
+ result[attribute_name] = transformed_value
212
239
  end
213
240
  end
214
241
 
@@ -237,18 +264,22 @@ module Rasti
237
264
  end
238
265
 
239
266
  relations.select { |r| r.one_to_many? || r.one_to_one? }.each do |relation|
240
- relation_collection_name = with_schema(relation.target_collection_class.collection_name)
241
- relations_ids = db[relation_collection_name].where(relation.foreign_key => primary_keys)
242
- .select(relation.target_collection_class.primary_key)
243
- .map(relation.target_collection_class.primary_key)
267
+ relation_data_source = environment.data_source_of relation.target_collection_class
268
+ relation_collection_name = relation_data_source.qualify relation.target_collection_class.collection_name
244
269
 
245
- target_collection = relation.target_collection_class.new db, schema
270
+ relations_ids = relation_data_source.db[relation_collection_name]
271
+ .where(relation.foreign_key => primary_keys)
272
+ .select(relation.target_collection_class.primary_key)
273
+ .map(relation.target_collection_class.primary_key)
274
+
275
+ target_collection = relation.target_collection_class.new environment
246
276
  target_collection.delete_cascade(*relations_ids) unless relations_ids.empty?
247
277
  end
248
278
  end
249
279
 
250
280
  def insert_relation_table(relation, primary_key, relation_primary_keys)
251
- relation_collection_name = relation.qualified_relation_collection_name(schema)
281
+ relation_data_source = environment.data_source relation.relation_data_source_name
282
+ relation_collection_name = relation_data_source.qualify relation.relation_collection_name
252
283
 
253
284
  values = relation_primary_keys.map do |relation_pk|
254
285
  {
@@ -257,12 +288,14 @@ module Rasti
257
288
  }
258
289
  end
259
290
 
260
- db[relation_collection_name].multi_insert values
291
+ relation_data_source.db[relation_collection_name].multi_insert values
261
292
  end
262
293
 
263
294
  def delete_relation_table(relation, primary_keys, relation_primary_keys=nil)
264
- relation_collection_name = relation.qualified_relation_collection_name(schema)
265
- ds = db[relation_collection_name].where(relation.source_foreign_key => primary_keys)
295
+ relation_data_source = environment.data_source relation.relation_data_source_name
296
+ relation_collection_name = relation_data_source.qualify relation.relation_collection_name
297
+
298
+ ds = relation_data_source.db[relation_collection_name].where(relation.source_foreign_key => primary_keys)
266
299
  ds = ds.where(relation.target_foreign_key => relation_primary_keys) if relation_primary_keys
267
300
  ds.delete
268
301
  end