v2 / vlib / db / sqlite / sqlite_orm_test.v
317 lines · 262 sloc · 6.72 KB · 5b55e6726af2225617f2c0ff782750a340bbe6be
Raw
1// vtest build: present_sqlite3?
2import orm
3import db.sqlite
4import time
5
6struct TestCustomSqlType {
7 id int @[primary; sql: serial]
8 custom string @[sql_type: 'INTEGER']
9 custom1 string @[sql_type: 'TEXT']
10 custom2 string @[sql_type: 'REAL']
11 custom3 string @[sql_type: 'NUMERIC']
12 custom4 string
13 custom5 int
14 custom6 time.Time
15}
16
17struct TestDefaultAttribute {
18 id string @[primary; sql: serial]
19 name string
20 created_at ?string @[default: 'CURRENT_TIME']
21 created_at1 ?string @[default: 'CURRENT_DATE']
22 created_at2 ?string @[default: 'CURRENT_TIMESTAMP']
23}
24
25struct TestDurationAlias {
26 id int @[primary; sql: serial]
27 duration time.Duration
28}
29
30struct EntityToTest {
31 id int @[notnull; sql_type: 'INTEGER']
32 smth string @[notnull; sql_type: 'TEXT']
33}
34
35struct TutorialBlogArticle {
36 id int @[primary; sql: serial]
37 title string
38 text string
39}
40
41struct TutorialBlogApp {
42mut:
43 db sqlite.DB
44}
45
46fn (app &TutorialBlogApp) find_all_tutorial_blog_articles() []TutorialBlogArticle {
47 return sql app.db {
48 select from TutorialBlogArticle
49 } or { panic(err) }
50}
51
52fn test_sqlite_orm() {
53 mut db := sqlite.connect(':memory:') or { panic(err) }
54 defer {
55 db.close() or { panic(err) }
56 }
57 table := orm.Table{
58 name: 'Test'
59 }
60 db.create(table, [
61 orm.TableField{
62 name: 'id'
63 typ: typeof[int]().idx
64 attrs: [
65 VAttribute{
66 name: 'primary'
67 },
68 VAttribute{
69 name: 'sql'
70 has_arg: true
71 kind: .plain
72 arg: 'serial'
73 },
74 ]
75 },
76 orm.TableField{
77 name: 'name'
78 typ: typeof[string]().idx
79 attrs: []
80 },
81 orm.TableField{
82 name: 'age'
83 typ: typeof[i64]().idx
84 },
85 ]) or { panic(err) }
86
87 db.insert(table, orm.QueryData{
88 fields: ['name', 'age']
89 data: [orm.string_to_primitive('Louis'), orm.i64_to_primitive(100)]
90 }) or { panic(err) }
91
92 res := db.select(orm.SelectConfig{
93 table: table
94 has_where: true
95 fields: ['id', 'name', 'age']
96 types: [typeof[int]().idx, typeof[string]().idx, typeof[i64]().idx]
97 }, orm.QueryData{}, orm.QueryData{
98 fields: ['name', 'age']
99 data: [orm.Primitive('Louis'), i64(100)]
100 types: [typeof[string]().idx, typeof[i64]().idx]
101 is_and: [true, true]
102 kinds: [.eq, .eq]
103 }) or { panic(err) }
104
105 id := res[0][0]
106 name := res[0][1]
107 age := res[0][2]
108
109 assert id is int
110 if id is int {
111 assert id == 1
112 }
113
114 assert name is string
115 if name is string {
116 assert name == 'Louis'
117 }
118
119 assert age is i64
120 if age is i64 {
121 assert age == 100
122 }
123
124 /** test orm sql type
125 * - verify if all type create by attribute sql_type has created
126 */
127
128 sql db {
129 create table TestCustomSqlType
130 }!
131
132 mut result_custom_sql := db.exec('
133 pragma table_info(TestCustomSqlType);
134 ')!
135
136 mut table_info_types_results := []string{}
137 information_schema_custom_sql := ['INTEGER', 'INTEGER', 'TEXT', 'REAL', 'NUMERIC', 'TEXT',
138 'INTEGER', 'INTEGER']
139
140 for data_type in result_custom_sql {
141 table_info_types_results << data_type.vals[2]
142 }
143 assert table_info_types_results == information_schema_custom_sql
144
145 sql db {
146 drop table TestCustomSqlType
147 }!
148
149 /** test default attribute
150 */
151
152 sql db {
153 create table TestDefaultAttribute
154 }!
155
156 mut result_default_sql := db.exec('
157 pragma table_info(TestDefaultAttribute);
158 ')!
159
160 mut information_schema_data_types_results := []string{}
161 information_schema_default_sql := ['', '', 'CURRENT_TIME', 'CURRENT_DATE', 'CURRENT_TIMESTAMP']
162
163 for data_type in result_default_sql {
164 information_schema_data_types_results << data_type.vals[4]
165 }
166 assert information_schema_data_types_results == information_schema_default_sql
167
168 test_default_attribute := TestDefaultAttribute{
169 name: 'Hitalo'
170 }
171
172 sql db {
173 insert test_default_attribute into TestDefaultAttribute
174 }!
175
176 test_default_attributes := sql db {
177 select from TestDefaultAttribute limit 1
178 }!
179
180 result_test_default_attribute := test_default_attributes.first()
181 assert result_test_default_attribute.name == 'Hitalo'
182 assert test_default_attribute.created_at or { '' } == ''
183 assert test_default_attribute.created_at1 or { '' } == ''
184 assert test_default_attribute.created_at2 or { '' } == ''
185 assert result_test_default_attribute.created_at or { '' }.len == 8 // HH:MM:SS
186 assert result_test_default_attribute.created_at1 or { '' }.len == 10 // YYYY-MM-DD
187 assert result_test_default_attribute.created_at2 or { '' }.len == 19 // YYYY-MM-DD HH:MM:SS
188
189 sql db {
190 drop table TestDefaultAttribute
191 }!
192}
193
194fn test_get_affected_rows_count() {
195 mut db := sqlite.connect(':memory:') or { panic(err) }
196 defer {
197 db.close() or { panic(err) }
198 }
199
200 db.exec('create table EntityToTest(
201 id integer not null constraint tbl_pk primary key,
202 smth integer
203 );')!
204
205 fst := EntityToTest{
206 id: 1
207 smth: '1'
208 }
209
210 sql db {
211 insert fst into EntityToTest
212 } or { panic('first insert failed') }
213
214 assert db.get_affected_rows_count() == 1
215
216 snd := EntityToTest{
217 id: 1
218 smth: '2'
219 }
220
221 mut sndfailed := false
222 sql db {
223 insert snd into EntityToTest
224 } or { sndfailed = true }
225
226 assert db.get_affected_rows_count() == 0
227 assert sndfailed
228
229 all := sql db {
230 select from EntityToTest
231 }!
232 assert 1 == all.len
233
234 sql db {
235 update EntityToTest set smth = '2' where id == 1
236 }!
237 assert db.get_affected_rows_count() == 1
238
239 sql db {
240 update EntityToTest set smth = '2' where id == 2
241 }!
242 assert db.get_affected_rows_count() == 0
243
244 sql db {
245 delete from EntityToTest where id == 2
246 }!
247 assert db.get_affected_rows_count() == 0
248
249 sql db {
250 delete from EntityToTest where id == 1
251 }!
252 assert db.get_affected_rows_count() == 1
253}
254
255fn test_sqlite_orm_supports_time_duration_alias_fields() {
256 mut db := sqlite.connect(':memory:') or { panic(err) }
257 defer {
258 db.close() or { panic(err) }
259 }
260
261 sql db {
262 create table TestDurationAlias
263 }!
264
265 result := db.exec('pragma table_info(TestDurationAlias);')!
266 assert result.len == 2
267 assert result[1].vals[1] == 'duration'
268 assert result[1].vals[2] == 'INTEGER'
269
270 record := TestDurationAlias{
271 duration: 3 * time.second
272 }
273
274 sql db {
275 insert record into TestDurationAlias
276 }!
277
278 rows := sql db {
279 select from TestDurationAlias limit 1
280 }!
281 assert rows.len == 1
282 assert rows[0].duration == 3 * time.second
283}
284
285fn test_sqlite_orm_tutorial_style_select_method() {
286 mut app := TutorialBlogApp{
287 db: sqlite.connect(':memory:') or { panic(err) }
288 }
289 defer {
290 app.db.close() or { panic(err) }
291 }
292
293 sql app.db {
294 create table TutorialBlogArticle
295 }!
296
297 first_article := TutorialBlogArticle{
298 title: 'Hello, world!'
299 text: 'V is great.'
300 }
301 second_article := TutorialBlogArticle{
302 title: 'Second post.'
303 text: 'Hm... what should I write about?'
304 }
305
306 sql app.db {
307 insert first_article into TutorialBlogArticle
308 insert second_article into TutorialBlogArticle
309 }!
310
311 articles := app.find_all_tutorial_blog_articles()
312 assert articles.len == 2
313
314 mut titles := articles.map(it.title)
315 titles.sort()
316 assert titles == ['Hello, world!', 'Second post.']
317}
318