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