rasti-db 1.4.0 → 2.2.0

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