Handle xorm tags via tagHandler prepared for customerize tag support (#551)
* handle xorm tags via tagHandler prepared for customerize tag support * add some comments and improvements
This commit is contained in:
parent
47cb51deca
commit
bda5f17e01
240
engine.go
240
engine.go
|
@ -44,6 +44,8 @@ type Engine struct {
|
||||||
DatabaseTZ *time.Location // The timezone of the database
|
DatabaseTZ *time.Location // The timezone of the database
|
||||||
|
|
||||||
disableGlobalCache bool
|
disableGlobalCache bool
|
||||||
|
|
||||||
|
tagHandlers map[string]tagHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShowSQL show SQL statement or not on logger if log level is great than INFO
|
// ShowSQL show SQL statement or not on logger if log level is great than INFO
|
||||||
|
@ -780,13 +782,18 @@ func (engine *Engine) autoMapType(v reflect.Value) *core.Table {
|
||||||
defer engine.mutex.Unlock()
|
defer engine.mutex.Unlock()
|
||||||
table, ok := engine.Tables[t]
|
table, ok := engine.Tables[t]
|
||||||
if !ok {
|
if !ok {
|
||||||
table = engine.mapType(v)
|
var err error
|
||||||
engine.Tables[t] = table
|
table, err = engine.mapType(v)
|
||||||
if engine.Cacher != nil {
|
if err != nil {
|
||||||
if v.CanAddr() {
|
engine.logger.Error(err)
|
||||||
engine.GobRegister(v.Addr().Interface())
|
} else {
|
||||||
} else {
|
engine.Tables[t] = table
|
||||||
engine.GobRegister(v.Interface())
|
if engine.Cacher != nil {
|
||||||
|
if v.CanAddr() {
|
||||||
|
engine.GobRegister(v.Addr().Interface())
|
||||||
|
} else {
|
||||||
|
engine.GobRegister(v.Interface())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -842,7 +849,7 @@ var (
|
||||||
tpTableName = reflect.TypeOf((*TableName)(nil)).Elem()
|
tpTableName = reflect.TypeOf((*TableName)(nil)).Elem()
|
||||||
)
|
)
|
||||||
|
|
||||||
func (engine *Engine) mapType(v reflect.Value) *core.Table {
|
func (engine *Engine) mapType(v reflect.Value) (*core.Table, error) {
|
||||||
t := v.Type()
|
t := v.Type()
|
||||||
table := engine.newTable()
|
table := engine.newTable()
|
||||||
if tb, ok := v.Interface().(TableName); ok {
|
if tb, ok := v.Interface().(TableName); ok {
|
||||||
|
@ -861,7 +868,6 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
|
||||||
table.Type = t
|
table.Type = t
|
||||||
|
|
||||||
var idFieldColName string
|
var idFieldColName string
|
||||||
var err error
|
|
||||||
var hasCacheTag, hasNoCacheTag bool
|
var hasCacheTag, hasNoCacheTag bool
|
||||||
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
@ -881,186 +887,94 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
|
||||||
if tags[0] == "-" {
|
if tags[0] == "-" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ctx = tagContext{
|
||||||
|
table: table,
|
||||||
|
col: col,
|
||||||
|
fieldValue: fieldValue,
|
||||||
|
indexNames: make(map[string]int),
|
||||||
|
engine: engine,
|
||||||
|
}
|
||||||
|
|
||||||
if strings.ToUpper(tags[0]) == "EXTENDS" {
|
if strings.ToUpper(tags[0]) == "EXTENDS" {
|
||||||
switch fieldValue.Kind() {
|
if err := ExtendsTagHandler(&ctx); err != nil {
|
||||||
case reflect.Ptr:
|
return nil, err
|
||||||
f := fieldValue.Type().Elem()
|
|
||||||
if f.Kind() == reflect.Struct {
|
|
||||||
fieldPtr := fieldValue
|
|
||||||
fieldValue = fieldValue.Elem()
|
|
||||||
if !fieldValue.IsValid() || fieldPtr.IsNil() {
|
|
||||||
fieldValue = reflect.New(f).Elem()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fallthrough
|
|
||||||
case reflect.Struct:
|
|
||||||
parentTable := engine.mapType(fieldValue)
|
|
||||||
for _, col := range parentTable.Columns() {
|
|
||||||
col.FieldName = fmt.Sprintf("%v.%v", t.Field(i).Name, col.FieldName)
|
|
||||||
table.AddColumn(col)
|
|
||||||
for indexName, indexType := range col.Indexes {
|
|
||||||
addIndex(indexName, table, col, indexType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
default:
|
|
||||||
//TODO: warning
|
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
indexNames := make(map[string]int)
|
|
||||||
var isIndex, isUnique bool
|
|
||||||
var preKey string
|
|
||||||
for j, key := range tags {
|
for j, key := range tags {
|
||||||
|
if ctx.ignoreNext {
|
||||||
|
ctx.ignoreNext = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
k := strings.ToUpper(key)
|
k := strings.ToUpper(key)
|
||||||
switch {
|
ctx.tagName = k
|
||||||
case k == "<-":
|
|
||||||
col.MapType = core.ONLYFROMDB
|
|
||||||
case k == "->":
|
|
||||||
col.MapType = core.ONLYTODB
|
|
||||||
case k == "PK":
|
|
||||||
col.IsPrimaryKey = true
|
|
||||||
col.Nullable = false
|
|
||||||
case k == "NULL":
|
|
||||||
if j == 0 {
|
|
||||||
col.Nullable = true
|
|
||||||
} else {
|
|
||||||
col.Nullable = (strings.ToUpper(tags[j-1]) != "NOT")
|
|
||||||
}
|
|
||||||
// TODO: for postgres how add autoincr?
|
|
||||||
/*case strings.HasPrefix(k, "AUTOINCR(") && strings.HasSuffix(k, ")"):
|
|
||||||
col.IsAutoIncrement = true
|
|
||||||
|
|
||||||
autoStart := k[len("AUTOINCR")+1 : len(k)-1]
|
pStart := strings.Index(k, "(")
|
||||||
autoStartInt, err := strconv.Atoi(autoStart)
|
if pStart == 0 {
|
||||||
if err != nil {
|
return nil, errors.New("( could not be the first charactor")
|
||||||
engine.LogError(err)
|
|
||||||
}
|
}
|
||||||
col.AutoIncrStart = autoStartInt*/
|
if pStart > -1 {
|
||||||
case k == "AUTOINCR":
|
if !strings.HasSuffix(k, ")") {
|
||||||
col.IsAutoIncrement = true
|
return nil, errors.New("cannot match ) charactor")
|
||||||
//col.AutoIncrStart = 1
|
|
||||||
case k == "DEFAULT":
|
|
||||||
col.Default = tags[j+1]
|
|
||||||
case k == "CREATED":
|
|
||||||
col.IsCreated = true
|
|
||||||
case k == "VERSION":
|
|
||||||
col.IsVersion = true
|
|
||||||
col.Default = "1"
|
|
||||||
case k == "UTC":
|
|
||||||
col.TimeZone = time.UTC
|
|
||||||
case k == "LOCAL":
|
|
||||||
col.TimeZone = time.Local
|
|
||||||
case strings.HasPrefix(k, "LOCALE(") && strings.HasSuffix(k, ")"):
|
|
||||||
location := k[len("LOCALE")+1 : len(k)-1]
|
|
||||||
col.TimeZone, err = time.LoadLocation(location)
|
|
||||||
if err != nil {
|
|
||||||
engine.logger.Error(err)
|
|
||||||
}
|
}
|
||||||
case k == "UPDATED":
|
|
||||||
col.IsUpdated = true
|
|
||||||
case k == "DELETED":
|
|
||||||
col.IsDeleted = true
|
|
||||||
case strings.HasPrefix(k, "INDEX(") && strings.HasSuffix(k, ")"):
|
|
||||||
indexName := k[len("INDEX")+1 : len(k)-1]
|
|
||||||
indexNames[indexName] = core.IndexType
|
|
||||||
case k == "INDEX":
|
|
||||||
isIndex = true
|
|
||||||
case strings.HasPrefix(k, "UNIQUE(") && strings.HasSuffix(k, ")"):
|
|
||||||
indexName := k[len("UNIQUE")+1 : len(k)-1]
|
|
||||||
indexNames[indexName] = core.UniqueType
|
|
||||||
case k == "UNIQUE":
|
|
||||||
isUnique = true
|
|
||||||
case k == "NOTNULL":
|
|
||||||
col.Nullable = false
|
|
||||||
case k == "CACHE":
|
|
||||||
if !hasCacheTag {
|
|
||||||
hasCacheTag = true
|
|
||||||
}
|
|
||||||
case k == "NOCACHE":
|
|
||||||
if !hasNoCacheTag {
|
|
||||||
hasNoCacheTag = true
|
|
||||||
}
|
|
||||||
case k == "NOT":
|
|
||||||
default:
|
|
||||||
if strings.HasPrefix(k, "'") && strings.HasSuffix(k, "'") {
|
|
||||||
if preKey != "DEFAULT" {
|
|
||||||
col.Name = key[1 : len(key)-1]
|
|
||||||
}
|
|
||||||
} else if strings.Contains(k, "(") && strings.HasSuffix(k, ")") {
|
|
||||||
fs := strings.Split(k, "(")
|
|
||||||
|
|
||||||
if _, ok := core.SqlTypes[fs[0]]; !ok {
|
ctx.tagName = k[:pStart]
|
||||||
preKey = k
|
ctx.params = strings.Split(k[pStart+1:len(k)-1], ",")
|
||||||
continue
|
}
|
||||||
}
|
|
||||||
col.SQLType = core.SQLType{Name: fs[0]}
|
if j > 0 {
|
||||||
if fs[0] == core.Enum && fs[1][0] == '\'' { //enum
|
ctx.preTag = strings.ToUpper(tags[j-1])
|
||||||
options := strings.Split(fs[1][0:len(fs[1])-1], ",")
|
}
|
||||||
col.EnumOptions = make(map[string]int)
|
if j < len(tags)-1 {
|
||||||
for k, v := range options {
|
ctx.nextTag = strings.ToUpper(tags[j+1])
|
||||||
v = strings.TrimSpace(v)
|
} else {
|
||||||
v = strings.Trim(v, "'")
|
ctx.nextTag = ""
|
||||||
col.EnumOptions[v] = k
|
}
|
||||||
}
|
|
||||||
} else if fs[0] == core.Set && fs[1][0] == '\'' { //set
|
if h, ok := engine.tagHandlers[ctx.tagName]; ok {
|
||||||
options := strings.Split(fs[1][0:len(fs[1])-1], ",")
|
if err := h(&ctx); err != nil {
|
||||||
col.SetOptions = make(map[string]int)
|
return nil, err
|
||||||
for k, v := range options {
|
}
|
||||||
v = strings.TrimSpace(v)
|
} else {
|
||||||
v = strings.Trim(v, "'")
|
if strings.HasPrefix(key, "'") && strings.HasSuffix(key, "'") {
|
||||||
col.SetOptions[v] = k
|
col.Name = key[1 : len(key)-1]
|
||||||
}
|
} else {
|
||||||
} else {
|
col.Name = key
|
||||||
fs2 := strings.Split(fs[1][0:len(fs[1])-1], ",")
|
}
|
||||||
if len(fs2) == 2 {
|
}
|
||||||
col.Length, err = strconv.Atoi(fs2[0])
|
|
||||||
if err != nil {
|
if ctx.hasCacheTag {
|
||||||
engine.logger.Error(err)
|
hasCacheTag = true
|
||||||
}
|
}
|
||||||
col.Length2, err = strconv.Atoi(fs2[1])
|
if ctx.hasNoCacheTag {
|
||||||
if err != nil {
|
hasNoCacheTag = true
|
||||||
engine.logger.Error(err)
|
|
||||||
}
|
|
||||||
} else if len(fs2) == 1 {
|
|
||||||
col.Length, err = strconv.Atoi(fs2[0])
|
|
||||||
if err != nil {
|
|
||||||
engine.logger.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if _, ok := core.SqlTypes[k]; ok {
|
|
||||||
col.SQLType = core.SQLType{Name: k}
|
|
||||||
} else if key != col.Default {
|
|
||||||
col.Name = key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
engine.dialect.SqlType(col)
|
|
||||||
}
|
}
|
||||||
preKey = k
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if col.SQLType.Name == "" {
|
if col.SQLType.Name == "" {
|
||||||
col.SQLType = core.Type2SQLType(fieldType)
|
col.SQLType = core.Type2SQLType(fieldType)
|
||||||
}
|
}
|
||||||
|
engine.dialect.SqlType(col)
|
||||||
if col.Length == 0 {
|
if col.Length == 0 {
|
||||||
col.Length = col.SQLType.DefaultLength
|
col.Length = col.SQLType.DefaultLength
|
||||||
}
|
}
|
||||||
if col.Length2 == 0 {
|
if col.Length2 == 0 {
|
||||||
col.Length2 = col.SQLType.DefaultLength2
|
col.Length2 = col.SQLType.DefaultLength2
|
||||||
}
|
}
|
||||||
|
|
||||||
if col.Name == "" {
|
if col.Name == "" {
|
||||||
col.Name = engine.ColumnMapper.Obj2Table(t.Field(i).Name)
|
col.Name = engine.ColumnMapper.Obj2Table(t.Field(i).Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if isUnique {
|
if ctx.isUnique {
|
||||||
indexNames[col.Name] = core.UniqueType
|
ctx.indexNames[col.Name] = core.UniqueType
|
||||||
} else if isIndex {
|
} else if ctx.isIndex {
|
||||||
indexNames[col.Name] = core.IndexType
|
ctx.indexNames[col.Name] = core.IndexType
|
||||||
}
|
}
|
||||||
|
|
||||||
for indexName, indexType := range indexNames {
|
for indexName, indexType := range ctx.indexNames {
|
||||||
addIndex(indexName, table, col, indexType)
|
addIndex(indexName, table, col, indexType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1114,7 +1028,7 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
|
||||||
table.Cacher = nil
|
table.Cacher = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return table
|
return table, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsTableEmpty if a table has any reocrd
|
// IsTableEmpty if a table has any reocrd
|
||||||
|
|
|
@ -306,7 +306,10 @@ func (session *Session) Sync2(beans ...interface{}) error {
|
||||||
|
|
||||||
for _, bean := range beans {
|
for _, bean := range beans {
|
||||||
v := rValue(bean)
|
v := rValue(bean)
|
||||||
table := engine.mapType(v)
|
table, err := engine.mapType(v)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
structTables = append(structTables, table)
|
structTables = append(structTables, table)
|
||||||
var tbName = session.tbNameNoSchema(table)
|
var tbName = session.tbNameNoSchema(table)
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,9 @@ var colStrTests = []struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestColumnsStringGeneration(t *testing.T) {
|
func TestColumnsStringGeneration(t *testing.T) {
|
||||||
|
|
||||||
var statement *Statement
|
var statement *Statement
|
||||||
|
|
||||||
for ndx, testCase := range colStrTests {
|
for ndx, testCase := range colStrTests {
|
||||||
|
|
||||||
statement = createTestStatement()
|
statement = createTestStatement()
|
||||||
|
|
||||||
if testCase.omitColumn != "" {
|
if testCase.omitColumn != "" {
|
||||||
|
@ -54,7 +52,6 @@ func TestColumnsStringGeneration(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkColumnsStringGeneration(b *testing.B) {
|
func BenchmarkColumnsStringGeneration(b *testing.B) {
|
||||||
|
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
|
|
||||||
statement := createTestStatement()
|
statement := createTestStatement()
|
||||||
|
|
|
@ -0,0 +1,281 @@
|
||||||
|
// Copyright 2017 The Xorm Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package xorm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-xorm/core"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tagContext struct {
|
||||||
|
tagName string
|
||||||
|
params []string
|
||||||
|
preTag, nextTag string
|
||||||
|
table *core.Table
|
||||||
|
col *core.Column
|
||||||
|
fieldValue reflect.Value
|
||||||
|
isIndex bool
|
||||||
|
isUnique bool
|
||||||
|
indexNames map[string]int
|
||||||
|
engine *Engine
|
||||||
|
hasCacheTag bool
|
||||||
|
hasNoCacheTag bool
|
||||||
|
ignoreNext bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// tagHandler describes tag handler for XORM
|
||||||
|
type tagHandler func(ctx *tagContext) error
|
||||||
|
|
||||||
|
var (
|
||||||
|
// defaultTagHandlers enumerates all the default tag handler
|
||||||
|
defaultTagHandlers = map[string]tagHandler{
|
||||||
|
"<-": OnlyFromDBTagHandler,
|
||||||
|
"->": OnlyToDBTagHandler,
|
||||||
|
"PK": PKTagHandler,
|
||||||
|
"NULL": NULLTagHandler,
|
||||||
|
"NOT": IgnoreTagHandler,
|
||||||
|
"AUTOINCR": AutoIncrTagHandler,
|
||||||
|
"DEFAULT": DefaultTagHandler,
|
||||||
|
"CREATED": CreatedTagHandler,
|
||||||
|
"UPDATED": UpdatedTagHandler,
|
||||||
|
"DELETED": DeletedTagHandler,
|
||||||
|
"VERSION": VersionTagHandler,
|
||||||
|
"UTC": UTCTagHandler,
|
||||||
|
"LOCAL": LocalTagHandler,
|
||||||
|
"NOTNULL": NotNullTagHandler,
|
||||||
|
"INDEX": IndexTagHandler,
|
||||||
|
"UNIQUE": UniqueTagHandler,
|
||||||
|
"CACHE": CacheTagHandler,
|
||||||
|
"NOCACHE": NoCacheTagHandler,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
for k := range core.SqlTypes {
|
||||||
|
defaultTagHandlers[k] = SQLTypeTagHandler
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IgnoreTagHandler describes ignored tag handler
|
||||||
|
func IgnoreTagHandler(ctx *tagContext) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnlyFromDBTagHandler describes mapping direction tag handler
|
||||||
|
func OnlyFromDBTagHandler(ctx *tagContext) error {
|
||||||
|
ctx.col.MapType = core.ONLYFROMDB
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnlyToDBTagHandler describes mapping direction tag handler
|
||||||
|
func OnlyToDBTagHandler(ctx *tagContext) error {
|
||||||
|
ctx.col.MapType = core.ONLYTODB
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PKTagHandler decribes primary key tag handler
|
||||||
|
func PKTagHandler(ctx *tagContext) error {
|
||||||
|
ctx.col.IsPrimaryKey = true
|
||||||
|
ctx.col.Nullable = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NULLTagHandler describes null tag handler
|
||||||
|
func NULLTagHandler(ctx *tagContext) error {
|
||||||
|
ctx.col.Nullable = (strings.ToUpper(ctx.preTag) != "NOT")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotNullTagHandler describes notnull tag handler
|
||||||
|
func NotNullTagHandler(ctx *tagContext) error {
|
||||||
|
ctx.col.Nullable = false
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AutoIncrTagHandler describes autoincr tag handler
|
||||||
|
func AutoIncrTagHandler(ctx *tagContext) error {
|
||||||
|
ctx.col.IsAutoIncrement = true
|
||||||
|
/*
|
||||||
|
if len(ctx.params) > 0 {
|
||||||
|
autoStartInt, err := strconv.Atoi(ctx.params[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ctx.col.AutoIncrStart = autoStartInt
|
||||||
|
} else {
|
||||||
|
ctx.col.AutoIncrStart = 1
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultTagHandler describes default tag handler
|
||||||
|
func DefaultTagHandler(ctx *tagContext) error {
|
||||||
|
if len(ctx.params) > 0 {
|
||||||
|
ctx.col.Default = ctx.params[0]
|
||||||
|
} else {
|
||||||
|
ctx.col.Default = ctx.nextTag
|
||||||
|
ctx.ignoreNext = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreatedTagHandler describes created tag handler
|
||||||
|
func CreatedTagHandler(ctx *tagContext) error {
|
||||||
|
ctx.col.IsCreated = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// VersionTagHandler describes version tag handler
|
||||||
|
func VersionTagHandler(ctx *tagContext) error {
|
||||||
|
ctx.col.IsVersion = true
|
||||||
|
ctx.col.Default = "1"
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UTCTagHandler describes utc tag handler
|
||||||
|
func UTCTagHandler(ctx *tagContext) error {
|
||||||
|
ctx.col.TimeZone = time.UTC
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalTagHandler describes local tag handler
|
||||||
|
func LocalTagHandler(ctx *tagContext) error {
|
||||||
|
if len(ctx.params) == 0 {
|
||||||
|
ctx.col.TimeZone = time.Local
|
||||||
|
} else {
|
||||||
|
var err error
|
||||||
|
ctx.col.TimeZone, err = time.LoadLocation(ctx.params[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdatedTagHandler describes updated tag handler
|
||||||
|
func UpdatedTagHandler(ctx *tagContext) error {
|
||||||
|
ctx.col.IsUpdated = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletedTagHandler describes deleted tag handler
|
||||||
|
func DeletedTagHandler(ctx *tagContext) error {
|
||||||
|
ctx.col.IsDeleted = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndexTagHandler describes index tag handler
|
||||||
|
func IndexTagHandler(ctx *tagContext) error {
|
||||||
|
if len(ctx.params) > 0 {
|
||||||
|
ctx.indexNames[ctx.params[0]] = core.IndexType
|
||||||
|
} else {
|
||||||
|
ctx.isIndex = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UniqueTagHandler describes unique tag handler
|
||||||
|
func UniqueTagHandler(ctx *tagContext) error {
|
||||||
|
if len(ctx.params) > 0 {
|
||||||
|
ctx.indexNames[ctx.params[0]] = core.UniqueType
|
||||||
|
} else {
|
||||||
|
ctx.isUnique = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SQLTypeTagHandler describes SQL Type tag handler
|
||||||
|
func SQLTypeTagHandler(ctx *tagContext) error {
|
||||||
|
ctx.col.SQLType = core.SQLType{Name: ctx.tagName}
|
||||||
|
if len(ctx.params) > 0 {
|
||||||
|
if ctx.tagName == core.Enum {
|
||||||
|
ctx.col.EnumOptions = make(map[string]int)
|
||||||
|
for k, v := range ctx.params {
|
||||||
|
v = strings.TrimSpace(v)
|
||||||
|
v = strings.Trim(v, "'")
|
||||||
|
ctx.col.EnumOptions[v] = k
|
||||||
|
}
|
||||||
|
} else if ctx.tagName == core.Set {
|
||||||
|
ctx.col.SetOptions = make(map[string]int)
|
||||||
|
for k, v := range ctx.params {
|
||||||
|
v = strings.TrimSpace(v)
|
||||||
|
v = strings.Trim(v, "'")
|
||||||
|
ctx.col.SetOptions[v] = k
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var err error
|
||||||
|
if len(ctx.params) == 2 {
|
||||||
|
ctx.col.Length, err = strconv.Atoi(ctx.params[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ctx.col.Length2, err = strconv.Atoi(ctx.params[1])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if len(ctx.params) == 1 {
|
||||||
|
ctx.col.Length, err = strconv.Atoi(ctx.params[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExtendsTagHandler describes extends tag handler
|
||||||
|
func ExtendsTagHandler(ctx *tagContext) error {
|
||||||
|
var fieldValue = ctx.fieldValue
|
||||||
|
switch fieldValue.Kind() {
|
||||||
|
case reflect.Ptr:
|
||||||
|
f := fieldValue.Type().Elem()
|
||||||
|
if f.Kind() == reflect.Struct {
|
||||||
|
fieldPtr := fieldValue
|
||||||
|
fieldValue = fieldValue.Elem()
|
||||||
|
if !fieldValue.IsValid() || fieldPtr.IsNil() {
|
||||||
|
fieldValue = reflect.New(f).Elem()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case reflect.Struct:
|
||||||
|
parentTable, err := ctx.engine.mapType(fieldValue)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, col := range parentTable.Columns() {
|
||||||
|
col.FieldName = fmt.Sprintf("%v.%v", ctx.col.FieldName, col.FieldName)
|
||||||
|
ctx.table.AddColumn(col)
|
||||||
|
for indexName, indexType := range col.Indexes {
|
||||||
|
addIndex(indexName, ctx.table, col, indexType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
//TODO: warning
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CacheTagHandler describes cache tag handler
|
||||||
|
func CacheTagHandler(ctx *tagContext) error {
|
||||||
|
if !ctx.hasCacheTag {
|
||||||
|
ctx.hasCacheTag = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NoCacheTagHandler describes nocache tag handler
|
||||||
|
func NoCacheTagHandler(ctx *tagContext) error {
|
||||||
|
if !ctx.hasNoCacheTag {
|
||||||
|
ctx.hasNoCacheTag = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
1
xorm.go
1
xorm.go
|
@ -86,6 +86,7 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) {
|
||||||
mutex: &sync.RWMutex{},
|
mutex: &sync.RWMutex{},
|
||||||
TagIdentifier: "xorm",
|
TagIdentifier: "xorm",
|
||||||
TZLocation: time.Local,
|
TZLocation: time.Local,
|
||||||
|
tagHandlers: defaultTagHandlers,
|
||||||
}
|
}
|
||||||
|
|
||||||
logger := NewSimpleLogger(os.Stdout)
|
logger := NewSimpleLogger(os.Stdout)
|
||||||
|
|
Loading…
Reference in New Issue