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
@@ -7,10 +7,10 @@ module Rasti
|
|
7
7
|
@foreign_key ||= options[:foreign_key] || target_collection_class.foreign_key
|
8
8
|
end
|
9
9
|
|
10
|
-
def fetch_graph(
|
10
|
+
def fetch_graph(environment, rows, selected_attributes=nil, excluded_attributes=nil, relations_graph=nil)
|
11
11
|
fks = rows.map { |row| row[foreign_key] }.uniq
|
12
12
|
|
13
|
-
target_collection = target_collection_class.new
|
13
|
+
target_collection = target_collection_class.new environment
|
14
14
|
|
15
15
|
query = target_collection.where(source_collection_class.primary_key => fks)
|
16
16
|
query = query.exclude_attributes(*excluded_attributes) if excluded_attributes
|
@@ -26,19 +26,21 @@ module Rasti
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
def add_join(
|
29
|
+
def add_join(environment, dataset, prefix=nil)
|
30
|
+
validate_join!
|
31
|
+
|
30
32
|
relation_alias = join_relation_name prefix
|
31
33
|
|
32
|
-
|
34
|
+
relation_name = prefix ? Sequel[prefix] : Sequel[source_collection_class.collection_name]
|
33
35
|
|
34
36
|
relation_condition = {
|
35
|
-
Sequel[relation_alias][target_collection_class.primary_key] =>
|
37
|
+
Sequel[relation_alias][target_collection_class.primary_key] => relation_name[foreign_key]
|
36
38
|
}
|
37
39
|
|
38
|
-
dataset.join(
|
40
|
+
dataset.join(environment.qualify_collection(target_collection_class).as(relation_alias), relation_condition)
|
39
41
|
end
|
40
42
|
|
41
|
-
def apply_filter(
|
43
|
+
def apply_filter(environment, dataset, primary_keys)
|
42
44
|
dataset.where(foreign_key => primary_keys)
|
43
45
|
end
|
44
46
|
|
@@ -7,10 +7,10 @@ module Rasti
|
|
7
7
|
@foreign_key ||= options[:foreign_key] || source_collection_class.foreign_key
|
8
8
|
end
|
9
9
|
|
10
|
-
def fetch_graph(
|
10
|
+
def fetch_graph(environment, rows, selected_attributes=nil, excluded_attributes=nil, relations_graph=nil)
|
11
11
|
pks = rows.map { |row| row[source_collection_class.primary_key] }.uniq
|
12
12
|
|
13
|
-
target_collection = target_collection_class.new
|
13
|
+
target_collection = target_collection_class.new environment
|
14
14
|
|
15
15
|
query = target_collection.where(foreign_key => pks)
|
16
16
|
query = query.exclude_attributes(*excluded_attributes) if excluded_attributes
|
@@ -24,25 +24,33 @@ module Rasti
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def add_join(
|
27
|
+
def add_join(environment, dataset, prefix=nil)
|
28
|
+
validate_join!
|
29
|
+
|
28
30
|
relation_alias = join_relation_name prefix
|
29
31
|
|
30
|
-
|
32
|
+
relation_name = prefix ? Sequel[prefix] : Sequel[source_collection_class.collection_name]
|
31
33
|
|
32
34
|
relation_condition = {
|
33
|
-
Sequel[relation_alias][foreign_key] =>
|
35
|
+
Sequel[relation_alias][foreign_key] => relation_name[source_collection_class.primary_key]
|
34
36
|
}
|
35
37
|
|
36
|
-
dataset.join(
|
38
|
+
dataset.join(environment.qualify_collection(target_collection_class).as(relation_alias), relation_condition)
|
37
39
|
end
|
38
40
|
|
39
|
-
def apply_filter(
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
def apply_filter(environment, dataset, primary_keys)
|
42
|
+
if source_collection_class.data_source_name == target_collection_class.data_source_name
|
43
|
+
dataset.join(environment.qualify_collection(target_collection_class), foreign_key => source_collection_class.primary_key)
|
44
|
+
.where(Sequel[target_collection_class.collection_name][target_collection_class.primary_key] => primary_keys)
|
45
|
+
.select_all(target_collection_class.collection_name)
|
46
|
+
.distinct
|
47
|
+
else
|
48
|
+
target_collection = target_collection_class.new environment
|
49
|
+
fks = target_collection.where(target_collection_class.primary_key => primary_keys)
|
50
|
+
.pluck(foreign_key)
|
51
|
+
.uniq
|
52
|
+
dataset.where(source_collection_class.primary_key => fks)
|
53
|
+
end
|
46
54
|
end
|
47
55
|
|
48
56
|
private
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Rasti
|
2
|
+
module DB
|
3
|
+
module TypeConverters
|
4
|
+
class SQLite
|
5
|
+
|
6
|
+
CONVERTERS = [SQLiteTypes::Array]
|
7
|
+
|
8
|
+
@to_db_mapping = {}
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def to_db(db, collection_name, attribute_name, value)
|
13
|
+
to_db_mapping = to_db_mapping_for db, collection_name
|
14
|
+
|
15
|
+
if to_db_mapping.key? attribute_name
|
16
|
+
to_db_mapping[attribute_name][:converter].to_db value
|
17
|
+
else
|
18
|
+
value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def from_db(object)
|
23
|
+
converter = find_converter_from_db object
|
24
|
+
if !converter.nil?
|
25
|
+
converter.from_db object
|
26
|
+
else
|
27
|
+
object
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def to_db_mapping_for(db, collection_name)
|
34
|
+
key = [db.opts[:database], collection_name]
|
35
|
+
|
36
|
+
@to_db_mapping[key] ||= begin
|
37
|
+
columns = Hash[db.schema(collection_name)]
|
38
|
+
|
39
|
+
columns.each_with_object({}) do |(name, schema), hash|
|
40
|
+
CONVERTERS.each do |converter|
|
41
|
+
unless hash.key? name
|
42
|
+
match = converter.column_type_regex.match schema[:db_type]
|
43
|
+
|
44
|
+
hash[name] = { converter: converter } if match
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def find_converter_from_db(object)
|
52
|
+
CONVERTERS.find do |converter|
|
53
|
+
converter.respond_for? object
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Rasti
|
2
|
+
module DB
|
3
|
+
module TypeConverters
|
4
|
+
module SQLiteTypes
|
5
|
+
class Array
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def column_type_regex
|
10
|
+
/^([a-z]+)\[\]$/
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_db(values)
|
14
|
+
JSON.dump(values)
|
15
|
+
end
|
16
|
+
|
17
|
+
def respond_for?(object)
|
18
|
+
parsed = JSON.parse object
|
19
|
+
object == to_db(parsed)
|
20
|
+
rescue
|
21
|
+
false
|
22
|
+
end
|
23
|
+
|
24
|
+
def from_db(object)
|
25
|
+
JSON.parse object
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/rasti/db/version.rb
CHANGED
data/rasti-db.gemspec
CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_runtime_dependency 'multi_require', '~> 1.0'
|
27
27
|
spec.add_runtime_dependency 'hierarchical_graph', '~> 1.0'
|
28
28
|
spec.add_runtime_dependency 'hash_ext', '~> 0.5'
|
29
|
+
spec.add_runtime_dependency 'inflecto', '~> 0.0'
|
29
30
|
|
30
31
|
spec.add_development_dependency 'rake', '~> 12.3'
|
31
32
|
spec.add_development_dependency 'minitest', '~> 5.0', '< 5.11'
|
data/spec/collection_spec.rb
CHANGED
@@ -2,6 +2,14 @@ require 'minitest_helper'
|
|
2
2
|
|
3
3
|
describe 'Collection' do
|
4
4
|
|
5
|
+
before do
|
6
|
+
Rasti::DB.type_converters = [Rasti::DB::TypeConverters::TimeInZone]
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
Rasti::DB.type_converters = [Rasti::DB::TypeConverters::TimeInZone, Rasti::DB::TypeConverters::SQLite]
|
11
|
+
end
|
12
|
+
|
5
13
|
describe 'Specification' do
|
6
14
|
|
7
15
|
it 'Implicit' do
|
@@ -10,6 +18,7 @@ describe 'Collection' do
|
|
10
18
|
Users.model.must_equal User
|
11
19
|
Users.primary_key.must_equal :id
|
12
20
|
Users.foreign_key.must_equal :user_id
|
21
|
+
Users.data_source_name.must_equal :default
|
13
22
|
end
|
14
23
|
|
15
24
|
it 'Explicit' do
|
@@ -18,6 +27,8 @@ describe 'Collection' do
|
|
18
27
|
People.model.must_equal Person
|
19
28
|
People.primary_key.must_equal :document_number
|
20
29
|
People.foreign_key.must_equal :document_number
|
30
|
+
|
31
|
+
Languages.data_source_name.must_equal :custom
|
21
32
|
end
|
22
33
|
|
23
34
|
it 'Lazy model name' do
|
@@ -42,11 +53,11 @@ describe 'Collection' do
|
|
42
53
|
user_id = db[:users].insert name: 'User 1'
|
43
54
|
|
44
55
|
1.upto(2) do |i|
|
45
|
-
db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...'
|
56
|
+
db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...', language_id: 1
|
46
57
|
db[:categories].insert name: "Category #{i}"
|
47
58
|
end
|
48
59
|
|
49
|
-
post_id = posts.insert user_id: user_id, title: 'Post title', body: '...', categories: [1,2]
|
60
|
+
post_id = posts.insert user_id: user_id, title: 'Post title', body: '...', categories: [1,2], language_id: 1
|
50
61
|
category_id = categories.insert name: 'Category', posts: [1,2]
|
51
62
|
|
52
63
|
db[:categories_posts].where(post_id: post_id).map(:category_id).must_equal [1,2]
|
@@ -59,7 +70,7 @@ describe 'Collection' do
|
|
59
70
|
end
|
60
71
|
|
61
72
|
user_id = db[:users].insert name: 'User 1'
|
62
|
-
post_id = db[:posts].insert user_id: user_id, title: 'Post title', body: '...'
|
73
|
+
post_id = db[:posts].insert user_id: user_id, title: 'Post title', body: '...', language_id: 1
|
63
74
|
1.upto(2) { |category_id| db[:categories_posts].insert post_id: post_id, category_id: category_id }
|
64
75
|
|
65
76
|
posts.insert_relations post_id, categories: [3]
|
@@ -91,7 +102,7 @@ describe 'Collection' do
|
|
91
102
|
user_id = db[:users].insert name: 'User 1'
|
92
103
|
|
93
104
|
1.upto(3) do |i|
|
94
|
-
db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...'
|
105
|
+
db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...', language_id: 1
|
95
106
|
db[:categories].insert name: "Category #{i}"
|
96
107
|
end
|
97
108
|
|
@@ -114,7 +125,7 @@ describe 'Collection' do
|
|
114
125
|
|
115
126
|
it 'Bulk update' do
|
116
127
|
user_id = db[:users].insert name: 'User 1'
|
117
|
-
1.upto(3) { |i| db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...' }
|
128
|
+
1.upto(3) { |i| db[:posts].insert user_id: user_id, title: "Post #{i}", body: '...', language_id: 1 }
|
118
129
|
|
119
130
|
posts.bulk_update(body: 'Updated ...') { where id: [1,2] }
|
120
131
|
|
@@ -139,7 +150,7 @@ describe 'Collection' do
|
|
139
150
|
end
|
140
151
|
|
141
152
|
user_id = db[:users].insert name: 'User 1'
|
142
|
-
post_id = db[:posts].insert user_id: user_id, title: 'Post title', body: '...'
|
153
|
+
post_id = db[:posts].insert user_id: user_id, title: 'Post title', body: '...', language_id: 1
|
143
154
|
1.upto(3) { |category_id| db[:categories_posts].insert post_id: post_id, category_id: category_id }
|
144
155
|
|
145
156
|
posts.delete_relations post_id, categories: [3]
|
@@ -170,7 +181,7 @@ describe 'Collection' do
|
|
170
181
|
category_id = db[:categories].insert name: "Category #{i}"
|
171
182
|
|
172
183
|
1.upto(3) do |n|
|
173
|
-
post_id = db[:posts].insert user_id: user_id, title: "Post #{i}.#{n}", body: '...'
|
184
|
+
post_id = db[:posts].insert user_id: user_id, title: "Post #{i}.#{n}", body: '...', language_id: 1
|
174
185
|
db[:categories_posts].insert post_id: post_id, category_id: category_id
|
175
186
|
end
|
176
187
|
end
|
@@ -227,6 +238,65 @@ describe 'Collection' do
|
|
227
238
|
|
228
239
|
end
|
229
240
|
|
241
|
+
describe 'Multiple data sources' do
|
242
|
+
|
243
|
+
before do
|
244
|
+
1.upto(3) do |i|
|
245
|
+
db[:users].insert name: "User #{i}"
|
246
|
+
db[:people].insert document_number: "document_#{i}",
|
247
|
+
first_name: "John #{i}",
|
248
|
+
last_name: "Doe #{i}",
|
249
|
+
birth_date: Time.now - i,
|
250
|
+
user_id: i
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'Insert' do
|
255
|
+
id = languages.insert name: 'Spanish', people: ['document_1', 'document_2']
|
256
|
+
|
257
|
+
custom_db[:languages][id: id][:name].must_equal 'Spanish'
|
258
|
+
db[:languages_people].where(language_id: id).select_map(:document_number).must_equal ['document_1', 'document_2']
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'Update' do
|
262
|
+
id = custom_db[:languages].insert name: 'Spanish'
|
263
|
+
db[:languages_people].insert language_id: id, document_number: 'document_1'
|
264
|
+
|
265
|
+
custom_db[:languages][id: id][:name].must_equal 'Spanish'
|
266
|
+
db[:languages_people].where(language_id: id).select_map(:document_number).must_equal ['document_1']
|
267
|
+
|
268
|
+
languages.update id, name: 'English', people: ['document_2', 'document_3']
|
269
|
+
|
270
|
+
custom_db[:languages][id: id][:name].must_equal 'English'
|
271
|
+
db[:languages_people].where(language_id: id).select_map(:document_number).must_equal ['document_2', 'document_3']
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'Delete' do
|
275
|
+
id = custom_db[:languages].insert name: 'Spanish'
|
276
|
+
db[:languages_people].insert language_id: id, document_number: 'document_1'
|
277
|
+
db[:posts].insert user_id: 1, title: 'Post 1', body: '...', language_id: id
|
278
|
+
|
279
|
+
languages.delete id
|
280
|
+
|
281
|
+
custom_db[:languages].count.must_equal 0
|
282
|
+
db[:languages_people].where(language_id: id).count.must_equal 1
|
283
|
+
db[:posts].where(language_id: id).count.must_equal 1
|
284
|
+
end
|
285
|
+
|
286
|
+
it 'Delete cascade' do
|
287
|
+
id = custom_db[:languages].insert name: 'Spanish'
|
288
|
+
db[:languages_people].insert language_id: id, document_number: 'document_1'
|
289
|
+
db[:posts].insert user_id: 1, title: 'Post 1', body: '...', language_id: id
|
290
|
+
|
291
|
+
languages.delete_cascade id
|
292
|
+
|
293
|
+
custom_db[:languages].count.must_equal 0
|
294
|
+
db[:languages_people].where(language_id: id).count.must_equal 0
|
295
|
+
db[:posts].where(language_id: id).count.must_equal 0
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
|
230
300
|
end
|
231
301
|
|
232
302
|
describe 'Queries' do
|
@@ -239,7 +309,7 @@ describe 'Collection' do
|
|
239
309
|
|
240
310
|
it 'Find graph' do
|
241
311
|
user_id = db[:users].insert name: 'User 1'
|
242
|
-
db[:posts].insert user_id: user_id, title: 'Post 1', body: '...'
|
312
|
+
db[:posts].insert user_id: user_id, title: 'Post 1', body: '...', language_id: 1
|
243
313
|
|
244
314
|
users.find_graph(user_id, :posts).must_equal User.new id: user_id, name: 'User 1', posts: posts.all
|
245
315
|
end
|
@@ -316,42 +386,51 @@ describe 'Collection' do
|
|
316
386
|
|
317
387
|
it 'Chain dataset as query' do
|
318
388
|
1.upto(2) { |i| db[:users].insert name: "User #{i}" }
|
319
|
-
1.upto(3) { |i| db[:posts].insert user_id: 1, title: "Post #{i}", body: '...' }
|
389
|
+
1.upto(3) { |i| db[:posts].insert user_id: 1, title: "Post #{i}", body: '...', language_id: 1 }
|
320
390
|
1.upto(2) { |i| db[:comments].insert post_id: i, user_id: 2, text: 'Comment' }
|
321
391
|
|
322
392
|
models = posts.commented_by(2).all
|
323
|
-
models.must_equal [1,2].map { |i| Post.new(id: i, user_id: 1, title: "Post #{i}", body: '...') }
|
393
|
+
models.must_equal [1,2].map { |i| Post.new(id: i, user_id: 1, title: "Post #{i}", body: '...', language_id: 1) }
|
324
394
|
end
|
325
395
|
|
326
396
|
it 'Custom query' do
|
327
397
|
1.upto(2) { |i| db[:users].insert name: "User #{i}" }
|
328
|
-
1.upto(3) { |i| db[:posts].insert user_id: 1, title: "Post #{i}", body: '...' }
|
398
|
+
1.upto(3) { |i| db[:posts].insert user_id: 1, title: "Post #{i}", body: '...', language_id: 1 }
|
329
399
|
1.upto(2) { |i| db[:comments].insert post_id: i, user_id: 2, text: 'Comment' }
|
330
400
|
|
331
401
|
models = comments.posts_commented_by(2)
|
332
|
-
models.must_equal [1,2].map { |i| Post.new(id: i, user_id: 1, title: "Post #{i}", body: '...') }
|
402
|
+
models.must_equal [1,2].map { |i| Post.new(id: i, user_id: 1, title: "Post #{i}", body: '...', language_id: 1) }
|
333
403
|
end
|
334
404
|
|
335
405
|
describe 'Named queries' do
|
336
406
|
|
337
407
|
before do
|
408
|
+
custom_db[:languages].insert name: 'Spanish'
|
409
|
+
custom_db[:languages].insert name: 'English'
|
410
|
+
|
338
411
|
1.upto(2) do |i|
|
339
412
|
db[:categories].insert name: "Category #{i}"
|
413
|
+
|
340
414
|
db[:users].insert name: "User #{i}"
|
415
|
+
|
341
416
|
db[:people].insert document_number: "document_#{i}",
|
342
417
|
first_name: "John #{i}",
|
343
418
|
last_name: "Doe #{i}",
|
344
419
|
birth_date: Time.now - i,
|
345
420
|
user_id: i
|
421
|
+
|
346
422
|
end
|
347
423
|
|
424
|
+
db[:languages_people].insert language_id: 1, document_number: 'document_1'
|
425
|
+
db[:languages_people].insert language_id: 2, document_number: 'document_2'
|
426
|
+
|
348
427
|
1.upto(3) do |i|
|
349
|
-
db[:posts].insert user_id: 1, title: "Post #{i}", body: '...'
|
428
|
+
db[:posts].insert user_id: 1, title: "Post #{i}", body: '...', language_id: 1
|
350
429
|
db[:categories_posts].insert category_id: 1, post_id: i
|
351
430
|
end
|
352
431
|
|
353
432
|
4.upto(5) do |i|
|
354
|
-
db[:posts].insert user_id: 2, title: "Post #{i}", body: '...'
|
433
|
+
db[:posts].insert user_id: 2, title: "Post #{i}", body: '...', language_id: 2
|
355
434
|
db[:categories_posts].insert category_id: 2, post_id: i
|
356
435
|
end
|
357
436
|
end
|
@@ -374,6 +453,23 @@ describe 'Collection' do
|
|
374
453
|
users.with_people('document_1').primary_keys.must_equal [1]
|
375
454
|
end
|
376
455
|
|
456
|
+
describe 'Multiple data sources' do
|
457
|
+
|
458
|
+
it 'One to many' do
|
459
|
+
languages.with_posts([1,2]).primary_keys.must_equal [1]
|
460
|
+
end
|
461
|
+
|
462
|
+
it 'Many to one' do
|
463
|
+
posts.with_languages([2]).primary_keys.must_equal [4,5]
|
464
|
+
end
|
465
|
+
|
466
|
+
it 'Many to Many' do
|
467
|
+
languages.with_people(['document_1']).primary_keys.must_equal [1]
|
468
|
+
people.with_languages([2]).primary_keys.must_equal ['document_2']
|
469
|
+
end
|
470
|
+
|
471
|
+
end
|
472
|
+
|
377
473
|
end
|
378
474
|
|
379
475
|
it 'Global' do
|
@@ -400,7 +496,7 @@ describe 'Collection' do
|
|
400
496
|
birth_date: Time.now - i,
|
401
497
|
user_id: i
|
402
498
|
db[:categories].insert name: "Category #{i}"
|
403
|
-
db[:posts].insert user_id: i, title: "Post #{i}", body: '...'
|
499
|
+
db[:posts].insert user_id: i, title: "Post #{i}", body: '...', language_id: 1
|
404
500
|
db[:categories_posts].insert post_id: i, category_id: i
|
405
501
|
end
|
406
502
|
|
@@ -448,21 +544,21 @@ describe 'Collection' do
|
|
448
544
|
stubs = Proc.new do |sql|
|
449
545
|
case sql
|
450
546
|
|
451
|
-
when 'SELECT users.* FROM
|
452
|
-
'SELECT users.* FROM
|
547
|
+
when 'SELECT users.* FROM schema_1.users',
|
548
|
+
'SELECT users.* FROM schema_1.users WHERE (users.id IN (2, 1))'
|
453
549
|
[
|
454
550
|
{id: 1},
|
455
551
|
{id: 2}
|
456
552
|
]
|
457
553
|
|
458
|
-
when 'SELECT posts.* FROM
|
459
|
-
'SELECT posts.* FROM
|
554
|
+
when 'SELECT posts.* FROM schema_1.posts',
|
555
|
+
'SELECT posts.* FROM schema_1.posts WHERE (posts.user_id IN (1, 2))'
|
460
556
|
[
|
461
|
-
{id: 3, user_id: 1},
|
462
|
-
{id: 4, user_id: 2}
|
557
|
+
{id: 3, user_id: 1, language_id: 1},
|
558
|
+
{id: 4, user_id: 2, language_id: 2}
|
463
559
|
]
|
464
560
|
|
465
|
-
when 'SELECT comments.* FROM
|
561
|
+
when 'SELECT comments.* FROM schema_1.comments WHERE (comments.post_id IN (3, 4))'
|
466
562
|
[
|
467
563
|
{id: 5, user_id: 2, post_id: 3},
|
468
564
|
{id: 6, user_id: 1, post_id: 3},
|
@@ -470,88 +566,152 @@ describe 'Collection' do
|
|
470
566
|
{id: 8, user_id: 2, post_id: 4}
|
471
567
|
]
|
472
568
|
|
473
|
-
|
474
|
-
|
569
|
+
when 'SELECT languages.* FROM schema_2.languages WHERE (languages.id IN (1, 2))'
|
570
|
+
[
|
571
|
+
{id: 1},
|
572
|
+
{id: 2}
|
573
|
+
]
|
574
|
+
|
475
575
|
end
|
476
576
|
end
|
477
577
|
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
578
|
+
last_id = 0
|
579
|
+
autoid = Proc.new do |sql|
|
580
|
+
case sql
|
581
|
+
when "INSERT INTO schema_1.people (document_number, first_name, last_name, birth_date, user_id) VALUES ('document_1', 'John', 'Doe', '2020-04-24 00:00:00.000000', 1)"
|
582
|
+
'document_1'
|
583
|
+
else
|
584
|
+
last_id += 1
|
482
585
|
end
|
483
586
|
end
|
587
|
+
|
588
|
+
Sequel.mock fetch: stubs, autoid: autoid
|
484
589
|
end
|
485
590
|
|
486
|
-
let
|
487
|
-
|
488
|
-
|
591
|
+
let :stub_environment do
|
592
|
+
Rasti::DB::Environment.new default: Rasti::DB::DataSource.new(stub_db, :schema_1),
|
593
|
+
custom: Rasti::DB::DataSource.new(stub_db, :schema_2)
|
594
|
+
end
|
595
|
+
|
596
|
+
let(:stub_users) { Users.new stub_environment }
|
597
|
+
let(:stub_posts) { Posts.new stub_environment }
|
598
|
+
let(:stub_comments) { Comments.new stub_environment }
|
599
|
+
let(:stub_people) { People.new stub_environment }
|
600
|
+
let(:stub_languages) { Languages.new stub_environment }
|
489
601
|
|
490
602
|
it 'Insert' do
|
491
603
|
stub_users.insert name: 'User 1'
|
604
|
+
|
492
605
|
stub_db.sqls.must_equal [
|
493
606
|
'BEGIN',
|
494
|
-
"INSERT INTO
|
607
|
+
"INSERT INTO schema_1.users (name) VALUES ('User 1')",
|
495
608
|
'COMMIT'
|
496
609
|
]
|
497
610
|
end
|
498
611
|
|
499
612
|
it 'Insert with many to many relation' do
|
500
|
-
stub_posts.insert user_id: 1, title: 'Post 1', body: '...', categories: [2,3]
|
613
|
+
stub_posts.insert user_id: 1, title: 'Post 1', body: '...', categories: [2,3], language_id: 1
|
614
|
+
|
615
|
+
stub_db.sqls.must_equal [
|
616
|
+
'BEGIN',
|
617
|
+
"INSERT INTO schema_1.posts (user_id, title, body, language_id) VALUES (1, 'Post 1', '...', 1)",
|
618
|
+
'DELETE FROM schema_1.categories_posts WHERE (post_id IN (1))',
|
619
|
+
'INSERT INTO schema_1.categories_posts (post_id, category_id) VALUES (1, 2)',
|
620
|
+
'INSERT INTO schema_1.categories_posts (post_id, category_id) VALUES (1, 3)',
|
621
|
+
'COMMIT'
|
622
|
+
]
|
623
|
+
end
|
624
|
+
|
625
|
+
it 'Insert in multiple schemas' do
|
626
|
+
stub_languages.insert name: 'Spanish'
|
627
|
+
|
628
|
+
stub_users.insert name: 'User 1'
|
629
|
+
|
630
|
+
stub_people.insert document_number: 'document_1',
|
631
|
+
first_name: 'John',
|
632
|
+
last_name: 'Doe',
|
633
|
+
birth_date: Time.parse('2020-04-24'),
|
634
|
+
user_id: 1,
|
635
|
+
languages: [1]
|
636
|
+
|
501
637
|
stub_db.sqls.must_equal [
|
502
638
|
'BEGIN',
|
503
|
-
"INSERT INTO
|
504
|
-
'
|
505
|
-
'
|
506
|
-
|
639
|
+
"INSERT INTO schema_2.languages (name) VALUES ('Spanish')",
|
640
|
+
'COMMIT',
|
641
|
+
'BEGIN',
|
642
|
+
"INSERT INTO schema_1.users (name) VALUES ('User 1')",
|
643
|
+
'COMMIT',
|
644
|
+
'BEGIN',
|
645
|
+
"INSERT INTO schema_1.people (document_number, first_name, last_name, birth_date, user_id) VALUES ('document_1', 'John', 'Doe', '2020-04-24 00:00:00.000000', 1)",
|
646
|
+
"DELETE FROM schema_1.languages_people WHERE (document_number IN ('document_1'))",
|
647
|
+
"INSERT INTO schema_1.languages_people (document_number, language_id) VALUES ('document_1', 1)",
|
507
648
|
'COMMIT'
|
508
649
|
]
|
509
650
|
end
|
510
651
|
|
511
652
|
it 'Update' do
|
512
653
|
stub_users.update 1, name: 'Updated name'
|
654
|
+
|
513
655
|
stub_db.sqls.must_equal [
|
514
656
|
'BEGIN',
|
515
|
-
"UPDATE
|
657
|
+
"UPDATE schema_1.users SET name = 'Updated name' WHERE (id = 1)",
|
516
658
|
'COMMIT'
|
517
659
|
]
|
518
660
|
end
|
519
661
|
|
520
662
|
it 'Delete' do
|
521
663
|
stub_users.delete 1
|
522
|
-
|
664
|
+
|
665
|
+
stub_db.sqls.must_equal [
|
666
|
+
'DELETE FROM schema_1.users WHERE (id = 1)'
|
667
|
+
]
|
523
668
|
end
|
524
669
|
|
525
670
|
it 'Chained query' do
|
526
671
|
stub_users.where(id: [1,2]).limit(1).order(:name).all
|
527
|
-
|
672
|
+
|
673
|
+
stub_db.sqls.must_equal [
|
674
|
+
'SELECT users.* FROM schema_1.users WHERE (users.id IN (1, 2)) ORDER BY users.name LIMIT 1'
|
675
|
+
]
|
528
676
|
end
|
529
677
|
|
530
678
|
it 'Graph' do
|
531
|
-
stub_posts.graph(:user, :categories, 'comments.user.posts.categories').all
|
679
|
+
stub_posts.graph(:user, :categories, 'comments.user.posts.categories', 'language.people').all
|
532
680
|
|
533
681
|
stub_db.sqls.must_equal [
|
534
|
-
'SELECT posts.* FROM
|
535
|
-
'SELECT categories.*,
|
536
|
-
'SELECT comments.* FROM
|
537
|
-
'SELECT users.* FROM
|
538
|
-
'SELECT posts.* FROM
|
539
|
-
'SELECT categories.*,
|
540
|
-
'SELECT
|
682
|
+
'SELECT posts.* FROM schema_1.posts',
|
683
|
+
'SELECT categories.*, categories_posts.post_id AS source_foreign_key FROM schema_1.categories INNER JOIN schema_1.categories_posts ON (schema_1.categories_posts.category_id = schema_1.categories.id) WHERE (categories_posts.post_id IN (3, 4))',
|
684
|
+
'SELECT comments.* FROM schema_1.comments WHERE (comments.post_id IN (3, 4))',
|
685
|
+
'SELECT users.* FROM schema_1.users WHERE (users.id IN (2, 1))',
|
686
|
+
'SELECT posts.* FROM schema_1.posts WHERE (posts.user_id IN (1, 2))',
|
687
|
+
'SELECT categories.*, categories_posts.post_id AS source_foreign_key FROM schema_1.categories INNER JOIN schema_1.categories_posts ON (schema_1.categories_posts.category_id = schema_1.categories.id) WHERE (categories_posts.post_id IN (3, 4))',
|
688
|
+
'SELECT languages.* FROM schema_2.languages WHERE (languages.id IN (1, 2))',
|
689
|
+
'SELECT people.*, languages_people.language_id AS source_foreign_key FROM schema_1.people INNER JOIN schema_1.languages_people ON (schema_1.languages_people.document_number = schema_1.people.document_number) WHERE (languages_people.language_id IN (1, 2))',
|
690
|
+
'SELECT users.* FROM schema_1.users WHERE (users.id IN (1, 2))'
|
691
|
+
]
|
692
|
+
end
|
693
|
+
|
694
|
+
it 'Join' do
|
695
|
+
stub_posts.join('user.person').where(document_number: 'document_1').all
|
696
|
+
|
697
|
+
stub_db.sqls.must_equal [
|
698
|
+
"SELECT DISTINCT posts.* FROM schema_1.posts INNER JOIN schema_1.users AS user ON (user.id = posts.user_id) INNER JOIN schema_1.people AS user__person ON (user__person.user_id = user.id) WHERE (posts.document_number = 'document_1')"
|
541
699
|
]
|
542
700
|
end
|
543
701
|
|
544
702
|
it 'Named query' do
|
545
703
|
stub_posts.commented_by(1).all
|
704
|
+
|
546
705
|
stub_db.sqls.must_equal [
|
547
|
-
'SELECT DISTINCT posts.* FROM
|
706
|
+
'SELECT DISTINCT posts.* FROM schema_1.posts INNER JOIN schema_1.comments ON (schema_1.comments.post_id = schema_1.posts.id) WHERE (comments.user_id = 1)'
|
548
707
|
]
|
549
708
|
end
|
550
709
|
|
551
710
|
it 'Custom query' do
|
552
711
|
stub_comments.posts_commented_by(2)
|
712
|
+
|
553
713
|
stub_db.sqls.must_equal [
|
554
|
-
'SELECT posts.* FROM
|
714
|
+
'SELECT posts.* FROM schema_1.comments INNER JOIN schema_1.posts ON (schema_1.posts.id = schema_1.comments.post_id) WHERE (comments.user_id = 2)'
|
555
715
|
]
|
556
716
|
end
|
557
717
|
|