Skip to content
This repository was archived by the owner on Sep 7, 2021. It is now read-only.
This repository is currently being migrated. It's locked while the migration is in progress.

Commit 4c80660

Browse files
mskriplunny
authored andcommitted
Allow adding prefix for fields with extends tag (#1284)
Added new syntax like `extends('Prefix')` to enable matching all extended fields as 'PrefixFieldName'. Close #1270
1 parent f1b4f83 commit 4c80660

File tree

3 files changed

+150
-1
lines changed

3 files changed

+150
-1
lines changed

engine.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -923,7 +923,16 @@ func (engine *Engine) mapType(v reflect.Value) (*core.Table, error) {
923923
engine: engine,
924924
}
925925

926-
if strings.ToUpper(tags[0]) == "EXTENDS" {
926+
if strings.HasPrefix(strings.ToUpper(tags[0]), "EXTENDS") {
927+
pStart := strings.Index(tags[0], "(")
928+
if pStart > -1 && strings.HasSuffix(tags[0], ")") {
929+
var tagPrefix = strings.TrimFunc(tags[0][pStart+1:len(tags[0])-1], func(r rune) bool {
930+
return r == '\'' || r == '"'
931+
})
932+
933+
ctx.params = []string{tagPrefix}
934+
}
935+
927936
if err := ExtendsTagHandler(&ctx); err != nil {
928937
return nil, err
929938
}

tag.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ func SQLTypeTagHandler(ctx *tagContext) error {
244244
// ExtendsTagHandler describes extends tag handler
245245
func ExtendsTagHandler(ctx *tagContext) error {
246246
var fieldValue = ctx.fieldValue
247+
var isPtr = false
247248
switch fieldValue.Kind() {
248249
case reflect.Ptr:
249250
f := fieldValue.Type().Elem()
@@ -254,6 +255,7 @@ func ExtendsTagHandler(ctx *tagContext) error {
254255
fieldValue = reflect.New(f).Elem()
255256
}
256257
}
258+
isPtr = true
257259
fallthrough
258260
case reflect.Struct:
259261
parentTable, err := ctx.engine.mapType(fieldValue)
@@ -262,6 +264,24 @@ func ExtendsTagHandler(ctx *tagContext) error {
262264
}
263265
for _, col := range parentTable.Columns() {
264266
col.FieldName = fmt.Sprintf("%v.%v", ctx.col.FieldName, col.FieldName)
267+
268+
var tagPrefix = ctx.col.FieldName
269+
if len(ctx.params) > 0 {
270+
col.Nullable = isPtr
271+
tagPrefix = ctx.params[0]
272+
if col.IsPrimaryKey {
273+
col.Name = ctx.col.FieldName
274+
col.IsPrimaryKey = false
275+
} else {
276+
col.Name = fmt.Sprintf("%v%v", tagPrefix, col.Name)
277+
}
278+
}
279+
280+
if col.Nullable {
281+
col.IsAutoIncrement = false
282+
col.IsPrimaryKey = false
283+
}
284+
265285
ctx.table.AddColumn(col)
266286
for indexName, indexType := range col.Indexes {
267287
addIndex(indexName, ctx.table, col, indexType)

tag_extends_test.go

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,3 +486,123 @@ func TestExtends4(t *testing.T) {
486486
panic(err)
487487
}
488488
}
489+
490+
type Size struct {
491+
ID int64 `xorm:"int(4) 'id' pk autoincr"`
492+
Width float32 `json:"width" xorm:"float 'Width'"`
493+
Height float32 `json:"height" xorm:"float 'Height'"`
494+
}
495+
496+
type Book struct {
497+
ID int64 `xorm:"int(4) 'id' pk autoincr"`
498+
SizeOpen *Size `xorm:"extends('Open')"`
499+
SizeClosed *Size `xorm:"extends('Closed')"`
500+
Size *Size `xorm:"extends('')"`
501+
}
502+
503+
func TestExtends5(t *testing.T) {
504+
assert.NoError(t, prepareEngine())
505+
err := testEngine.DropTables(&Book{}, &Size{})
506+
if err != nil {
507+
t.Error(err)
508+
panic(err)
509+
}
510+
511+
err = testEngine.CreateTables(&Size{}, &Book{})
512+
if err != nil {
513+
t.Error(err)
514+
panic(err)
515+
}
516+
517+
var sc = Size{Width: 0.2, Height: 0.4}
518+
var so = Size{Width: 0.2, Height: 0.8}
519+
var s = Size{Width: 0.15, Height: 1.5}
520+
var bk1 = Book{
521+
SizeOpen: &so,
522+
SizeClosed: &sc,
523+
Size: &s,
524+
}
525+
var bk2 = Book{
526+
SizeOpen: &so,
527+
}
528+
var bk3 = Book{
529+
SizeClosed: &sc,
530+
Size: &s,
531+
}
532+
var bk4 = Book{}
533+
var bk5 = Book{Size: &s}
534+
_, err = testEngine.Insert(&sc, &so, &s, &bk1, &bk2, &bk3, &bk4, &bk5)
535+
if err != nil {
536+
t.Fatal(err)
537+
}
538+
539+
var books = map[int64]Book{
540+
bk1.ID: bk1,
541+
bk2.ID: bk2,
542+
bk3.ID: bk3,
543+
bk4.ID: bk4,
544+
bk5.ID: bk5,
545+
}
546+
547+
session := testEngine.NewSession()
548+
defer session.Close()
549+
550+
var mapper = testEngine.GetTableMapper().Obj2Table
551+
var quote = testEngine.Quote
552+
bookTableName := quote(testEngine.TableName(mapper("Book"), true))
553+
sizeTableName := quote(testEngine.TableName(mapper("Size"), true))
554+
555+
list := make([]Book, 0)
556+
err = session.
557+
Select(fmt.Sprintf(
558+
"%s.%s, sc.%s AS %s, sc.%s AS %s, s.%s, s.%s",
559+
quote(bookTableName),
560+
quote("id"),
561+
quote("Width"),
562+
quote("ClosedWidth"),
563+
quote("Height"),
564+
quote("ClosedHeight"),
565+
quote("Width"),
566+
quote("Height"),
567+
)).
568+
Table(bookTableName).
569+
Join(
570+
"LEFT",
571+
sizeTableName+" AS `sc`",
572+
bookTableName+".`SizeClosed`=sc.`id`",
573+
).
574+
Join(
575+
"LEFT",
576+
sizeTableName+" AS `s`",
577+
bookTableName+".`Size`=s.`id`",
578+
).
579+
Find(&list)
580+
if err != nil {
581+
t.Error(err)
582+
panic(err)
583+
}
584+
585+
for _, book := range list {
586+
if ok := assert.Equal(t, books[book.ID].SizeClosed.Width, book.SizeClosed.Width); !ok {
587+
t.Error("Not bounded size closed")
588+
panic("Not bounded size closed")
589+
}
590+
591+
if ok := assert.Equal(t, books[book.ID].SizeClosed.Height, book.SizeClosed.Height); !ok {
592+
t.Error("Not bounded size closed")
593+
panic("Not bounded size closed")
594+
}
595+
596+
if books[book.ID].Size != nil || book.Size != nil {
597+
if ok := assert.Equal(t, books[book.ID].Size.Width, book.Size.Width); !ok {
598+
t.Error("Not bounded size")
599+
panic("Not bounded size")
600+
}
601+
602+
if ok := assert.Equal(t, books[book.ID].Size.Height, book.Size.Height); !ok {
603+
t.Error("Not bounded size")
604+
panic("Not bounded size")
605+
}
606+
}
607+
}
608+
}

0 commit comments

Comments
 (0)