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
data/spec/query_spec.rb
CHANGED
@@ -3,22 +3,26 @@ require 'minitest_helper'
|
|
3
3
|
describe 'Query' do
|
4
4
|
|
5
5
|
before do
|
6
|
-
|
6
|
+
custom_db[:languages].insert name: 'Spanish'
|
7
|
+
|
8
|
+
1.upto(10) do |i|
|
7
9
|
db[:users].insert name: "User #{i}"
|
8
10
|
|
9
|
-
db[:people].insert user_id: i,
|
10
|
-
document_number: i,
|
11
|
-
first_name: "Name #{i}",
|
12
|
-
last_name: "Last Name #{i}",
|
13
|
-
birth_date:
|
11
|
+
db[:people].insert user_id: i,
|
12
|
+
document_number: "document_#{i}",
|
13
|
+
first_name: "Name #{i}",
|
14
|
+
last_name: "Last Name #{i}",
|
15
|
+
birth_date: Date.parse('2020-04-24')
|
16
|
+
|
17
|
+
db[:languages_people].insert language_id: 1, document_number: "document_#{i}"
|
14
18
|
end
|
15
19
|
|
16
|
-
db[:posts].insert user_id: 2, title: 'Sample post', body: '...'
|
17
|
-
db[:posts].insert user_id: 1, title: 'Another post', body: '...'
|
18
|
-
db[:posts].insert user_id: 4, title: 'Best post', body: '...'
|
20
|
+
db[:posts].insert user_id: 2, title: 'Sample post', body: '...', language_id: 1
|
21
|
+
db[:posts].insert user_id: 1, title: 'Another post', body: '...', language_id: 1
|
22
|
+
db[:posts].insert user_id: 4, title: 'Best post', body: '...', language_id: 1
|
19
23
|
|
20
24
|
1.upto(3) { |i| db[:categories].insert name: "Category #{i}" }
|
21
|
-
|
25
|
+
|
22
26
|
db[:comments].insert post_id: 1, user_id: 5, text: 'Comment 1'
|
23
27
|
db[:comments].insert post_id: 1, user_id: 7, text: 'Comment 2'
|
24
28
|
db[:comments].insert post_id: 2, user_id: 2, text: 'Comment 3'
|
@@ -30,11 +34,15 @@ describe 'Query' do
|
|
30
34
|
db[:categories_posts].insert post_id: 3, category_id: 3
|
31
35
|
end
|
32
36
|
|
33
|
-
let(:users_query) { Rasti::DB::Query.new collection_class: Users, dataset: db[:users] }
|
34
|
-
|
35
|
-
let(:posts_query) { Rasti::DB::Query.new collection_class: Posts, dataset: db[:posts] }
|
36
|
-
|
37
|
-
let(:comments_query) { Rasti::DB::Query.new collection_class: Comments, dataset: db[:comments] }
|
37
|
+
let(:users_query) { Rasti::DB::Query.new collection_class: Users, dataset: db[:users], environment: environment }
|
38
|
+
|
39
|
+
let(:posts_query) { Rasti::DB::Query.new collection_class: Posts, dataset: db[:posts], environment: environment }
|
40
|
+
|
41
|
+
let(:comments_query) { Rasti::DB::Query.new collection_class: Comments, dataset: db[:comments], environment: environment }
|
42
|
+
|
43
|
+
let(:people_query) { Rasti::DB::Query.new collection_class: People, dataset: db[:people], environment: environment }
|
44
|
+
|
45
|
+
let(:languages_query) { Rasti::DB::Query.new collection_class: Languages, dataset: custom_db[:languages], environment: environment }
|
38
46
|
|
39
47
|
it 'Count' do
|
40
48
|
users_query.count.must_equal 10
|
@@ -62,7 +70,7 @@ describe 'Query' do
|
|
62
70
|
end
|
63
71
|
|
64
72
|
it 'Exclude attributes' do
|
65
|
-
posts_query.exclude_attributes(:body).all.must_equal db[:posts].select(:id, :user_id, :title).map { |r| Post.new r }
|
73
|
+
posts_query.exclude_attributes(:body).all.must_equal db[:posts].select(:id, :user_id, :title, :language_id).map { |r| Post.new r }
|
66
74
|
end
|
67
75
|
|
68
76
|
it 'All attributes' do
|
@@ -70,35 +78,57 @@ describe 'Query' do
|
|
70
78
|
end
|
71
79
|
|
72
80
|
it 'Select graph attributes' do
|
73
|
-
|
81
|
+
language = Language.new custom_db[:languages].where(id: 1).select(:id).first
|
82
|
+
|
83
|
+
person = Person.new db[:people].where(document_number: 'document_2').select(:document_number, :user_id).first.merge(languages: [language])
|
74
84
|
|
75
85
|
user = User.new db[:users].where(id: 2).select(:id).first.merge(person: person)
|
76
86
|
|
77
|
-
|
87
|
+
categories = db[:categories].where(id: [1,2]).select(:id).map { |c| Category.new c }
|
88
|
+
|
89
|
+
post = Post.new db[:posts].where(id: 1).first.merge(user: user, categories: categories)
|
90
|
+
|
91
|
+
selected_attributes = {
|
92
|
+
user: [:id],
|
93
|
+
'user.person' => [:document_number, :user_id],
|
94
|
+
'user.person.languages' => [:id],
|
95
|
+
categories: [:id]
|
96
|
+
}
|
78
97
|
|
79
98
|
posts_query.where(id: 1)
|
80
|
-
.graph(
|
81
|
-
.select_graph_attributes(
|
99
|
+
.graph(*selected_attributes.keys)
|
100
|
+
.select_graph_attributes(selected_attributes)
|
82
101
|
.all
|
83
102
|
.must_equal [post]
|
84
103
|
end
|
85
|
-
|
104
|
+
|
86
105
|
it 'Exclude graph attributes' do
|
87
|
-
|
106
|
+
language = Language.new custom_db[:languages].where(id: 1).select(:id).first
|
107
|
+
|
108
|
+
person = Person.new db[:people].where(document_number: 'document_2').select(:document_number, :user_id).first.merge(languages: [language])
|
88
109
|
|
89
110
|
user = User.new db[:users].where(id: 2).select(:id).first.merge(person: person)
|
90
111
|
|
91
|
-
|
112
|
+
categories = db[:categories].where(id: [1,2]).select(:id).map { |c| Category.new c }
|
113
|
+
|
114
|
+
post = Post.new db[:posts].where(id: 1).first.merge(user: user, categories: categories)
|
115
|
+
|
116
|
+
excluded_attributes = {
|
117
|
+
user: [:name],
|
118
|
+
'user.person' => [:first_name, :last_name, :birth_date],
|
119
|
+
'user.person.languages' => [:name],
|
120
|
+
categories: [:name]
|
121
|
+
}
|
92
122
|
|
93
123
|
posts_query.where(id: 1)
|
94
|
-
.graph(
|
95
|
-
.exclude_graph_attributes(
|
124
|
+
.graph(*excluded_attributes.keys)
|
125
|
+
.exclude_graph_attributes(excluded_attributes)
|
96
126
|
.all
|
97
127
|
.must_equal [post]
|
98
128
|
end
|
99
|
-
|
129
|
+
|
100
130
|
it 'All graph attributes' do
|
101
|
-
person = Person.new db[:people].where(document_number:
|
131
|
+
person = Person.new db[:people].where(document_number: 'document_2').first
|
102
132
|
|
103
133
|
user = User.new db[:users].where(id: 2).select(:id).first.merge(person: person)
|
104
134
|
|
@@ -112,6 +142,30 @@ describe 'Query' do
|
|
112
142
|
.must_equal [post]
|
113
143
|
end
|
114
144
|
|
145
|
+
describe 'Select computed attributes' do
|
146
|
+
it 'With join' do
|
147
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'Comment 4'
|
148
|
+
users_query.select_computed_attributes(:comments_count)
|
149
|
+
.where(id: 5)
|
150
|
+
.all
|
151
|
+
.must_equal [User.new(id: 5, name: 'User 5', comments_count: 2)]
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'Without join' do
|
155
|
+
person_expected = Person.new user_id: 1,
|
156
|
+
document_number: 'document_1',
|
157
|
+
first_name: 'Name 1',
|
158
|
+
last_name: 'Last Name 1',
|
159
|
+
birth_date: Date.parse('2020-04-24'),
|
160
|
+
full_name: 'Name 1 Last Name 1'
|
161
|
+
|
162
|
+
people_query.select_computed_attributes(:full_name)
|
163
|
+
.where(document_number: 'document_1')
|
164
|
+
.all
|
165
|
+
.must_equal [person_expected]
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
115
169
|
it 'Map' do
|
116
170
|
users_query.map(&:name).must_equal db[:users].map(:name)
|
117
171
|
end
|
@@ -120,45 +174,88 @@ describe 'Query' do
|
|
120
174
|
users_query.detect(id: 3).must_equal User.new(id: 3, name: 'User 3')
|
121
175
|
end
|
122
176
|
|
177
|
+
describe 'Each' do
|
178
|
+
|
179
|
+
it 'without size' do
|
180
|
+
users = []
|
181
|
+
|
182
|
+
users_query.each do |user|
|
183
|
+
users << user
|
184
|
+
end
|
185
|
+
|
186
|
+
users.size.must_equal 10
|
187
|
+
users.each_with_index do |user, i|
|
188
|
+
user.must_equal User.new(id: i+1, name: "User #{i+1}")
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'with size' do
|
193
|
+
users = []
|
194
|
+
users_query.each(batch_size: 2) do |user|
|
195
|
+
users << user
|
196
|
+
end
|
197
|
+
|
198
|
+
users.size.must_equal 10
|
199
|
+
users.each_with_index do |user, i|
|
200
|
+
user.must_equal User.new(id: i+1, name: "User #{i+1}")
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'Each batch' do
|
207
|
+
users_batch = []
|
208
|
+
users_query.each_batch(size: 2) do |page|
|
209
|
+
users_batch << page
|
210
|
+
end
|
211
|
+
|
212
|
+
users_batch.size.must_equal 5
|
213
|
+
i = 1
|
214
|
+
users_batch.each do |user_page|
|
215
|
+
user_page.must_equal [User.new(id: i, name: "User #{i}"), User.new(id: i+1, name: "User #{i+1}")]
|
216
|
+
i += 2
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
123
220
|
it 'Where' do
|
124
221
|
users_query.where(id: 3).all.must_equal [User.new(id: 3, name: 'User 3')]
|
125
222
|
end
|
126
|
-
|
223
|
+
|
127
224
|
it 'Exclude' do
|
128
225
|
users_query.exclude(id: [1,2,3,4,5,6,7,8,9]).all.must_equal [User.new(id: 10, name: 'User 10')]
|
129
226
|
end
|
130
|
-
|
227
|
+
|
131
228
|
it 'And' do
|
132
229
|
users_query.where(id: [1,2]).where(name: 'User 2').all.must_equal [User.new(id: 2, name: 'User 2')]
|
133
230
|
end
|
134
|
-
|
231
|
+
|
135
232
|
it 'Or' do
|
136
233
|
users_query.where(id: 1).or(name: 'User 2').all.must_equal [
|
137
|
-
User.new(id: 1, name: 'User 1'),
|
234
|
+
User.new(id: 1, name: 'User 1'),
|
138
235
|
User.new(id: 2, name: 'User 2')
|
139
236
|
]
|
140
237
|
end
|
141
|
-
|
238
|
+
|
142
239
|
it 'Order' do
|
143
240
|
posts_query.order(:title).all.must_equal [
|
144
|
-
Post.new(id: 2, user_id: 1, title: 'Another post', body: '...'),
|
145
|
-
Post.new(id: 3, user_id: 4, title: 'Best post', body: '...'),
|
146
|
-
Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...')
|
241
|
+
Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1),
|
242
|
+
Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
|
243
|
+
Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...', language_id: 1)
|
147
244
|
]
|
148
245
|
end
|
149
|
-
|
246
|
+
|
150
247
|
it 'Reverse order' do
|
151
248
|
posts_query.reverse_order(:title).all.must_equal [
|
152
|
-
Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...'),
|
153
|
-
Post.new(id: 3, user_id: 4, title: 'Best post', body: '...'),
|
154
|
-
Post.new(id: 2, user_id: 1, title: 'Another post', body: '...')
|
249
|
+
Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...', language_id: 1),
|
250
|
+
Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
|
251
|
+
Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1)
|
155
252
|
]
|
156
253
|
end
|
157
|
-
|
254
|
+
|
158
255
|
it 'Limit and offset' do
|
159
256
|
users_query.limit(1).offset(1).all.must_equal [User.new(id: 2, name: 'User 2')]
|
160
257
|
end
|
161
|
-
|
258
|
+
|
162
259
|
it 'First' do
|
163
260
|
users_query.first.must_equal User.new(id: 1, name: 'User 1')
|
164
261
|
end
|
@@ -168,7 +265,32 @@ describe 'Query' do
|
|
168
265
|
end
|
169
266
|
|
170
267
|
it 'Graph' do
|
171
|
-
users_query.graph(:posts).where(id: 1).first.must_equal User.new(id: 1, name: 'User 1', posts: [Post.new(id: 2, user_id: 1, title: 'Another post', body: '...')])
|
268
|
+
users_query.graph(:posts).where(id: 1).first.must_equal User.new(id: 1, name: 'User 1', posts: [Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1)])
|
269
|
+
end
|
270
|
+
|
271
|
+
it 'Graph with multiple data sources' do
|
272
|
+
language = Language.new id: 1, name: 'Spanish'
|
273
|
+
|
274
|
+
person = Person.new user_id: 2,
|
275
|
+
document_number: 'document_2',
|
276
|
+
first_name: 'Name 2',
|
277
|
+
last_name: 'Last Name 2',
|
278
|
+
birth_date: Date.parse('2020-04-24'),
|
279
|
+
languages: [language]
|
280
|
+
|
281
|
+
user = User.new id: 2,
|
282
|
+
name: 'User 2',
|
283
|
+
person: person
|
284
|
+
|
285
|
+
post = Post.new id: 1,
|
286
|
+
user_id: 2,
|
287
|
+
user: user,
|
288
|
+
title: 'Sample post',
|
289
|
+
body: '...',
|
290
|
+
language_id: 1,
|
291
|
+
language: language
|
292
|
+
|
293
|
+
posts_query.where(id: 1).graph(:language, 'user.person.languages').first.must_equal post
|
172
294
|
end
|
173
295
|
|
174
296
|
it 'Any?' do
|
@@ -184,7 +306,7 @@ describe 'Query' do
|
|
184
306
|
end
|
185
307
|
|
186
308
|
it 'To String' do
|
187
|
-
users_query.where(id: [1,2,3]).order(:name).to_s.must_equal '#<Rasti::DB::Query: "SELECT
|
309
|
+
users_query.where(id: [1,2,3]).order(:name).to_s.must_equal '#<Rasti::DB::Query: "SELECT `users`.* FROM `users` WHERE (`users`.`id` IN (1, 2, 3)) ORDER BY `users`.`name`">'
|
188
310
|
end
|
189
311
|
|
190
312
|
describe 'Named queries' do
|
@@ -204,30 +326,62 @@ describe 'Query' do
|
|
204
326
|
describe 'Join' do
|
205
327
|
|
206
328
|
it 'One to Many' do
|
207
|
-
users_query.join(:posts).where(title
|
329
|
+
users_query.join(:posts).where(Sequel[:posts][:title] => 'Sample post').all.must_equal [User.new(id: 2, name: 'User 2')]
|
208
330
|
end
|
209
331
|
|
210
332
|
it 'Many to One' do
|
211
|
-
posts_query.join(:user).where(name
|
333
|
+
posts_query.join(:user).where(Sequel[:user][:name] => 'User 4').all.must_equal [Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1)]
|
212
334
|
end
|
213
335
|
|
214
336
|
it 'One to One' do
|
215
|
-
users_query.join(:person).where(document_number
|
337
|
+
users_query.join(:person).where(Sequel[:person][:document_number] => 'document_1').all.must_equal [User.new(id: 1, name: 'User 1')]
|
216
338
|
end
|
217
339
|
|
218
340
|
it 'Many to Many' do
|
219
|
-
posts_query.join(:categories).where(name
|
220
|
-
Post.new(id: 2, user_id: 1, title: 'Another post', body: '...'),
|
221
|
-
Post.new(id: 3, user_id: 4, title: 'Best post', body: '...'),
|
341
|
+
posts_query.join(:categories).where(Sequel[:categories][:name] => 'Category 3').order(:id).all.must_equal [
|
342
|
+
Post.new(id: 2, user_id: 1, title: 'Another post', body: '...', language_id: 1),
|
343
|
+
Post.new(id: 3, user_id: 4, title: 'Best post', body: '...', language_id: 1),
|
222
344
|
]
|
223
345
|
end
|
224
346
|
|
225
347
|
it 'Nested' do
|
226
348
|
posts_query.join('categories', 'comments.user.person')
|
227
349
|
.where(Sequel[:categories][:name] => 'Category 2')
|
228
|
-
.where(Sequel[:comments__user__person][:document_number] =>
|
350
|
+
.where(Sequel[:comments__user__person][:document_number] => 'document_7')
|
229
351
|
.all
|
230
|
-
.must_equal [Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...')]
|
352
|
+
.must_equal [Post.new(id: 1, user_id: 2, title: 'Sample post', body: '...', language_id: 1)]
|
353
|
+
end
|
354
|
+
|
355
|
+
it 'Excluded attributes permanents excluded when join' do
|
356
|
+
posts_query.join(:user)
|
357
|
+
.exclude_attributes(:body)
|
358
|
+
.where(Sequel[:user][:name] => 'User 4')
|
359
|
+
.all
|
360
|
+
.must_equal [Post.new(id: 3, title: 'Best post', user_id: 4, language_id: 1)]
|
361
|
+
|
362
|
+
posts_query.exclude_attributes(:body)
|
363
|
+
.join(:user)
|
364
|
+
.where(Sequel[:user][:name] => 'User 4')
|
365
|
+
.all
|
366
|
+
.must_equal [Post.new(id: 3, title: 'Best post', user_id: 4, language_id: 1)]
|
367
|
+
end
|
368
|
+
|
369
|
+
describe 'Multiple data sources' do
|
370
|
+
|
371
|
+
it 'One to Many' do
|
372
|
+
error = proc { languages_query.join(:posts).all }.must_raise RuntimeError
|
373
|
+
error.message.must_equal 'Invalid join of multiple data sources: custom.languages > default.posts'
|
374
|
+
end
|
375
|
+
|
376
|
+
it 'Many to One' do
|
377
|
+
error = proc { posts_query.join(:language).all }.must_raise RuntimeError
|
378
|
+
error.message.must_equal 'Invalid join of multiple data sources: default.posts > custom.languages'
|
379
|
+
end
|
380
|
+
|
381
|
+
it 'Many to Many' do
|
382
|
+
error = proc { languages_query.join(:people).all }.must_raise RuntimeError
|
383
|
+
error.message.must_equal 'Invalid join of multiple data sources: custom.languages > default.people'
|
384
|
+
end
|
231
385
|
end
|
232
386
|
|
233
387
|
end
|
@@ -238,7 +392,7 @@ describe 'Query' do
|
|
238
392
|
error = proc { posts_query.nql('a + b') }.must_raise Rasti::DB::NQL::InvalidExpressionError
|
239
393
|
error.message.must_equal 'Invalid filter expression: a + b'
|
240
394
|
end
|
241
|
-
|
395
|
+
|
242
396
|
it 'Filter to self table' do
|
243
397
|
posts_query.nql('user_id > 1')
|
244
398
|
.pluck(:user_id)
|
@@ -254,17 +408,149 @@ describe 'Query' do
|
|
254
408
|
end
|
255
409
|
|
256
410
|
it 'Filter to 2nd order relation' do
|
257
|
-
posts_query.nql('comments.user.person.document_number =
|
411
|
+
posts_query.nql('comments.user.person.document_number = document_7')
|
258
412
|
.pluck(:id)
|
259
413
|
.must_equal [1]
|
260
414
|
end
|
261
415
|
|
262
416
|
it 'Filter combined' do
|
263
|
-
posts_query.nql('(categories.id = 1 | categories.id = 3) & comments.user.person.document_number =
|
417
|
+
posts_query.nql('(categories.id = 1 | categories.id = 3) & comments.user.person.document_number = document_2')
|
264
418
|
.pluck(:id)
|
265
419
|
.must_equal [2]
|
266
420
|
end
|
267
421
|
|
422
|
+
describe 'Computed Attributes' do
|
423
|
+
|
424
|
+
it 'Filter relation computed attribute' do
|
425
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'Comment 4'
|
426
|
+
users_query.nql('comments_count = 2').all.must_equal [User.new(id: 5, name: 'User 5')]
|
427
|
+
end
|
428
|
+
|
429
|
+
it 'Filter with relation computed attribute with "and" combined' do
|
430
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'Comment 4'
|
431
|
+
db[:comments].insert post_id: 1, user_id: 4, text: 'Comment 3'
|
432
|
+
users_query.nql('(comments_count > 1) & (id = 5)').all.must_equal [User.new(id: 5, name: 'User 5')]
|
433
|
+
end
|
434
|
+
|
435
|
+
it 'Filter relation computed attribute with "or" combined' do
|
436
|
+
db[:comments].insert post_id: 1, user_id: 2, text: 'Comment 3'
|
437
|
+
users_query.nql('(comments_count = 2) | (id = 5)')
|
438
|
+
.order(:id)
|
439
|
+
.all
|
440
|
+
.must_equal [ User.new(id: 2, name: 'User 2'), User.new(id: 5, name: 'User 5') ]
|
441
|
+
end
|
442
|
+
|
443
|
+
it 'Filter relation computed attribute with "and" and "or" combined' do
|
444
|
+
db[:comments].insert post_id: 1, user_id: 2, text: 'Comment 3'
|
445
|
+
users_query.nql('((comments_count = 2) | (id = 5)) & (name: User 5)')
|
446
|
+
.order(:id)
|
447
|
+
.all
|
448
|
+
.must_equal [ User.new(id: 5, name: 'User 5') ]
|
449
|
+
end
|
450
|
+
|
451
|
+
it 'Filter simple computed attribute' do
|
452
|
+
person_expected = Person.new user_id: 1,
|
453
|
+
document_number: 'document_1',
|
454
|
+
first_name: 'Name 1',
|
455
|
+
last_name: 'Last Name 1',
|
456
|
+
birth_date: Date.parse('2020-04-24')
|
457
|
+
|
458
|
+
people_query.nql('full_name = Name 1 Last Name 1')
|
459
|
+
.all
|
460
|
+
.must_equal [person_expected]
|
461
|
+
end
|
462
|
+
|
463
|
+
end
|
464
|
+
|
465
|
+
describe 'Filter Array' do
|
466
|
+
|
467
|
+
def filter_condition_must_raise(comparison_symbol, comparison_name)
|
468
|
+
error = proc { comments_query.nql("tags #{comparison_symbol} [fake, notice]") }.must_raise Rasti::DB::NQL::FilterConditionStrategies::UnsupportedTypeComparison
|
469
|
+
error.argument_type.must_equal Rasti::DB::NQL::FilterConditionStrategies::Types::SQLiteArray
|
470
|
+
error.comparison_name.must_equal comparison_name
|
471
|
+
error.message.must_equal "Unsupported comparison #{comparison_name} for Rasti::DB::NQL::FilterConditionStrategies::Types::SQLiteArray"
|
472
|
+
end
|
473
|
+
|
474
|
+
it 'Must raise exception from not supported methods' do
|
475
|
+
comparisons = {
|
476
|
+
greater_than: '>',
|
477
|
+
greater_than_or_equal: '>=',
|
478
|
+
less_than: '<',
|
479
|
+
less_than_or_equal: '<='
|
480
|
+
}
|
481
|
+
|
482
|
+
comparisons.each do |name, symbol|
|
483
|
+
filter_condition_must_raise symbol, name
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
it 'Included any of these elements' do
|
488
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice', tags: '["fake","notice"]'
|
489
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice 2', tags: '["notice"]'
|
490
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice 3', tags: '["fake_notice"]'
|
491
|
+
expected_comments = [
|
492
|
+
Comment.new(id: 4, text: 'fake notice', tags: ['fake','notice'], user_id: 5, post_id: 1),
|
493
|
+
Comment.new(id: 5, text: 'fake notice 2', tags: ['notice'], user_id: 5, post_id: 1)
|
494
|
+
]
|
495
|
+
|
496
|
+
comments_query.nql('tags: [ fake, notice ]')
|
497
|
+
.all
|
498
|
+
.must_equal expected_comments
|
499
|
+
end
|
500
|
+
|
501
|
+
it 'Included exactly all these elements' do
|
502
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice', tags: '["fake","notice"]'
|
503
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice 2', tags: '["notice"]'
|
504
|
+
comments_query.nql('tags = [fake, notice]')
|
505
|
+
.all
|
506
|
+
.must_equal [Comment.new(id: 4, text: 'fake notice', tags: ['fake','notice'], user_id: 5, post_id: 1)]
|
507
|
+
end
|
508
|
+
|
509
|
+
it 'Not included anyone of these elements' do
|
510
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice', tags: '["fake","notice"]'
|
511
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'Good notice!', tags: '["good"]'
|
512
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice', tags: '["fake"]'
|
513
|
+
expected_comments = [
|
514
|
+
Comment.new(id: 1, text: 'Comment 1', tags: [], user_id: 5, post_id: 1),
|
515
|
+
Comment.new(id: 2, text: 'Comment 2', tags: [], user_id: 7, post_id: 1),
|
516
|
+
Comment.new(id: 3, text: 'Comment 3', tags: [], user_id: 2, post_id: 2),
|
517
|
+
Comment.new(id: 5, text: 'Good notice!', tags: ['good'], user_id: 5, post_id: 1)
|
518
|
+
]
|
519
|
+
comments_query.nql('tags !: [fake, notice]')
|
520
|
+
.all
|
521
|
+
.must_equal expected_comments
|
522
|
+
end
|
523
|
+
|
524
|
+
it 'Not include any of these elements' do
|
525
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice', tags: '["fake","notice"]'
|
526
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'Good notice!', tags: '["good"]'
|
527
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice', tags: '["fake"]'
|
528
|
+
expected_comments = [
|
529
|
+
Comment.new(id: 1, text: 'Comment 1', tags: '[]', user_id: 5, post_id: 1),
|
530
|
+
Comment.new(id: 2, text: 'Comment 2', tags: '[]', user_id: 7, post_id: 1),
|
531
|
+
Comment.new(id: 3, text: 'Comment 3', tags: '[]', user_id: 2, post_id: 2),
|
532
|
+
Comment.new(id: 5, text: 'Good notice!', tags: ['good'], user_id: 5, post_id: 1),
|
533
|
+
Comment.new(id: 6, text: 'fake notice', tags: ['fake'], user_id: 5, post_id: 1)
|
534
|
+
]
|
535
|
+
comments_query.nql('tags != [fake, notice]')
|
536
|
+
.all
|
537
|
+
.must_equal expected_comments
|
538
|
+
end
|
539
|
+
|
540
|
+
it 'Include any like these elements' do
|
541
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'fake notice', tags: '["fake","notice"]'
|
542
|
+
db[:comments].insert post_id: 1, user_id: 5, text: 'this is a fake notice!', tags: '["fake_notice"]'
|
543
|
+
expected_comments = [
|
544
|
+
Comment.new(id: 4, text: 'fake notice', tags: ['fake','notice'], user_id: 5, post_id: 1),
|
545
|
+
Comment.new(id: 5, text: 'this is a fake notice!', tags: ['fake_notice'], user_id: 5, post_id: 1)
|
546
|
+
]
|
547
|
+
comments_query.nql('tags ~ [fake]')
|
548
|
+
.all
|
549
|
+
.must_equal expected_comments
|
550
|
+
end
|
551
|
+
|
552
|
+
end
|
553
|
+
|
268
554
|
end
|
269
555
|
|
270
556
|
end
|