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
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
|