v / vlib / orm / orm_insert_test.v
456 lines · 365 sloc · 7.21 KB · 99be39cbd15d4bbb5ab14d2f870199908c00bc8d
Raw
1// vtest retry: 3
2import db.sqlite
3import rand
4
5struct Parent {
6 id int @[primary; sql: serial]
7 name string
8 children []Child @[fkey: 'parent_id']
9 notes []Note @[fkey: 'owner_id']
10}
11
12struct Child {
13mut:
14 id int @[primary; sql: serial]
15 parent_id int
16 name string
17}
18
19struct Note {
20mut:
21 id int @[primary; sql: serial]
22 owner_id int
23 text string
24}
25
26struct Account {
27 id int @[primary; sql: serial]
28}
29
30struct Package {
31 id int @[primary; sql: serial]
32 name string @[unique]
33 author User @[fkey: 'id'] // mandatory user
34}
35
36struct Delivery {
37 id int @[primary; sql: serial]
38 name string @[unique]
39 author ?User @[fkey: 'id'] // optional user
40}
41
42struct User {
43pub mut:
44 id int @[primary; sql: serial]
45 username string @[unique]
46}
47
48struct Entity {
49 uuid string @[primary]
50 description string
51}
52
53struct EntityWithFloatPrimary {
54 id f64 @[primary]
55 name string
56}
57
58pub fn insert_parent(db sqlite.DB, mut parent Parent) ! {
59 sql db {
60 insert parent into Parent
61 }!
62}
63
64fn test_set_primary_value() {
65 // The primary key is an constraint that ensures each record in a table is unique.
66 // Primary keys must contain unique values and cannot contain `NULL` values.
67 // However, this statement does not imply that a value cannot be inserted by the user.
68 // Therefore, let's allow this.
69 db := sqlite.connect(':memory:')!
70
71 sql db {
72 create table Child
73 }!
74
75 child := Child{
76 id: 10
77 parent_id: 20
78 }
79
80 sql db {
81 insert child into Child
82 }!
83
84 children := sql db {
85 select from Child
86 }!
87
88 assert children.first() == child
89}
90
91fn test_uuid_primary_key() {
92 db := sqlite.connect(':memory:')!
93 uuid := rand.uuid_v4()
94
95 sql db {
96 create table Entity
97 }!
98
99 entity := Entity{
100 uuid: uuid
101 description: 'Test'
102 }
103
104 sql db {
105 insert entity into Entity
106 }!
107
108 entities := sql db {
109 select from Entity where uuid == uuid
110 }!
111
112 mut is_duplicate_inserted := true
113
114 sql db {
115 insert entity into Entity
116 } or { is_duplicate_inserted = false }
117
118 assert entities.len == 1
119 assert entities.first() == entity
120 assert is_duplicate_inserted == false
121}
122
123fn test_float_primary_key() {
124 db := sqlite.connect(':memory:')!
125 id := 3.14
126
127 sql db {
128 create table EntityWithFloatPrimary
129 }!
130
131 entity := EntityWithFloatPrimary{
132 id: id
133 name: 'Test'
134 }
135
136 sql db {
137 insert entity into EntityWithFloatPrimary
138 }!
139
140 entities := sql db {
141 select from EntityWithFloatPrimary where id == id
142 }!
143
144 assert entities.len == 1
145 assert entities.first() == entity
146}
147
148fn test_does_not_insert_uninitialized_mandatory_field() {
149 db := sqlite.connect(':memory:')!
150
151 sql db {
152 create table User
153 create table Package
154 }!
155
156 package := Package{
157 name: 'xml'
158 // author
159 }
160
161 mut query_successful := true
162
163 sql db {
164 insert package into Package
165 } or { query_successful = false }
166
167 assert !query_successful
168
169 users := sql db {
170 select from User
171 }!
172
173 // users must be empty because the package doesn't have an initialized `User` structure.
174 assert users.len == 0
175}
176
177fn test_insert_empty_mandatory_field() {
178 db := sqlite.connect(':memory:')!
179
180 sql db {
181 create table User
182 create table Package
183 }!
184
185 package := Package{
186 name: 'xml'
187 author: User{}
188 }
189
190 sql db {
191 insert package into Package
192 }!
193
194 users := sql db {
195 select from User
196 }!
197
198 assert users.len == 1
199}
200
201fn test_does_insert_uninitialized_optional_field() {
202 db := sqlite.connect(':memory:')!
203
204 sql db {
205 create table User
206 create table Delivery
207 }!
208
209 package := Delivery{
210 name: 'wow'
211 // author
212 }
213
214 sql db {
215 insert package into Delivery
216 }!
217
218 users := sql db {
219 select from User
220 }!
221
222 assert users.len == 0 // no user added
223}
224
225fn test_insert_empty_optional_field() {
226 db := sqlite.connect(':memory:')!
227
228 sql db {
229 create table User
230 create table Delivery
231 }!
232
233 package := Delivery{
234 name: 'bob'
235 author: User{}
236 }
237
238 sql db {
239 insert package into Delivery
240 }!
241
242 users := sql db {
243 select from User
244 }!
245
246 assert users.len == 1 // user was added
247}
248
249fn test_insert_empty_object() {
250 db := sqlite.connect(':memory:')!
251
252 account := Account{}
253
254 sql db {
255 create table Account
256 insert account into Account
257 }!
258
259 accounts := sql db {
260 select from Account
261 }!
262
263 assert accounts.len == 1
264}
265
266fn test_orm_insert_mut_object() {
267 db := sqlite.connect(':memory:')!
268
269 sql db {
270 create table Parent
271 create table Child
272 create table Note
273 }!
274
275 mut parent := Parent{
276 name: 'test'
277 }
278
279 insert_parent(db, mut parent)!
280
281 parents := sql db {
282 select from Parent
283 }!
284
285 assert parents.len == 1
286}
287
288fn test_orm_insert_with_multiple_child_elements() {
289 mut db := sqlite.connect(':memory:')!
290
291 sql db {
292 create table Parent
293 create table Child
294 create table Note
295 }!
296
297 new_parent := Parent{
298 name: 'test'
299 children: [
300 Child{
301 name: 'Lisa'
302 },
303 Child{
304 name: 'Steve'
305 },
306 ]
307 notes: [
308 Note{
309 text: 'First note'
310 },
311 Note{
312 text: 'Second note'
313 },
314 Note{
315 text: 'Third note'
316 },
317 ]
318 }
319
320 sql db {
321 insert new_parent into Parent
322 }!
323
324 parents := sql db {
325 select from Parent where id == 1
326 }!
327
328 parent := parents.first()
329 assert parent.children.len == new_parent.children.len
330 assert parent.notes.len == new_parent.notes.len
331
332 children_count := sql db {
333 select count from Child
334 }!
335 assert children_count == new_parent.children.len
336
337 note_count := sql db {
338 select count from Note
339 }!
340 assert note_count == new_parent.notes.len
341
342 assert parent.children[0].name == 'Lisa'
343 assert parent.children[1].name == 'Steve'
344
345 assert parent.notes[0].text == 'First note'
346 assert parent.notes[1].text == 'Second note'
347 assert parent.notes[2].text == 'Third note'
348}
349
350fn test_orm_insert_with_child_element_and_no_table() {
351 mut db := sqlite.connect(':memory:')!
352
353 sql db {
354 create table Parent
355 }!
356
357 new_parent := Parent{
358 name: 'test'
359 children: [
360 Child{
361 name: 'Lisa'
362 },
363 ]
364 }
365
366 sql db {
367 insert new_parent into Parent
368 } or { assert true }
369
370 sql db {
371 create table Child
372 }!
373
374 sql db {
375 insert new_parent into Parent
376 } or { assert false }
377
378 new_parent_two := Parent{
379 name: 'retest'
380 children: [
381 Child{
382 name: 'Sophia'
383 },
384 ]
385 }
386
387 sql db {
388 insert new_parent_two into Parent
389 } or { assert false }
390
391 p_table := sql db {
392 select from Parent
393 }!
394
395 assert p_table[2].children[0].name == 'Sophia'
396}
397
398@[table: 'customers']
399struct Customer {
400 id i64 @[primary; sql: serial]
401 name string
402}
403
404fn test_i64_primary_field_works_with_insertions_of_id_0() {
405 db := sqlite.connect(':memory:')!
406 sql db {
407 create table Customer
408 }!
409 for i in ['Bob', 'Charlie'] {
410 new_customer := Customer{
411 name: i
412 }
413 sql db {
414 insert new_customer into Customer
415 }!
416 }
417 users := sql db {
418 select from Customer
419 }!
420 assert users.len == 2
421 // println("${users}")
422}
423
424struct Address {
425 id i64 @[primary; sql: serial]
426 street string
427 number int
428}
429
430fn test_the_result_of_insert_should_be_the_last_insert_id() {
431 db := sqlite.connect(':memory:')!
432 address := Address{
433 street: 'abc'
434 number: 123
435 }
436 dump(address)
437 sql db {
438 create table Address
439 } or {}
440 aid1 := sql db {
441 insert address into Address
442 } or { panic(err) }
443 dump(aid1)
444 assert aid1 == 1
445 aid2 := sql db {
446 insert address into Address
447 } or { panic(err) }
448 dump(aid2)
449 assert aid2 == 2
450 addresses := sql db {
451 select from Address
452 }!
453 dump(addresses)
454 assert addresses.len == 2
455 assert addresses.all(it.street == 'abc' && it.number == 123)
456}
457