Skip to content

Commit e2f9100

Browse files
committed
Move tag parser related codes as a standalone sub package (#1547)
Fix sliceEq fix tests Move tag parser related codes as a standalone sub package Reviewed-on: https://gitea.com/xorm/xorm/pulls/1547
1 parent aa522f7 commit e2f9100

28 files changed

+1890
-1882
lines changed

.drone.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ steps:
2222
commands:
2323
- make test-sqlite
2424
- TEST_CACHE_ENABLE=true make test-sqlite
25-
- go test ./caches/... ./core/... ./dialects/... ./internal/... \
26-
./log/... ./migrate/... ./names/... ./schemas/...
25+
- go test ./caches/... ./convert/... ./core/... ./dialects/... \
26+
./log/... ./migrate/... ./names/... ./schemas/... ./tags/...
2727
when:
2828
event:
2929
- push

convert.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -346,10 +346,3 @@ func asBool(bs []byte) (bool, error) {
346346
}
347347
return strconv.ParseBool(string(bs))
348348
}
349-
350-
// Conversion is an interface. A type implements Conversion will according
351-
// the custom method to fill into database and retrieve from database.
352-
type Conversion interface {
353-
FromDB([]byte) error
354-
ToDB() ([]byte, error)
355-
}

convert/conversion.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2017 The Xorm Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package convert
6+
7+
// Conversion is an interface. A type implements Conversion will according
8+
// the custom method to fill into database and retrieve from database.
9+
type Conversion interface {
10+
FromDB([]byte) error
11+
ToDB() ([]byte, error)
12+
}

engine.go

Lines changed: 10 additions & 221 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"xorm.io/xorm/log"
2929
"xorm.io/xorm/names"
3030
"xorm.io/xorm/schemas"
31+
"xorm.io/xorm/tags"
3132
)
3233

