forgejo/vendor/xorm.io/xorm/schemas/column.go

136 lines
3.6 KiB
Go
Raw Normal View History

// Copyright 2019 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 schemas
2016-11-03 23:16:01 +01:00
import (
"errors"
2016-11-03 23:16:01 +01:00
"fmt"
"reflect"
"strconv"
2016-11-03 23:16:01 +01:00
"strings"
"time"
)
2021-05-14 21:17:06 +02:00
// enumerates all database mapping way
2016-11-03 23:16:01 +01:00
const (
TWOSIDES = iota + 1
ONLYTODB
ONLYFROMDB
)
// Column defines database column
2016-11-03 23:16:01 +01:00
type Column struct {
Name string
TableName string
FieldName string // Avaiable only when parsed from a struct
2016-11-03 23:16:01 +01:00
SQLType SQLType
IsJSON bool
2016-11-03 23:16:01 +01:00
Length int
Length2 int
Nullable bool
Default string
Indexes map[string]int
IsPrimaryKey bool
IsAutoIncrement bool
MapType int
IsCreated bool
IsUpdated bool
IsDeleted bool
IsCascade bool
IsVersion bool
DefaultIsEmpty bool // false means column has no default set, but not default value is empty
2016-11-03 23:16:01 +01:00
EnumOptions map[string]int
SetOptions map[string]int
DisableTimeZone bool
TimeZone *time.Location // column specified time zone
Comment string
2016-11-03 23:16:01 +01:00
}
// NewColumn creates a new column
2016-11-03 23:16:01 +01:00
func NewColumn(name, fieldName string, sqlType SQLType, len1, len2 int, nullable bool) *Column {
return &Column{
Name: name,
2021-01-05 07:28:51 +01:00
IsJSON: sqlType.IsJson(),
2016-11-03 23:16:01 +01:00
TableName: "",
FieldName: fieldName,
SQLType: sqlType,
Length: len1,
Length2: len2,
Nullable: nullable,
Default: "",
Indexes: make(map[string]int),
IsPrimaryKey: false,
IsAutoIncrement: false,
MapType: TWOSIDES,
IsCreated: false,
IsUpdated: false,
IsDeleted: false,
IsCascade: false,
IsVersion: false,
DefaultIsEmpty: true, // default should be no default
2016-11-03 23:16:01 +01:00
EnumOptions: make(map[string]int),
Comment: "",
2016-11-03 23:16:01 +01:00
}
}
// ValueOf returns column's filed of struct's value
2016-11-03 23:16:01 +01:00
func (col *Column) ValueOf(bean interface{}) (*reflect.Value, error) {
dataStruct := reflect.Indirect(reflect.ValueOf(bean))
return col.ValueOfV(&dataStruct)
}
// ValueOfV returns column's filed of struct's value accept reflevt value
2016-11-03 23:16:01 +01:00
func (col *Column) ValueOfV(dataStruct *reflect.Value) (*reflect.Value, error) {
var fieldValue reflect.Value
fieldPath := strings.Split(col.FieldName, ".")
2016-11-03 23:16:01 +01:00
if dataStruct.Type().Kind() == reflect.Map {
keyValue := reflect.ValueOf(fieldPath[len(fieldPath)-1])
2016-11-03 23:16:01 +01:00
fieldValue = dataStruct.MapIndex(keyValue)
return &fieldValue, nil
} else if dataStruct.Type().Kind() == reflect.Interface {
structValue := reflect.ValueOf(dataStruct.Interface())
dataStruct = &structValue
}
level := len(fieldPath)
fieldValue = dataStruct.FieldByName(fieldPath[0])
2016-11-03 23:16:01 +01:00
for i := 0; i < level-1; i++ {
if !fieldValue.IsValid() {
break
}
if fieldValue.Kind() == reflect.Struct {
fieldValue = fieldValue.FieldByName(fieldPath[i+1])
2016-11-03 23:16:01 +01:00
} else if fieldValue.Kind() == reflect.Ptr {
if fieldValue.IsNil() {
fieldValue.Set(reflect.New(fieldValue.Type().Elem()))
}
fieldValue = fieldValue.Elem().FieldByName(fieldPath[i+1])
2016-11-03 23:16:01 +01:00
} else {
return nil, fmt.Errorf("field %v is not valid", col.FieldName)
2016-11-03 23:16:01 +01:00
}
}
if !fieldValue.IsValid() {
return nil, fmt.Errorf("field %v is not valid", col.FieldName)
2016-11-03 23:16:01 +01:00
}
return &fieldValue, nil
}
// ConvertID converts id content to suitable type according column type
func (col *Column) ConvertID(sid string) (interface{}, error) {
if col.SQLType.IsNumeric() {
n, err := strconv.ParseInt(sid, 10, 64)
if err != nil {
return nil, err
}
return n, nil
} else if col.SQLType.IsText() {
return sid, nil
}
return nil, errors.New("not supported")
}