rasti-db 1.5.0 → 2.3.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 +52 -19
- data/lib/rasti/db.rb +11 -2
- data/lib/rasti/db/collection.rb +67 -36
- data/lib/rasti/db/computed_attribute.rb +22 -0
- data/lib/rasti/db/data_source.rb +18 -0
- data/lib/rasti/db/environment.rb +32 -0
- data/lib/rasti/db/nql/filter_condition_strategies/base.rb +17 -0
- data/lib/rasti/db/nql/filter_condition_strategies/postgres.rb +21 -0
- data/lib/rasti/db/nql/filter_condition_strategies/sqlite.rb +21 -0
- data/lib/rasti/db/nql/filter_condition_strategies/types/generic.rb +49 -0
- data/lib/rasti/db/nql/filter_condition_strategies/types/pg_array.rb +32 -0
- data/lib/rasti/db/nql/filter_condition_strategies/types/sqlite_array.rb +34 -0
- data/lib/rasti/db/nql/filter_condition_strategies/unsupported_type_comparison.rb +22 -0
- data/lib/rasti/db/nql/nodes/array_content.rb +21 -0
- data/lib/rasti/db/nql/nodes/attribute.rb +37 -0
- data/lib/rasti/db/nql/nodes/binary_node.rb +4 -0
- data/lib/rasti/db/nql/nodes/comparisons/base.rb +15 -1
- data/lib/rasti/db/nql/nodes/comparisons/equal.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/greater_than.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/greater_than_or_equal.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/include.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/less_than.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/less_than_or_equal.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/like.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/not_equal.rb +0 -4
- data/lib/rasti/db/nql/nodes/comparisons/not_include.rb +0 -4
- data/lib/rasti/db/nql/nodes/conjunction.rb +2 -2
- data/lib/rasti/db/nql/nodes/constants/array.rb +17 -0
- data/lib/rasti/db/nql/nodes/constants/base.rb +17 -0
- data/lib/rasti/db/nql/nodes/constants/false.rb +1 -1
- data/lib/rasti/db/nql/nodes/constants/float.rb +1 -1
- data/lib/rasti/db/nql/nodes/constants/integer.rb +1 -1
- data/lib/rasti/db/nql/nodes/constants/literal_string.rb +1 -1
- data/lib/rasti/db/nql/nodes/constants/string.rb +1 -1
- data/lib/rasti/db/nql/nodes/constants/time.rb +1 -1
- data/lib/rasti/db/nql/nodes/constants/true.rb +1 -1
- data/lib/rasti/db/nql/nodes/disjunction.rb +2 -2
- data/lib/rasti/db/nql/nodes/parenthesis_sentence.rb +6 -2
- data/lib/rasti/db/nql/nodes/sentence.rb +6 -2
- data/lib/rasti/db/nql/syntax.rb +262 -44
- data/lib/rasti/db/nql/syntax.treetop +27 -14
- data/lib/rasti/db/query.rb +55 -23
- data/lib/rasti/db/relations/base.rb +22 -8
- data/lib/rasti/db/relations/graph.rb +10 -16
- data/lib/rasti/db/relations/many_to_many.rb +57 -23
- data/lib/rasti/db/relations/many_to_one.rb +9 -7
- data/lib/rasti/db/relations/one_to_many.rb +21 -13
- data/lib/rasti/db/type_converters/sqlite.rb +62 -0
- data/lib/rasti/db/type_converters/sqlite_types/array.rb +34 -0
- data/lib/rasti/db/version.rb +1 -1
- data/rasti-db.gemspec +1 -0
- data/spec/collection_spec.rb +210 -50
- data/spec/computed_attribute_spec.rb +32 -0
- data/spec/minitest_helper.rb +77 -15
- data/spec/model_spec.rb +4 -2
- data/spec/nql/computed_attributes_spec.rb +29 -0
- data/spec/nql/filter_condition_spec.rb +23 -4
- data/spec/nql/filter_condition_strategies_spec.rb +112 -0
- data/spec/nql/syntax_parser_spec.rb +36 -5
- data/spec/query_spec.rb +340 -54
- data/spec/relations_spec.rb +27 -7
- data/spec/type_converters/sqlite_spec.rb +66 -0
- metadata +40 -4
- data/lib/rasti/db/helpers.rb +0 -16
- data/lib/rasti/db/nql/nodes/field.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 057df50ee7debeb86b2ad63d4dffc965df8941e0f19ac4d4f96fe97ca319c314
|
4
|
+
data.tar.gz: c0cda671e2ea8f748b59c34108440edc7e016702f4d5832efac995a650005e62
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d31034d885d8791bb04a2417372d56226c51b4fe8c54279d294148b22c68a7744f12887a948692f12e0b24c1a4abf8868b3c9250948ffb516e2c2515b42ea0aa
|
7
|
+
data.tar.gz: b75bc69a65eb10032f510ff5cb99cd511b69bc354c6bc3bc836e23612a0a21f9cc0a01849b752d58b1e86c0b9387adcb665ad609198495120a1da0c6fa2418a7
|
data/README.md
CHANGED
@@ -28,49 +28,62 @@ Or install it yourself as:
|
|
28
28
|
### Database connection
|
29
29
|
|
30
30
|
```ruby
|
31
|
-
|
31
|
+
DB_1 = Sequel.connect ...
|
32
|
+
DB_2 = Sequel.connect ...
|
32
33
|
```
|
33
34
|
|
34
35
|
### Database schema
|
35
36
|
|
36
37
|
```ruby
|
37
|
-
|
38
|
+
DB_1.create_table :users do
|
38
39
|
primary_key :id
|
39
40
|
String :name, null: false, unique: true
|
40
41
|
end
|
41
42
|
|
42
|
-
|
43
|
+
DB_1.create_table :posts do
|
43
44
|
primary_key :id
|
44
45
|
String :title, null: false, unique: true
|
45
46
|
String :body, null: false
|
47
|
+
Integer :language_id, null: false, index: true
|
46
48
|
foreign_key :user_id, :users, null: false, index: true
|
47
49
|
end
|
48
50
|
|
49
|
-
|
51
|
+
DB_1.create_table :comments do
|
50
52
|
primary_key :id
|
51
53
|
String :text, null: false
|
52
54
|
foreign_key :user_id, :users, null: false, index: true
|
53
55
|
foreign_key :post_id, :posts, null: false, index: true
|
54
56
|
end
|
55
57
|
|
56
|
-
|
58
|
+
DB_1.create_table :categories do
|
57
59
|
primary_key :id
|
58
60
|
String :name, null: false, unique: true
|
59
61
|
end
|
60
62
|
|
61
|
-
|
63
|
+
DB_1.create_table :categories_posts do
|
62
64
|
foreign_key :category_id, :categories, null: false, index: true
|
63
65
|
foreign_key :post_id, :posts, null: false, index: true
|
64
66
|
primary_key [:category_id, :post_id]
|
65
67
|
end
|
66
68
|
|
67
|
-
|
69
|
+
DB_1.create_table :people do
|
68
70
|
String :document_number, null: false, primary_key: true
|
69
71
|
String :first_name, null: false
|
70
72
|
String :last_name, null: false
|
71
73
|
Date :birth_date, null: false
|
72
74
|
foreign_key :user_id, :users, null: false, unique: true
|
73
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
|
74
87
|
```
|
75
88
|
|
76
89
|
### Models
|
@@ -80,7 +93,8 @@ User = Rasti::DB::Model[:id, :name, :posts, :comments, :person]
|
|
80
93
|
Post = Rasti::DB::Model[:id, :title, :body, :user_id, :user, :comments, :categories]
|
81
94
|
Comment = Rasti::DB::Model[:id, :text, :user_id, :user, :post_id, :post]
|
82
95
|
Category = Rasti::DB::Model[:id, :name, :posts]
|
83
|
-
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]
|
84
98
|
```
|
85
99
|
|
86
100
|
### Collections
|
@@ -97,16 +111,16 @@ class Posts < Rasti::DB::Collection
|
|
97
111
|
many_to_many :categories
|
98
112
|
one_to_many :comments
|
99
113
|
|
100
|
-
query :created_by do |user_id|
|
114
|
+
query :created_by do |user_id|
|
101
115
|
where user_id: user_id
|
102
116
|
end
|
103
|
-
|
117
|
+
|
104
118
|
query :entitled, -> (title) { where title: title }
|
105
119
|
|
106
120
|
query :commented_by do |user_id|
|
107
121
|
chainable do
|
108
|
-
dataset.join(
|
109
|
-
.where(
|
122
|
+
dataset.join(qualify(:comments), post_id: :id)
|
123
|
+
.where(Sequel[:comments][:user_id] => user_id)
|
110
124
|
.select_all(:posts)
|
111
125
|
.distinct
|
112
126
|
end
|
@@ -129,19 +143,34 @@ class People < Rasti::DB::Collection
|
|
129
143
|
set_model Person
|
130
144
|
|
131
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
|
132
151
|
end
|
133
152
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
people
|
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
|
158
|
+
end
|
159
|
+
|
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
|
139
168
|
```
|
140
169
|
|
141
170
|
### Persistence
|
142
171
|
|
143
172
|
```ruby
|
144
|
-
|
173
|
+
DB_1.transaction do
|
145
174
|
id = users.insert name: 'User 1'
|
146
175
|
users.update id, name: 'User updated'
|
147
176
|
users.delete id
|
@@ -174,7 +203,7 @@ posts.created_by(1) # => [Post, ...]
|
|
174
203
|
posts.created_by(1).entitled('...').commented_by(2) # => [Post, ...]
|
175
204
|
posts.with_categories([1,2]) # => [Post, ...]
|
176
205
|
|
177
|
-
posts.graph(:user, :categories, 'comments.user') # => [Post(User, [Categories, ...], [Comments(User)]), ...]
|
206
|
+
posts.graph(:user, :language, :categories, 'comments.user') # => [Post(User, Language, [Categories, ...], [Comments(User)]), ...]
|
178
207
|
|
179
208
|
posts.join(:user).where(name: 'User 4') # => [Post, ...]
|
180
209
|
|
@@ -185,6 +214,10 @@ posts.all_attributes # => [Post, ...]
|
|
185
214
|
posts.graph('user.person').select_graph_attributes(user: [:id], 'user.person': [:last_name, :user_id]) # => [Post, ...]
|
186
215
|
posts.graph('user.person').exclude_graph_attributes(user: [:name], 'user.person': [:first_name, :last_name]) # => [Post, ...]
|
187
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
|
188
221
|
```
|
189
222
|
### Natural Query Language
|
190
223
|
|
data/lib/rasti/db.rb
CHANGED
@@ -6,21 +6,25 @@ require 'treetop'
|
|
6
6
|
require 'hierarchical_graph'
|
7
7
|
require 'class_config'
|
8
8
|
require 'hash_ext'
|
9
|
+
require 'inflecto'
|
9
10
|
require 'multi_require'
|
10
11
|
|
11
12
|
module Rasti
|
12
13
|
module DB
|
13
|
-
|
14
|
+
|
14
15
|
extend MultiRequire
|
15
16
|
extend ClassConfig
|
16
17
|
|
17
|
-
require_relative 'db/helpers'
|
18
18
|
require_relative 'db/query'
|
19
19
|
require_relative_pattern 'db/relations/*'
|
20
20
|
require_relative_pattern 'db/type_converters/postgres_types/*'
|
21
|
+
require_relative_pattern 'db/type_converters/sqlite_types/*'
|
22
|
+
require_relative 'db/nql/nodes/constants/base'
|
23
|
+
require_relative_pattern 'db/nql/filter_condition_strategies/types/*'
|
21
24
|
require_relative_pattern 'db/**/*'
|
22
25
|
|
23
26
|
attr_config :type_converters, []
|
27
|
+
attr_config :nql_filter_condition_strategy, nil
|
24
28
|
|
25
29
|
def self.to_db(db, collection_name, attribute_name, value)
|
26
30
|
type_converters.inject(value) do |result, type_converter|
|
@@ -34,5 +38,10 @@ module Rasti
|
|
34
38
|
end
|
35
39
|
end
|
36
40
|
|
41
|
+
def self.nql_filter_condition_for(comparison_name, identifier, argument)
|
42
|
+
raise 'Undefined Rasti::DB.nql_filter_condition_strategy' unless nql_filter_condition_strategy
|
43
|
+
nql_filter_condition_strategy.filter_condition_for comparison_name, identifier, argument
|
44
|
+
end
|
45
|
+
|
37
46
|
end
|
38
47
|
end
|
data/lib/rasti/db/collection.rb
CHANGED
@@ -4,8 +4,6 @@ module Rasti
|
|
4
4
|
|
5
5
|
QUERY_METHODS = Query.public_instance_methods - Object.public_instance_methods
|
6
6
|
|
7
|
-
include Helpers::WithSchema
|
8
|
-
|
9
7
|
class << self
|
10
8
|
|
11
9
|
extend Sequel::Inflections
|
@@ -16,7 +14,7 @@ module Rasti
|
|
16
14
|
end
|
17
15
|
|
18
16
|
def collection_attributes
|
19
|
-
@collection_attributes ||= model.attributes - relations.keys
|
17
|
+
@collection_attributes ||= model.attributes - relations.keys - computed_attributes.keys
|
20
18
|
end
|
21
19
|
|
22
20
|
def primary_key
|
@@ -37,12 +35,20 @@ module Rasti
|
|
37
35
|
end
|
38
36
|
end
|
39
37
|
|
38
|
+
def data_source_name
|
39
|
+
@data_source_name ||= superclass.respond_to?(:data_source_name) ? superclass.data_source_name : :default
|
40
|
+
end
|
41
|
+
|
40
42
|
def relations
|
41
|
-
@relations ||=
|
43
|
+
@relations ||= Hash::Indifferent.new
|
42
44
|
end
|
43
45
|
|
44
46
|
def queries
|
45
|
-
@queries ||=
|
47
|
+
@queries ||= Hash::Indifferent.new
|
48
|
+
end
|
49
|
+
|
50
|
+
def computed_attributes
|
51
|
+
@computed_attributes ||= Hash::Indifferent.new
|
46
52
|
end
|
47
53
|
|
48
54
|
private
|
@@ -63,11 +69,17 @@ module Rasti
|
|
63
69
|
@model = model
|
64
70
|
end
|
65
71
|
|
72
|
+
def set_data_source_name(name)
|
73
|
+
@data_source_name = name.to_sym
|
74
|
+
end
|
75
|
+
|
66
76
|
[Relations::OneToMany, Relations::ManyToOne, Relations::ManyToMany, Relations::OneToOne].each do |relation_class|
|
67
77
|
define_method underscore(demodulize(relation_class.name)) do |name, options={}|
|
68
78
|
relations[name] = relation_class.new name, self, options
|
69
79
|
|
70
|
-
|
80
|
+
query_name = relations[name].to_many? ? name : pluralize(name)
|
81
|
+
|
82
|
+
query "with_#{query_name}" do |primary_keys|
|
71
83
|
with_related name, primary_keys
|
72
84
|
end
|
73
85
|
end
|
@@ -83,13 +95,15 @@ module Rasti
|
|
83
95
|
end
|
84
96
|
end
|
85
97
|
|
86
|
-
|
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
|
87
102
|
|
88
|
-
|
103
|
+
end
|
89
104
|
|
90
|
-
def initialize(
|
91
|
-
@
|
92
|
-
@schema = schema ? schema.to_sym : nil
|
105
|
+
def initialize(environment)
|
106
|
+
@environment = environment
|
93
107
|
end
|
94
108
|
|
95
109
|
QUERY_METHODS.each do |method|
|
@@ -98,12 +112,8 @@ module Rasti
|
|
98
112
|
end
|
99
113
|
end
|
100
114
|
|
101
|
-
def dataset
|
102
|
-
db[qualified_collection_name]
|
103
|
-
end
|
104
|
-
|
105
115
|
def insert(attributes)
|
106
|
-
db.transaction do
|
116
|
+
data_source.db.transaction do
|
107
117
|
db_attributes = transform_attributes_to_db attributes
|
108
118
|
collection_attributes, relations_primary_keys = split_related_attributes db_attributes
|
109
119
|
primary_key = dataset.insert collection_attributes
|
@@ -126,7 +136,7 @@ module Rasti
|
|
126
136
|
end
|
127
137
|
|
128
138
|
def update(primary_key, attributes)
|
129
|
-
db.transaction do
|
139
|
+
data_source.db.transaction do
|
130
140
|
db_attributes = transform_attributes_to_db attributes
|
131
141
|
collection_attributes, relations_primary_keys = split_related_attributes db_attributes
|
132
142
|
dataset.where(self.class.primary_key => primary_key).update(collection_attributes) unless collection_attributes.empty?
|
@@ -152,7 +162,7 @@ module Rasti
|
|
152
162
|
end
|
153
163
|
|
154
164
|
def delete_relations(primary_key, relations)
|
155
|
-
db.transaction do
|
165
|
+
data_source.db.transaction do
|
156
166
|
relations.each do |relation_name, relation_primary_keys|
|
157
167
|
relation = self.class.relations[relation_name]
|
158
168
|
delete_relation_table relation, primary_key, relation_primary_keys
|
@@ -162,7 +172,7 @@ module Rasti
|
|
162
172
|
end
|
163
173
|
|
164
174
|
def delete_cascade(*primary_keys)
|
165
|
-
db.transaction do
|
175
|
+
data_source.db.transaction do
|
166
176
|
delete_cascade_relations primary_keys
|
167
177
|
bulk_delete { |q| q.where self.class.primary_key => primary_keys }
|
168
178
|
end
|
@@ -187,33 +197,48 @@ module Rasti
|
|
187
197
|
|
188
198
|
private
|
189
199
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
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]
|
195
208
|
end
|
196
209
|
|
197
210
|
def qualified_collection_name
|
198
|
-
|
211
|
+
data_source.qualify self.class.collection_name
|
199
212
|
end
|
200
213
|
|
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
|
+
|
201
219
|
def default_query
|
202
220
|
Query.new collection_class: self.class,
|
203
221
|
dataset: dataset.select_all(self.class.collection_name),
|
204
|
-
|
222
|
+
environment: environment
|
205
223
|
end
|
206
224
|
|
207
225
|
def build_query(filter=nil, &block)
|
208
226
|
raise ArgumentError, 'must specify filter hash or block' if filter.nil? && block.nil?
|
209
227
|
|
210
228
|
if filter
|
211
|
-
default_query.where
|
229
|
+
default_query.where(filter)
|
212
230
|
else
|
213
231
|
block.arity == 0 ? default_query.instance_eval(&block) : block.call(default_query)
|
214
232
|
end
|
215
233
|
end
|
216
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
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
217
242
|
def split_related_attributes(attributes)
|
218
243
|
relation_names = self.class.relations.values.select(&:many_to_many?).map(&:name)
|
219
244
|
|
@@ -239,18 +264,22 @@ module Rasti
|
|
239
264
|
end
|
240
265
|
|
241
266
|
relations.select { |r| r.one_to_many? || r.one_to_one? }.each do |relation|
|
242
|
-
|
243
|
-
|
244
|
-
.select(relation.target_collection_class.primary_key)
|
245
|
-
.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
|
246
269
|
|
247
|
-
|
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
|
248
276
|
target_collection.delete_cascade(*relations_ids) unless relations_ids.empty?
|
249
277
|
end
|
250
278
|
end
|
251
279
|
|
252
280
|
def insert_relation_table(relation, primary_key, relation_primary_keys)
|
253
|
-
|
281
|
+
relation_data_source = environment.data_source relation.relation_data_source_name
|
282
|
+
relation_collection_name = relation_data_source.qualify relation.relation_collection_name
|
254
283
|
|
255
284
|
values = relation_primary_keys.map do |relation_pk|
|
256
285
|
{
|
@@ -259,12 +288,14 @@ module Rasti
|
|
259
288
|
}
|
260
289
|
end
|
261
290
|
|
262
|
-
db[relation_collection_name].multi_insert values
|
291
|
+
relation_data_source.db[relation_collection_name].multi_insert values
|
263
292
|
end
|
264
293
|
|
265
294
|
def delete_relation_table(relation, primary_keys, relation_primary_keys=nil)
|
266
|
-
|
267
|
-
|
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)
|
268
299
|
ds = ds.where(relation.target_foreign_key => relation_primary_keys) if relation_primary_keys
|
269
300
|
ds.delete
|
270
301
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Rasti
|
2
|
+
module DB
|
3
|
+
class ComputedAttribute
|
4
|
+
|
5
|
+
attr_reader :identifier
|
6
|
+
|
7
|
+
def initialize(identifier, &join)
|
8
|
+
@identifier = identifier
|
9
|
+
@join = join
|
10
|
+
end
|
11
|
+
|
12
|
+
def apply_join(dataset)
|
13
|
+
join ? join.call(dataset) : dataset
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :join
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|