@@ -6,12 +6,16 @@ package tags
6
6
7
7
import (
8
8
"reflect"
9
+ "strings"
9
10
"testing"
11
+ "time"
10
12
11
- "github.com/stretchr/testify/assert"
12
13
"xorm.io/xorm/caches"
13
14
"xorm.io/xorm/dialects"
14
15
"xorm.io/xorm/names"
16
+ "xorm.io/xorm/schemas"
17
+
18
+ "github.com/stretchr/testify/assert"
15
19
)
16
20
17
21
type ParseTableName1 struct {}
@@ -80,21 +84,469 @@ func TestParseWithOtherIdentifier(t *testing.T) {
80
84
parser := NewParser (
81
85
"xorm" ,
82
86
dialects .QueryDialect ("mysql" ),
83
- names.GonicMapper {},
87
+ names.SameMapper {},
84
88
names.SnakeMapper {},
85
89
caches .NewManager (),
86
90
)
87
91
88
92
type StructWithDBTag struct {
89
93
FieldFoo string `db:"foo"`
90
94
}
95
+
91
96
parser .SetIdentifier ("db" )
92
97
table , err := parser .Parse (reflect .ValueOf (new (StructWithDBTag )))
93
98
assert .NoError (t , err )
94
- assert .EqualValues (t , "struct_with_db_tag " , table .Name )
99
+ assert .EqualValues (t , "StructWithDBTag " , table .Name )
95
100
assert .EqualValues (t , 1 , len (table .Columns ()))
96
101
97
102
for _ , col := range table .Columns () {
98
103
assert .EqualValues (t , "foo" , col .Name )
99
104
}
100
105
}
106
+
107
+ func TestParseWithIgnore (t * testing.T ) {
108
+ parser := NewParser (
109
+ "db" ,
110
+ dialects .QueryDialect ("mysql" ),
111
+ names.SameMapper {},
112
+ names.SnakeMapper {},
113
+ caches .NewManager (),
114
+ )
115
+
116
+ type StructWithIgnoreTag struct {
117
+ FieldFoo string `db:"-"`
118
+ }
119
+
120
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithIgnoreTag )))
121
+ assert .NoError (t , err )
122
+ assert .EqualValues (t , "StructWithIgnoreTag" , table .Name )
123
+ assert .EqualValues (t , 0 , len (table .Columns ()))
124
+ }
125
+
126
+ func TestParseWithAutoincrement (t * testing.T ) {
127
+ parser := NewParser (
128
+ "db" ,
129
+ dialects .QueryDialect ("mysql" ),
130
+ names.SnakeMapper {},
131
+ names.GonicMapper {},
132
+ caches .NewManager (),
133
+ )
134
+
135
+ type StructWithAutoIncrement struct {
136
+ ID int64
137
+ }
138
+
139
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithAutoIncrement )))
140
+ assert .NoError (t , err )
141
+ assert .EqualValues (t , "struct_with_auto_increment" , table .Name )
142
+ assert .EqualValues (t , 1 , len (table .Columns ()))
143
+ assert .EqualValues (t , "id" , table .Columns ()[0 ].Name )
144
+ assert .True (t , table .Columns ()[0 ].IsAutoIncrement )
145
+ assert .True (t , table .Columns ()[0 ].IsPrimaryKey )
146
+ }
147
+
148
+ func TestParseWithAutoincrement2 (t * testing.T ) {
149
+ parser := NewParser (
150
+ "db" ,
151
+ dialects .QueryDialect ("mysql" ),
152
+ names.SnakeMapper {},
153
+ names.GonicMapper {},
154
+ caches .NewManager (),
155
+ )
156
+
157
+ type StructWithAutoIncrement2 struct {
158
+ ID int64 `db:"pk autoincr"`
159
+ }
160
+
161
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithAutoIncrement2 )))
162
+ assert .NoError (t , err )
163
+ assert .EqualValues (t , "struct_with_auto_increment2" , table .Name )
164
+ assert .EqualValues (t , 1 , len (table .Columns ()))
165
+ assert .EqualValues (t , "id" , table .Columns ()[0 ].Name )
166
+ assert .True (t , table .Columns ()[0 ].IsAutoIncrement )
167
+ assert .True (t , table .Columns ()[0 ].IsPrimaryKey )
168
+ assert .False (t , table .Columns ()[0 ].Nullable )
169
+ }
170
+
171
+ func TestParseWithNullable (t * testing.T ) {
172
+ parser := NewParser (
173
+ "db" ,
174
+ dialects .QueryDialect ("mysql" ),
175
+ names.SnakeMapper {},
176
+ names.GonicMapper {},
177
+ caches .NewManager (),
178
+ )
179
+
180
+ type StructWithNullable struct {
181
+ Name string `db:"notnull"`
182
+ FullName string `db:"null comment('column comment,字段注释')"`
183
+ }
184
+
185
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithNullable )))
186
+ assert .NoError (t , err )
187
+ assert .EqualValues (t , "struct_with_nullable" , table .Name )
188
+ assert .EqualValues (t , 2 , len (table .Columns ()))
189
+ assert .EqualValues (t , "name" , table .Columns ()[0 ].Name )
190
+ assert .EqualValues (t , "full_name" , table .Columns ()[1 ].Name )
191
+ assert .False (t , table .Columns ()[0 ].Nullable )
192
+ assert .True (t , table .Columns ()[1 ].Nullable )
193
+ assert .EqualValues (t , "column comment,字段注释" , table .Columns ()[1 ].Comment )
194
+ }
195
+
196
+ func TestParseWithTimes (t * testing.T ) {
197
+ parser := NewParser (
198
+ "db" ,
199
+ dialects .QueryDialect ("mysql" ),
200
+ names.SnakeMapper {},
201
+ names.GonicMapper {},
202
+ caches .NewManager (),
203
+ )
204
+
205
+ type StructWithTimes struct {
206
+ Name string `db:"notnull"`
207
+ CreatedAt time.Time `db:"created"`
208
+ UpdatedAt time.Time `db:"updated"`
209
+ DeletedAt time.Time `db:"deleted"`
210
+ }
211
+
212
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithTimes )))
213
+ assert .NoError (t , err )
214
+ assert .EqualValues (t , "struct_with_times" , table .Name )
215
+ assert .EqualValues (t , 4 , len (table .Columns ()))
216
+ assert .EqualValues (t , "name" , table .Columns ()[0 ].Name )
217
+ assert .EqualValues (t , "created_at" , table .Columns ()[1 ].Name )
218
+ assert .EqualValues (t , "updated_at" , table .Columns ()[2 ].Name )
219
+ assert .EqualValues (t , "deleted_at" , table .Columns ()[3 ].Name )
220
+ assert .False (t , table .Columns ()[0 ].Nullable )
221
+ assert .True (t , table .Columns ()[1 ].Nullable )
222
+ assert .True (t , table .Columns ()[1 ].IsCreated )
223
+ assert .True (t , table .Columns ()[2 ].Nullable )
224
+ assert .True (t , table .Columns ()[2 ].IsUpdated )
225
+ assert .True (t , table .Columns ()[3 ].Nullable )
226
+ assert .True (t , table .Columns ()[3 ].IsDeleted )
227
+ }
228
+
229
+ func TestParseWithExtends (t * testing.T ) {
230
+ parser := NewParser (
231
+ "db" ,
232
+ dialects .QueryDialect ("mysql" ),
233
+ names.SnakeMapper {},
234
+ names.GonicMapper {},
235
+ caches .NewManager (),
236
+ )
237
+
238
+ type StructWithEmbed struct {
239
+ Name string
240
+ CreatedAt time.Time `db:"created"`
241
+ UpdatedAt time.Time `db:"updated"`
242
+ DeletedAt time.Time `db:"deleted"`
243
+ }
244
+
245
+ type StructWithExtends struct {
246
+ SW StructWithEmbed `db:"extends"`
247
+ }
248
+
249
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithExtends )))
250
+ assert .NoError (t , err )
251
+ assert .EqualValues (t , "struct_with_extends" , table .Name )
252
+ assert .EqualValues (t , 4 , len (table .Columns ()))
253
+ assert .EqualValues (t , "name" , table .Columns ()[0 ].Name )
254
+ assert .EqualValues (t , "created_at" , table .Columns ()[1 ].Name )
255
+ assert .EqualValues (t , "updated_at" , table .Columns ()[2 ].Name )
256
+ assert .EqualValues (t , "deleted_at" , table .Columns ()[3 ].Name )
257
+ assert .True (t , table .Columns ()[0 ].Nullable )
258
+ assert .True (t , table .Columns ()[1 ].Nullable )
259
+ assert .True (t , table .Columns ()[1 ].IsCreated )
260
+ assert .True (t , table .Columns ()[2 ].Nullable )
261
+ assert .True (t , table .Columns ()[2 ].IsUpdated )
262
+ assert .True (t , table .Columns ()[3 ].Nullable )
263
+ assert .True (t , table .Columns ()[3 ].IsDeleted )
264
+ }
265
+
266
+ func TestParseWithCache (t * testing.T ) {
267
+ parser := NewParser (
268
+ "db" ,
269
+ dialects .QueryDialect ("mysql" ),
270
+ names.SnakeMapper {},
271
+ names.GonicMapper {},
272
+ caches .NewManager (),
273
+ )
274
+
275
+ type StructWithCache struct {
276
+ Name string `db:"cache"`
277
+ }
278
+
279
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithCache )))
280
+ assert .NoError (t , err )
281
+ assert .EqualValues (t , "struct_with_cache" , table .Name )
282
+ assert .EqualValues (t , 1 , len (table .Columns ()))
283
+ assert .EqualValues (t , "name" , table .Columns ()[0 ].Name )
284
+ assert .True (t , table .Columns ()[0 ].Nullable )
285
+ cacher := parser .cacherMgr .GetCacher (table .Name )
286
+ assert .NotNil (t , cacher )
287
+ }
288
+
289
+ func TestParseWithNoCache (t * testing.T ) {
290
+ parser := NewParser (
291
+ "db" ,
292
+ dialects .QueryDialect ("mysql" ),
293
+ names.SnakeMapper {},
294
+ names.GonicMapper {},
295
+ caches .NewManager (),
296
+ )
297
+
298
+ type StructWithNoCache struct {
299
+ Name string `db:"nocache"`
300
+ }
301
+
302
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithNoCache )))
303
+ assert .NoError (t , err )
304
+ assert .EqualValues (t , "struct_with_no_cache" , table .Name )
305
+ assert .EqualValues (t , 1 , len (table .Columns ()))
306
+ assert .EqualValues (t , "name" , table .Columns ()[0 ].Name )
307
+ assert .True (t , table .Columns ()[0 ].Nullable )
308
+ cacher := parser .cacherMgr .GetCacher (table .Name )
309
+ assert .Nil (t , cacher )
310
+ }
311
+
312
+ func TestParseWithEnum (t * testing.T ) {
313
+ parser := NewParser (
314
+ "db" ,
315
+ dialects .QueryDialect ("mysql" ),
316
+ names.SnakeMapper {},
317
+ names.GonicMapper {},
318
+ caches .NewManager (),
319
+ )
320
+
321
+ type StructWithEnum struct {
322
+ Name string `db:"enum('alice', 'bob')"`
323
+ }
324
+
325
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithEnum )))
326
+ assert .NoError (t , err )
327
+ assert .EqualValues (t , "struct_with_enum" , table .Name )
328
+ assert .EqualValues (t , 1 , len (table .Columns ()))
329
+ assert .EqualValues (t , "name" , table .Columns ()[0 ].Name )
330
+ assert .True (t , table .Columns ()[0 ].Nullable )
331
+ assert .EqualValues (t , schemas .Enum , strings .ToUpper (table .Columns ()[0 ].SQLType .Name ))
332
+ assert .EqualValues (t , map [string ]int {
333
+ "alice" : 0 ,
334
+ "bob" : 1 ,
335
+ }, table .Columns ()[0 ].EnumOptions )
336
+ }
337
+
338
+ func TestParseWithSet (t * testing.T ) {
339
+ parser := NewParser (
340
+ "db" ,
341
+ dialects .QueryDialect ("mysql" ),
342
+ names.SnakeMapper {},
343
+ names.GonicMapper {},
344
+ caches .NewManager (),
345
+ )
346
+
347
+ type StructWithSet struct {
348
+ Name string `db:"set('alice', 'bob')"`
349
+ }
350
+
351
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithSet )))
352
+ assert .NoError (t , err )
353
+ assert .EqualValues (t , "struct_with_set" , table .Name )
354
+ assert .EqualValues (t , 1 , len (table .Columns ()))
355
+ assert .EqualValues (t , "name" , table .Columns ()[0 ].Name )
356
+ assert .True (t , table .Columns ()[0 ].Nullable )
357
+ assert .EqualValues (t , schemas .Set , strings .ToUpper (table .Columns ()[0 ].SQLType .Name ))
358
+ assert .EqualValues (t , map [string ]int {
359
+ "alice" : 0 ,
360
+ "bob" : 1 ,
361
+ }, table .Columns ()[0 ].SetOptions )
362
+ }
363
+
364
+ func TestParseWithIndex (t * testing.T ) {
365
+ parser := NewParser (
366
+ "db" ,
367
+ dialects .QueryDialect ("mysql" ),
368
+ names.SnakeMapper {},
369
+ names.GonicMapper {},
370
+ caches .NewManager (),
371
+ )
372
+
373
+ type StructWithIndex struct {
374
+ Name string `db:"index"`
375
+ Name2 string `db:"index(s)"`
376
+ Name3 string `db:"unique"`
377
+ }
378
+
379
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithIndex )))
380
+ assert .NoError (t , err )
381
+ assert .EqualValues (t , "struct_with_index" , table .Name )
382
+ assert .EqualValues (t , 3 , len (table .Columns ()))
383
+ assert .EqualValues (t , "name" , table .Columns ()[0 ].Name )
384
+ assert .EqualValues (t , "name2" , table .Columns ()[1 ].Name )
385
+ assert .EqualValues (t , "name3" , table .Columns ()[2 ].Name )
386
+ assert .True (t , table .Columns ()[0 ].Nullable )
387
+ assert .True (t , table .Columns ()[1 ].Nullable )
388
+ assert .True (t , table .Columns ()[2 ].Nullable )
389
+ assert .EqualValues (t , 1 , len (table .Columns ()[0 ].Indexes ))
390
+ assert .EqualValues (t , 1 , len (table .Columns ()[1 ].Indexes ))
391
+ assert .EqualValues (t , 1 , len (table .Columns ()[2 ].Indexes ))
392
+ }
393
+
394
+ func TestParseWithVersion (t * testing.T ) {
395
+ parser := NewParser (
396
+ "db" ,
397
+ dialects .QueryDialect ("mysql" ),
398
+ names.SnakeMapper {},
399
+ names.GonicMapper {},
400
+ caches .NewManager (),
401
+ )
402
+
403
+ type StructWithVersion struct {
404
+ Name string
405
+ Version int `db:"version"`
406
+ }
407
+
408
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithVersion )))
409
+ assert .NoError (t , err )
410
+ assert .EqualValues (t , "struct_with_version" , table .Name )
411
+ assert .EqualValues (t , 2 , len (table .Columns ()))
412
+ assert .EqualValues (t , "name" , table .Columns ()[0 ].Name )
413
+ assert .EqualValues (t , "version" , table .Columns ()[1 ].Name )
414
+ assert .True (t , table .Columns ()[0 ].Nullable )
415
+ assert .True (t , table .Columns ()[1 ].Nullable )
416
+ assert .True (t , table .Columns ()[1 ].IsVersion )
417
+ }
418
+
419
+ func TestParseWithLocale (t * testing.T ) {
420
+ parser := NewParser (
421
+ "db" ,
422
+ dialects .QueryDialect ("mysql" ),
423
+ names.SnakeMapper {},
424
+ names.GonicMapper {},
425
+ caches .NewManager (),
426
+ )
427
+
428
+ type StructWithLocale struct {
429
+ UTCLocale time.Time `db:"utc"`
430
+ LocalLocale time.Time `db:"local"`
431
+ }
432
+
433
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithLocale )))
434
+ assert .NoError (t , err )
435
+ assert .EqualValues (t , "struct_with_locale" , table .Name )
436
+ assert .EqualValues (t , 2 , len (table .Columns ()))
437
+ assert .EqualValues (t , "utc_locale" , table .Columns ()[0 ].Name )
438
+ assert .EqualValues (t , "local_locale" , table .Columns ()[1 ].Name )
439
+ assert .EqualValues (t , time .UTC , table .Columns ()[0 ].TimeZone )
440
+ assert .EqualValues (t , time .Local , table .Columns ()[1 ].TimeZone )
441
+ }
442
+
443
+ func TestParseWithDefault (t * testing.T ) {
444
+ parser := NewParser (
445
+ "db" ,
446
+ dialects .QueryDialect ("mysql" ),
447
+ names.SnakeMapper {},
448
+ names.GonicMapper {},
449
+ caches .NewManager (),
450
+ )
451
+
452
+ type StructWithDefault struct {
453
+ Default1 time.Time `db:"default '1970-01-01 00:00:00'"`
454
+ Default2 time.Time `db:"default(CURRENT_TIMESTAMP)"`
455
+ }
456
+
457
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithDefault )))
458
+ assert .NoError (t , err )
459
+ assert .EqualValues (t , "struct_with_default" , table .Name )
460
+ assert .EqualValues (t , 2 , len (table .Columns ()))
461
+ assert .EqualValues (t , "default1" , table .Columns ()[0 ].Name )
462
+ assert .EqualValues (t , "default2" , table .Columns ()[1 ].Name )
463
+ assert .EqualValues (t , "'1970-01-01 00:00:00'" , table .Columns ()[0 ].Default )
464
+ assert .EqualValues (t , "CURRENT_TIMESTAMP" , table .Columns ()[1 ].Default )
465
+ }
466
+
467
+ func TestParseWithOnlyToDB (t * testing.T ) {
468
+ parser := NewParser (
469
+ "db" ,
470
+ dialects .QueryDialect ("mysql" ),
471
+ names.GonicMapper {
472
+ "DB" : true ,
473
+ },
474
+ names.SnakeMapper {},
475
+ caches .NewManager (),
476
+ )
477
+
478
+ type StructWithOnlyToDB struct {
479
+ Default1 time.Time `db:"->"`
480
+ Default2 time.Time `db:"<-"`
481
+ }
482
+
483
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithOnlyToDB )))
484
+ assert .NoError (t , err )
485
+ assert .EqualValues (t , "struct_with_only_to_db" , table .Name )
486
+ assert .EqualValues (t , 2 , len (table .Columns ()))
487
+ assert .EqualValues (t , "default1" , table .Columns ()[0 ].Name )
488
+ assert .EqualValues (t , "default2" , table .Columns ()[1 ].Name )
489
+ assert .EqualValues (t , schemas .ONLYTODB , table .Columns ()[0 ].MapType )
490
+ assert .EqualValues (t , schemas .ONLYFROMDB , table .Columns ()[1 ].MapType )
491
+ }
492
+
493
+ func TestParseWithJSON (t * testing.T ) {
494
+ parser := NewParser (
495
+ "db" ,
496
+ dialects .QueryDialect ("mysql" ),
497
+ names.GonicMapper {
498
+ "JSON" : true ,
499
+ },
500
+ names.SnakeMapper {},
501
+ caches .NewManager (),
502
+ )
503
+
504
+ type StructWithJSON struct {
505
+ Default1 []string `db:"json"`
506
+ }
507
+
508
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithJSON )))
509
+ assert .NoError (t , err )
510
+ assert .EqualValues (t , "struct_with_json" , table .Name )
511
+ assert .EqualValues (t , 1 , len (table .Columns ()))
512
+ assert .EqualValues (t , "default1" , table .Columns ()[0 ].Name )
513
+ assert .True (t , table .Columns ()[0 ].IsJSON )
514
+ }
515
+
516
+ func TestParseWithSQLType (t * testing.T ) {
517
+ parser := NewParser (
518
+ "db" ,
519
+ dialects .QueryDialect ("mysql" ),
520
+ names.GonicMapper {
521
+ "SQL" : true ,
522
+ },
523
+ names.GonicMapper {
524
+ "UUID" : true ,
525
+ },
526
+ caches .NewManager (),
527
+ )
528
+
529
+ type StructWithSQLType struct {
530
+ Col1 string `db:"varchar(32)"`
531
+ Col2 string `db:"char(32)"`
532
+ Int int64 `db:"bigint"`
533
+ DateTime time.Time `db:"datetime"`
534
+ UUID string `db:"uuid"`
535
+ }
536
+
537
+ table , err := parser .Parse (reflect .ValueOf (new (StructWithSQLType )))
538
+ assert .NoError (t , err )
539
+ assert .EqualValues (t , "struct_with_sql_type" , table .Name )
540
+ assert .EqualValues (t , 5 , len (table .Columns ()))
541
+ assert .EqualValues (t , "col1" , table .Columns ()[0 ].Name )
542
+ assert .EqualValues (t , "col2" , table .Columns ()[1 ].Name )
543
+ assert .EqualValues (t , "int" , table .Columns ()[2 ].Name )
544
+ assert .EqualValues (t , "date_time" , table .Columns ()[3 ].Name )
545
+ assert .EqualValues (t , "uuid" , table .Columns ()[4 ].Name )
546
+
547
+ assert .EqualValues (t , "VARCHAR" , table .Columns ()[0 ].SQLType .Name )
548
+ assert .EqualValues (t , "CHAR" , table .Columns ()[1 ].SQLType .Name )
549
+ assert .EqualValues (t , "BIGINT" , table .Columns ()[2 ].SQLType .Name )
550
+ assert .EqualValues (t , "DATETIME" , table .Columns ()[3 ].SQLType .Name )
551
+ assert .EqualValues (t , "UUID" , table .Columns ()[4 ].SQLType .Name )
552
+ }
0 commit comments