3334
// Engine is the major struct of xorm, it means a database manager.
@@ -36,10 +37,7 @@ type Engine struct {
3637
db *core.DB
3738
dialect dialects.Dialect
3839

39-
ColumnMapper names.Mapper
40-
TableMapper names.Mapper
41-
TagIdentifier string
42-
Tables map[reflect.Type]*schemas.Table
40+
Tables map[reflect.Type]*schemas.Table
4341

4442
mutex *sync.RWMutex
4543

@@ -50,12 +48,12 @@ type Engine struct {
5048
TZLocation *time.Location // The timezone of the application
5149
DatabaseTZ *time.Location // The timezone of the database
5250

53-
tagHandlers map[string]tagHandler
54-
5551
engineGroup *EngineGroup
56-
cacherMgr *caches.Manager
5752

5853
defaultContext context.Context
54+
55+
tagParser *tags.Parser
56+
cacherMgr *caches.Manager
5957
}
6058

6159
func (engine *Engine) SetCacher(tableName string, cacher caches.Cacher) {
@@ -151,12 +149,12 @@ func (engine *Engine) SetMapper(mapper names.Mapper) {
151149

152150
// SetTableMapper set the table name mapping rule
153151
func (engine *Engine) SetTableMapper(mapper names.Mapper) {
154-
engine.TableMapper = mapper
152+
engine.tagParser.TableMapper = mapper
155153
}
156154

157155
// SetColumnMapper set the column name mapping rule
158156
func (engine *Engine) SetColumnMapper(mapper names.Mapper) {
159-
engine.ColumnMapper = mapper
157+
engine.tagParser.ColumnMapper = mapper
160158
}
161159

162160
// SupportInsertMany If engine's database support batch insert records like
@@ -769,7 +767,7 @@ func (engine *Engine) autoMapType(v reflect.Value) (*schemas.Table, error) {
769767
table, ok := engine.Tables[t]
770768
if !ok {
771769
var err error
772-
table, err = engine.mapType(v)
770+
table, err = engine.tagParser.MapType(v)
773771
if err != nil {
774772
return nil, err
775773
}
@@ -813,215 +811,6 @@ func (engine *Engine) TableInfo(bean interface{}) *Table {
813811
return &Table{tb, engine.TableName(bean)}
814812
}
815813

816-
func addIndex(indexName string, table *schemas.Table, col *schemas.Column, indexType int) {
817-
if index, ok := table.Indexes[indexName]; ok {
818-
index.AddColumn(col.Name)
819-
col.Indexes[index.Name] = indexType
820-
} else {
821-
index := schemas.NewIndex(indexName, indexType)
822-
index.AddColumn(col.Name)
823-
table.AddIndex(index)
824-
col.Indexes[index.Name] = indexType
825-
}
826-
}
827-
828-
// TableName table name interface to define customerize table name
829-
type TableName interface {
830-
TableName() string
831-
}
832-
833-
var (
834-
tpTableName = reflect.TypeOf((*TableName)(nil)).Elem()
835-
)
836-
837-
func (engine *Engine) mapType(v reflect.Value) (*schemas.Table, error) {
838-
t := v.Type()
839-
table := schemas.NewEmptyTable()
840-
table.Type = t
841-
table.Name = names.GetTableName(engine.TableMapper, v)
842-
843-
var idFieldColName string
844-
var hasCacheTag, hasNoCacheTag bool
845-
846-
for i := 0; i < t.NumField(); i++ {
847-
tag := t.Field(i).Tag
848-
849-
ormTagStr := tag.Get(engine.TagIdentifier)
850-
var col *schemas.Column
851-
fieldValue := v.Field(i)
852-
fieldType := fieldValue.Type()
853-
854-
if ormTagStr != "" {
855-
col = &schemas.Column{
856-
FieldName: t.Field(i).Name,
857-
Nullable: true,
858-
IsPrimaryKey: false,
859-
IsAutoIncrement: false,
860-
MapType: schemas.TWOSIDES,
861-
Indexes: make(map[string]int),
862-
DefaultIsEmpty: true,
863-
}
864-
tags := splitTag(ormTagStr)
865-
866-
if len(tags) > 0 {
867-
if tags[0] == "-" {
868-
continue
869-
}
870-
871-
var ctx = tagContext{
872-
table: table,
873-
col: col,
874-
fieldValue: fieldValue,
875-
indexNames: make(map[string]int),
876-
engine: engine,
877-
}
878-
879-
if strings.HasPrefix(strings.ToUpper(tags[0]), "EXTENDS") {
880-
pStart := strings.Index(tags[0], "(")
881-
if pStart > -1 && strings.HasSuffix(tags[0], ")") {
882-
var tagPrefix = strings.TrimFunc(tags[0][pStart+1:len(tags[0])-1], func(r rune) bool {
883-
return r == '\'' || r == '"'
884-
})
885-
886-
ctx.params = []string{tagPrefix}
887-
}
888-
889-
if err := ExtendsTagHandler(&ctx); err != nil {
890-
return nil, err
891-
}
892-
continue
893-
}
894-
895-
for j, key := range tags {
896-
if ctx.ignoreNext {
897-
ctx.ignoreNext = false
898-
continue
899-
}
900-
901-
k := strings.ToUpper(key)
902-
ctx.tagName = k
903-
ctx.params = []string{}
904-
905-
pStart := strings.Index(k, "(")
906-
if pStart == 0 {
907-
return nil, errors.New("( could not be the first character")
908-
}
909-
if pStart > -1 {
910-
if !strings.HasSuffix(k, ")") {
911-
return nil, fmt.Errorf("field %s tag %s cannot match ) character", col.FieldName, key)
912-
}
913-
914-
ctx.tagName = k[:pStart]
915-
ctx.params = strings.Split(key[pStart+1:len(k)-1], ",")
916-
}
917-
918-
if j > 0 {
919-
ctx.preTag = strings.ToUpper(tags[j-1])
920-
}
921-
if j < len(tags)-1 {
922-
ctx.nextTag = tags[j+1]
923-
} else {
924-
ctx.nextTag = ""
925-
}
926-
927-
if h, ok := engine.tagHandlers[ctx.tagName]; ok {
928-
if err := h(&ctx); err != nil {
929-
return nil, err
930-
}
931-
} else {
932-
if strings.HasPrefix(key, "'") && strings.HasSuffix(key, "'") {
933-
col.Name = key[1 : len(key)-1]
934-
} else {
935-
col.Name = key
936-
}
937-
}
938-
939-
if ctx.hasCacheTag {
940-
hasCacheTag = true
941-
}
942-
if ctx.hasNoCacheTag {
943-
hasNoCacheTag = true
944-
}
945-
}
946-
947-
if col.SQLType.Name == "" {
948-
col.SQLType = schemas.Type2SQLType(fieldType)
949-
}
950-
engine.dialect.SQLType(col)
951-
if col.Length == 0 {
952-
col.Length = col.SQLType.DefaultLength
953-
}
954-
if col.Length2 == 0 {
955-
col.Length2 = col.SQLType.DefaultLength2
956-
}
957-
if col.Name == "" {
958-
col.Name = engine.ColumnMapper.Obj2Table(t.Field(i).Name)
959-
}
960-
961-
if ctx.isUnique {
962-
ctx.indexNames[col.Name] = schemas.UniqueType
963-
} else if ctx.isIndex {
964-
ctx.indexNames[col.Name] = schemas.IndexType
965-
}
966-
967-
for indexName, indexType := range ctx.indexNames {
968-
addIndex(indexName, table, col, indexType)
969-
}
970-
}
971-
} else {
972-
var sqlType schemas.SQLType
973-
if fieldValue.CanAddr() {
974-
if _, ok := fieldValue.Addr().Interface().(Conversion); ok {
975-
sqlType = schemas.SQLType{Name: schemas.Text}
976-
}
977-
}
978-
if _, ok := fieldValue.Interface().(Conversion); ok {
979-
sqlType = schemas.SQLType{Name: schemas.Text}
980-
} else {
981-
sqlType = schemas.Type2SQLType(fieldType)
982-
}
983-
col = schemas.NewColumn(engine.ColumnMapper.Obj2Table(t.Field(i).Name),
984-
t.Field(i).Name, sqlType, sqlType.DefaultLength,
985-
sqlType.DefaultLength2, true)
986-
987-
if fieldType.Kind() == reflect.Int64 && (strings.ToUpper(col.FieldName) == "ID" || strings.HasSuffix(strings.ToUpper(col.FieldName), ".ID")) {
988-
idFieldColName = col.Name
989-
}
990-
}
991-
if col.IsAutoIncrement {
992-
col.Nullable = false
993-
}
994-
995-
table.AddColumn(col)
996-
997-
} // end for
998-
999-
if idFieldColName != "" && len(table.PrimaryKeys) == 0 {
1000-
col := table.GetColumn(idFieldColName)
1001-
col.IsPrimaryKey = true
1002-
col.IsAutoIncrement = true
1003-
col.Nullable = false
1004-
table.PrimaryKeys = append(table.PrimaryKeys, col.Name)
1005-
table.AutoIncrement = col.Name
1006-
}
1007-
1008-
if hasCacheTag {
1009-
if engine.GetDefaultCacher() != nil { // !nash! use engine's cacher if provided
1010-
engine.logger.Info("enable cache on table:", table.Name)
1011-
engine.SetCacher(table.Name, engine.GetDefaultCacher())
1012-
} else {
1013-
engine.logger.Info("enable LRU cache on table:", table.Name)
1014-
engine.SetCacher(table.Name, caches.NewLRUCacher2(caches.NewMemoryStore(), time.Hour, 10000))
1015-
}
1016-
}
1017-
if hasNoCacheTag {
1018-
engine.logger.Info("disable cache on table:", table.Name)
1019-
engine.SetCacher(table.Name, nil)
1020-
}
1021-
1022-
return table, nil
1023-
}
1024-
1025814
// IsTableEmpty if a table has any reocrd
1026815
func (engine *Engine) IsTableEmpty(bean interface{}) (bool, error) {
1027816
session := engine.NewSession()
@@ -1542,12 +1331,12 @@ func (engine *Engine) formatTime(sqlTypeName string, t time.Time) (v interface{}
15421331

15431332
// GetColumnMapper returns the column name mapper
15441333
func (engine *Engine) GetColumnMapper() names.Mapper {
1545-
return engine.ColumnMapper
1334+
return engine.tagParser.ColumnMapper
15461335
}
15471336

15481337
// GetTableMapper returns the table name mapper
15491338
func (engine *Engine) GetTableMapper() names.Mapper {
1550-
return engine.TableMapper
1339+
return engine.tagParser.TableMapper
15511340
}
15521341

15531342
// GetTZLocation returns time zone of the application

engine_cond.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"time"
1313

1414
"xorm.io/builder"
15+
"xorm.io/xorm/convert"
1516
"xorm.io/xorm/internal/utils"
1617
"xorm.io/xorm/schemas"
1718
)
@@ -137,7 +138,7 @@ func (engine *Engine) buildConds(table *schemas.Table, bean interface{},
137138
continue
138139
}
139140
val = engine.formatColTime(col, t)
140-
} else if _, ok := reflect.New(fieldType).Interface().(Conversion); ok {
141+
} else if _, ok := reflect.New(fieldType).Interface().(convert.Conversion); ok {
141142
continue
142143
} else if valNul, ok := fieldValue.Interface().(driver.Valuer); ok {
143144
val, _ = valNul.Value()

engine_group.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,9 @@ func (eg *EngineGroup) Ping() error {
112112

113113
// SetColumnMapper set the column name mapping rule
114114
func (eg *EngineGroup) SetColumnMapper(mapper names.Mapper) {
115-
eg.Engine.ColumnMapper = mapper
115+
eg.Engine.SetColumnMapper(mapper)
116116
for i := 0; i < len(eg.slaves); i++ {
117-
eg.slaves[i].ColumnMapper = mapper
117+
eg.slaves[i].SetColumnMapper(mapper)
118118
}
119119
}
120120

@@ -182,9 +182,9 @@ func (eg *EngineGroup) SetPolicy(policy GroupPolicy) *EngineGroup {
182182

183183
// SetTableMapper set the table name mapping rule
184184
func (eg *EngineGroup) SetTableMapper(mapper names.Mapper) {
185-
eg.Engine.TableMapper = mapper
185+
eg.Engine.SetTableMapper(mapper)
186186
for i := 0; i < len(eg.slaves); i++ {
187-
eg.slaves[i].TableMapper = mapper
187+
eg.slaves[i].SetTableMapper(mapper)
188188
}
189189
}
190190

0 commit comments

Comments
 (0)