v / vlib / orm / orm_test.v
550 lines · 437 sloc · 9.8 KB · b469eb9fa3b7b06a5b47a2d1203296fea8ef479a
Raw
1// vtest retry: 3
2// vtest build: present_sqlite3? && !windows
3// import db.mysql
4// import db.pg
5import orm
6import time
7import db.sqlite
8
9const offset_const = 2
10
11@[index: 'name, nr_downloads']
12struct Module {
13 id int @[primary; sql: serial]
14 name string @[index]
15 nr_downloads int
16 test_id u64 @[index]
17 user ?User
18 created time.Time
19}
20
21@[table: 'userlist']
22struct User {
23 id int @[primary; sql: serial]
24 age int
25 name string @[default: 'name'; sql: 'username']
26 is_customer bool
27 skipped_string string @[skip]
28 skipped_string2 string @[sql: '-']
29 skipped_array []string @[skip]
30 skipped_array2 []string @[sql: '-']
31}
32
33struct Foo {
34 age int
35}
36
37struct TestTime {
38 id int @[primary; sql: serial]
39 create time.Time
40}
41
42struct SelectTransformUser {
43 id int @[primary; sql: serial]
44 name string @[sql_select: 'upper(name)']
45}
46
47fn test_use_struct_field_as_limit() {
48 db := sqlite.connect(':memory:') or { panic(err) }
49
50 sql db {
51 create table User
52 }!
53
54 foo := Foo{
55 age: 10
56 }
57
58 sam := User{
59 age: 29
60 name: 'Sam'
61 skipped_string2: 'this should be ignored'
62 skipped_array: ['ignored', 'array']
63 skipped_array2: ['another', 'ignored', 'array']
64 }
65
66 sql db {
67 insert sam into User
68 }!
69
70 users := sql db {
71 select from User limit foo.age
72 }!
73
74 assert users.len == 1
75 assert users[0].name == 'Sam'
76 assert users[0].age == 29
77 assert users[0].skipped_string == ''
78 assert users[0].skipped_string2 == ''
79 assert users[0].skipped_array == [], 'skipped because of the @[skip] tag, used for both sql and json'
80 assert users[0].skipped_array2 == [], "should be skipped, because of the sql specific @[sql: '-'] tag"
81}
82
83fn test_orm_sql_select_attribute() {
84 mut db := sqlite.connect(':memory:') or { panic(err) }
85 defer {
86 db.close() or {}
87 }
88
89 sql db {
90 create table SelectTransformUser
91 }!
92
93 alice := SelectTransformUser{
94 name: 'Alice'
95 }
96
97 sql db {
98 insert alice into SelectTransformUser
99 }!
100
101 rows := sql db {
102 select from SelectTransformUser where id == 1
103 }!
104
105 assert rows.len == 1
106 assert rows[0].name == 'ALICE'
107
108 mut qb := orm.new_query[SelectTransformUser](db)
109 qb_rows := qb.query()!
110
111 assert qb_rows.len == 1
112 assert qb_rows[0].name == 'ALICE'
113}
114
115fn test_orm_select_specific_fields() {
116 mut db := sqlite.connect(':memory:') or { panic(err) }
117 defer {
118 db.close() or {}
119 }
120
121 sql db {
122 create table User
123 create table SelectTransformUser
124 }!
125
126 sam := User{
127 age: 29
128 name: 'Sam'
129 }
130 alice := SelectTransformUser{
131 name: 'Alice'
132 }
133
134 sql db {
135 insert sam into User
136 insert alice into SelectTransformUser
137 }!
138
139 users := sql db {
140 select id, name from User where name == 'Sam'
141 }!
142
143 assert users.len == 1
144 assert users[0].id == 1
145 assert users[0].name == 'Sam'
146 assert users[0].age == 0
147 assert users[0].is_customer == false
148
149 transformed := sql db {
150 select name from SelectTransformUser where id == 1
151 }!
152
153 assert transformed.len == 1
154 assert transformed[0].name == 'ALICE'
155 assert transformed[0].id == 0
156}
157
158fn test_orm_order_by_explicit_asc() {
159 mut db := sqlite.connect(':memory:')!
160 defer {
161 db.close() or { panic(err) }
162 }
163
164 sql db {
165 create table User
166 }!
167
168 users := [
169 User{
170 age: 31
171 name: 'Alice'
172 },
173 User{
174 age: 19
175 name: 'Bob'
176 },
177 User{
178 age: 44
179 name: 'Charlie'
180 },
181 ]
182
183 for user in users {
184 sql db {
185 insert user into User
186 }!
187 }
188
189 // vfmt off
190 rows := sql db {
191 select from User order by age asc limit 2
192 }!
193 // vfmt on
194
195 assert rows.len == 2
196 assert rows[0].name == 'Bob'
197 assert rows[0].age == 19
198 assert rows[1].name == 'Alice'
199 assert rows[1].age == 31
200}
201
202fn test_orm() {
203 db := sqlite.connect(':memory:') or { panic(err) }
204
205 sql db {
206 create table Module
207 }!
208 sql db {
209 create table User
210 }!
211
212 name := 'Peter'
213
214 sam := User{
215 age: 29
216 name: 'Sam'
217 }
218
219 peter := User{
220 age: 31
221 name: 'Peter'
222 }
223
224 k := User{
225 age: 30
226 name: 'Kate'
227 is_customer: true
228 }
229
230 sql db {
231 insert sam into User
232 insert peter into User
233 insert k into User
234 }!
235
236 c := sql db {
237 select count from User where id != 1
238 }!
239 assert c == 2
240
241 nr_all_users := sql db {
242 select count from User
243 }!
244 assert nr_all_users == 3
245
246 nr_users1 := sql db {
247 select count from User where id == 1
248 }!
249 assert nr_users1 == 1
250
251 nr_peters := sql db {
252 select count from User where id == 2 && name == 'Peter'
253 }!
254 assert nr_peters == 1
255
256 nr_peters2 := sql db {
257 select count from User where id == 2 && name == name
258 }!
259 assert nr_peters2 == 1
260
261 nr_peters3 := sql db {
262 select count from User where name == name
263 }!
264 assert nr_peters3 == 1
265
266 peters := sql db {
267 select from User where name == name
268 }!
269 assert peters.len == 1
270 assert peters[0].name == 'Peter'
271
272 mut users := sql db {
273 select from User where name == name limit 1
274 }!
275
276 one_peter := users.first()
277 assert one_peter.name == 'Peter'
278 assert one_peter.id == 2
279
280 users = sql db {
281 select from User where id == 1
282 }!
283
284 user := users.first()
285 assert user.name == 'Sam'
286 assert user.id == 1
287 assert user.age == 29
288
289 users = sql db {
290 select from User where id > 0
291 }!
292 assert users.len == 3
293 assert users[0].name == 'Sam'
294 assert users[1].name == 'Peter'
295 assert users[1].age == 31
296
297 users2 := sql db {
298 select from User where id < 0
299 }!
300 assert users2.len == 0
301
302 users3 := sql db {
303 select from User where age == 29 || age == 31
304 }!
305
306 assert users3.len == 2
307 assert users3[0].age == 29
308 assert users3[1].age == 31
309
310 new_user := User{
311 name: 'New user'
312 age: 30
313 }
314 sql db {
315 insert new_user into User
316 }!
317
318 users = sql db {
319 select from User where id == 4
320 }!
321
322 x := users.first()
323 assert x.age == 30
324 assert x.id == 4
325 assert x.name == 'New user'
326
327 users = sql db {
328 select from User where id == 3
329 }!
330
331 kate := users.first()
332 assert kate.is_customer == true
333
334 users = sql db {
335 select from User where is_customer == true limit 1
336 }!
337
338 customer := users.first()
339 assert customer.is_customer == true
340 assert customer.name == 'Kate'
341
342 sql db {
343 update User set age = 31 where name == 'Kate'
344 }!
345
346 users = sql db {
347 select from User where id == 3
348 }!
349 kate2 := users.first()
350 assert kate2.age == 31
351 assert kate2.name == 'Kate'
352
353 sql db {
354 update User set age = 32, name = 'Kate N' where name == 'Kate'
355 }!
356
357 users = sql db {
358 select from User where id == 3
359 }!
360 mut kate3 := users.first()
361 assert kate3.age == 32
362 assert kate3.name == 'Kate N'
363
364 new_age := 33
365 sql db {
366 update User set age = new_age, name = 'Kate N' where id == 3
367 }!
368
369 users = sql db {
370 select from User where id == 3
371 }!
372
373 kate3 = users.first()
374 assert kate3.age == 33
375 assert kate3.name == 'Kate N'
376
377 foo := Foo{34}
378 sql db {
379 update User set age = foo.age, name = 'Kate N' where id == 3
380 }!
381
382 users = sql db {
383 select from User where id == 3
384 }!
385 kate3 = users.first()
386 assert kate3.age == 34
387 assert kate3.name == 'Kate N'
388
389 no_user := sql db {
390 select from User where id == 30
391 }!
392
393 assert no_user.len == 0
394
395 two_users := sql db {
396 select from User limit 2
397 }!
398 assert two_users.len == 2
399 assert two_users[0].id == 1
400
401 y := sql db {
402 select from User limit 2 offset 1
403 }!
404 assert y.len == 2
405 assert y[0].id == 2
406
407 z := sql db {
408 select from User order by id limit 2 offset offset_const
409 }!
410 assert z.len == 2
411 assert z[0].id == 3
412
413 users = sql db {
414 select from User order by age desc limit 1
415 }!
416
417 oldest := users.first()
418 assert oldest.age == 34
419
420 offs := 1
421 users = sql db {
422 select from User order by age desc limit 1 offset offs
423 }!
424
425 second_oldest := users.first()
426 assert second_oldest.age == 31
427 sql db {
428 delete from User where age == 34
429 }!
430
431 users = sql db {
432 select from User order by age desc limit 1
433 }!
434 updated_oldest := users.first()
435 assert updated_oldest.age == 31
436
437 // Remove this when pg is used
438 // db.exec('insert into User (name, age) values (NULL, 31)')
439 users = sql db {
440 select from User where id == 5
441 }!
442 assert users.len == 0
443
444 users = sql db {
445 select from User where id == 1
446 }!
447 age_test := users.first()
448
449 assert age_test.age == 29
450
451 sql db {
452 update User set age = age + 1 where id == 1
453 }!
454
455 users = sql db {
456 select from User where id == 1
457 }!
458
459 mut first := users.first()
460 assert first.age == 30
461
462 sql db {
463 update User set age = age * 2 where id == 1
464 }!
465
466 users = sql db {
467 select from User where id == 1
468 }!
469
470 first = users.first()
471 assert first.age == 60
472
473 sql db {
474 create table TestTime
475 }!
476
477 tnow := time.now()
478
479 time_test := TestTime{
480 create: tnow
481 }
482
483 sql db {
484 insert time_test into TestTime
485 }!
486
487 data := sql db {
488 select from TestTime where create == tnow
489 }!
490
491 assert data.len == 1
492 assert tnow.unix() == data[0].create.unix()
493
494 mod := Module{}
495
496 sql db {
497 insert mod into Module
498 }!
499
500 sql db {
501 update Module set test_id = 11 where id == 1
502 }!
503
504 mut modules := sql db {
505 select from Module where id == 1
506 }!
507
508 assert modules.first().test_id == 11
509
510 t := time.now()
511 sql db {
512 update Module set created = t where id == 1
513 }!
514
515 modules = sql db {
516 select from Module where id == 1
517 }!
518
519 // Note: usually updated_time_mod.created != t, because t has
520 // its microseconds set, while the value retrieved from the DB
521 // has them zeroed, because the db field resolution is seconds.
522 // Note: the database also stores the time in UTC, so the
523 // comparison must be done on the unix timestamp.
524 assert modules.first().created.unix() == t.unix()
525
526 users = sql db {
527 select from User where (name == 'Sam' && is_customer == true) || id == 1
528 }!
529
530 assert users.first() == first
531
532 sql db {
533 drop table Module
534 drop table TestTime
535 }!
536}
537
538fn test_distinct() {
539 db := sqlite.connect(':memory:') or { panic(err) }
540
541 // Create table without unique constraints to allow true duplicates
542 db.exec('CREATE TABLE items (name TEXT, category TEXT)')!
543 db.exec("INSERT INTO items VALUES ('Apple', 'Fruit'), ('Apple', 'Fruit'), ('Banana', 'Fruit')")!
544
545 without_distinct := db.exec('SELECT name, category FROM items')!
546 assert without_distinct.len == 3
547
548 with_distinct := db.exec('SELECT DISTINCT name, category FROM items')!
549 assert with_distinct.len == 2
550}
551