d28f005552
Fix limit for databases other than sqlite go mod tidy && go mod vendor Remove unneeded break statements Make everything work with the new xorm version Fix xorm logging Fix lint Fix redis init Fix using id field Fix database init for testing Change default database log level Add xorm logger Use const for postgres go mod tidy Merge branch 'master' into update/xorm # Conflicts: # go.mod # go.sum # vendor/modules.txt go mod vendor Fix loading fixtures for postgres Go mod vendor1 Update xorm to version 1 Co-authored-by: kolaente <k@knt.li> Reviewed-on: https://kolaente.dev/vikunja/api/pulls/323
154 lines
4 KiB
Go
154 lines
4 KiB
Go
// 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 statements
|
||
|
||
import (
|
||
"database/sql"
|
||
"database/sql/driver"
|
||
"fmt"
|
||
"reflect"
|
||
"time"
|
||
|
||
"xorm.io/xorm/convert"
|
||
"xorm.io/xorm/dialects"
|
||
"xorm.io/xorm/internal/json"
|
||
"xorm.io/xorm/schemas"
|
||
)
|
||
|
||
var (
|
||
nullFloatType = reflect.TypeOf(sql.NullFloat64{})
|
||
)
|
||
|
||
// Value2Interface convert a field value of a struct to interface for puting into database
|
||
func (statement *Statement) Value2Interface(col *schemas.Column, fieldValue reflect.Value) (interface{}, error) {
|
||
if fieldValue.CanAddr() {
|
||
if fieldConvert, ok := fieldValue.Addr().Interface().(convert.Conversion); ok {
|
||
data, err := fieldConvert.ToDB()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if col.SQLType.IsBlob() {
|
||
return data, nil
|
||
}
|
||
return string(data), nil
|
||
}
|
||
}
|
||
|
||
if fieldConvert, ok := fieldValue.Interface().(convert.Conversion); ok {
|
||
data, err := fieldConvert.ToDB()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if col.SQLType.IsBlob() {
|
||
return data, nil
|
||
}
|
||
if nil == data {
|
||
return nil, nil
|
||
}
|
||
return string(data), nil
|
||
}
|
||
|
||
fieldType := fieldValue.Type()
|
||
k := fieldType.Kind()
|
||
if k == reflect.Ptr {
|
||
if fieldValue.IsNil() {
|
||
return nil, nil
|
||
} else if !fieldValue.IsValid() {
|
||
return nil, nil
|
||
} else {
|
||
// !nashtsai! deference pointer type to instance type
|
||
fieldValue = fieldValue.Elem()
|
||
fieldType = fieldValue.Type()
|
||
k = fieldType.Kind()
|
||
}
|
||
}
|
||
|
||
switch k {
|
||
case reflect.Bool:
|
||
return fieldValue.Bool(), nil
|
||
case reflect.String:
|
||
return fieldValue.String(), nil
|
||
case reflect.Struct:
|
||
if fieldType.ConvertibleTo(schemas.TimeType) {
|
||
t := fieldValue.Convert(schemas.TimeType).Interface().(time.Time)
|
||
tf := dialects.FormatColumnTime(statement.dialect, statement.defaultTimeZone, col, t)
|
||
return tf, nil
|
||
} else if fieldType.ConvertibleTo(nullFloatType) {
|
||
t := fieldValue.Convert(nullFloatType).Interface().(sql.NullFloat64)
|
||
if !t.Valid {
|
||
return nil, nil
|
||
}
|
||
return t.Float64, nil
|
||
}
|
||
|
||
if !col.SQLType.IsJson() {
|
||
// !<winxxp>! 增加支持driver.Valuer接口的结构,如sql.NullString
|
||
if v, ok := fieldValue.Interface().(driver.Valuer); ok {
|
||
return v.Value()
|
||
}
|
||
|
||
fieldTable, err := statement.tagParser.ParseWithCache(fieldValue)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if len(fieldTable.PrimaryKeys) == 1 {
|
||
pkField := reflect.Indirect(fieldValue).FieldByName(fieldTable.PKColumns()[0].FieldName)
|
||
return pkField.Interface(), nil
|
||
}
|
||
return nil, fmt.Errorf("no primary key for col %v", col.Name)
|
||
}
|
||
|
||
if col.SQLType.IsText() {
|
||
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return string(bytes), nil
|
||
} else if col.SQLType.IsBlob() {
|
||
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return bytes, nil
|
||
}
|
||
return nil, fmt.Errorf("Unsupported type %v", fieldValue.Type())
|
||
case reflect.Complex64, reflect.Complex128:
|
||
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return string(bytes), nil
|
||
case reflect.Array, reflect.Slice, reflect.Map:
|
||
if !fieldValue.IsValid() {
|
||
return fieldValue.Interface(), nil
|
||
}
|
||
|
||
if col.SQLType.IsText() {
|
||
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return string(bytes), nil
|
||
} else if col.SQLType.IsBlob() {
|
||
var bytes []byte
|
||
var err error
|
||
if (k == reflect.Slice) &&
|
||
(fieldValue.Type().Elem().Kind() == reflect.Uint8) {
|
||
bytes = fieldValue.Bytes()
|
||
} else {
|
||
bytes, err = json.DefaultJSONHandler.Marshal(fieldValue.Interface())
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
return bytes, nil
|
||
}
|
||
return nil, ErrUnSupportedType
|
||
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||
return int64(fieldValue.Uint()), nil
|
||
default:
|
||
return fieldValue.Interface(), nil
|
||
}
|
||
}
|