123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- // 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/xormplus/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,
- "COMMENT": CommentTagHandler,
- }
- )
- 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
- }
- // CommentTagHandler add comment to column
- func CommentTagHandler(ctx *tagContext) error {
- if len(ctx.params) > 0 {
- ctx.col.Comment = strings.Trim(ctx.params[0], "' ")
- }
- 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
- var isPtr = false
- 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()
- }
- }
- isPtr = true
- 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)
- var tagPrefix = ctx.col.FieldName
- if len(ctx.params) > 0 {
- col.Nullable = isPtr
- tagPrefix = ctx.params[0]
- if col.IsPrimaryKey {
- col.Name = ctx.col.FieldName
- col.IsPrimaryKey = false
- } else {
- col.Name = fmt.Sprintf("%v%v", tagPrefix, col.Name)
- }
- }
- if col.Nullable {
- col.IsAutoIncrement = false
- col.IsPrimaryKey = false
- }
- 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
- }
|