貌似不支持 sql.NullTime #2099

Open
opened 2022-01-14 07:57:52 +00:00 by fanybook · 2 comments
Contributor

现象:我自定义了一个类型,封装了 sql.NullTime

// db.Time
type Time struct {
    sql.NullTime
}

在 insert 的时候,报错了 “panic: reflect.Value.Convert: value of type time.Time cannot be converted to type db.Time”

我跟了一下,发现应该和自动时间戳有关

xorm 生成里 time.Time 的时间戳,然后貌似不知道该怎么转换

session_insert.go -> genInsertColumns -> setColumnTime

现象:我自定义了一个类型,封装了 sql.NullTime ```go // db.Time type Time struct { sql.NullTime } ``` 在 insert 的时候,报错了 “panic: reflect.Value.Convert: value of type time.Time cannot be converted to type db.Time” 我跟了一下,发现应该和自动时间戳有关 xorm 生成里 time.Time 的时间戳,然后貌似不知道该怎么转换 session_insert.go -> genInsertColumns -> setColumnTime
Author
Contributor

还有一个问题,insert 的时候,能不能通过类型的 Value() 看以下是否为 nil,如果为 nil 就不要拼 insert 的 sql 文了

现在的现象是,使用了类似 sql.NullSting 的类型,然后在定义 model 时直接使用了 sql.NullSting,而没用 *sql.NullSting

然后 new(Model),这个字段就必然不是 nil,但是它的 Value() 是 nil 啊,但是 insert sql 会把这个字段拼上,导致数据库如果不允许为 null,但是有默认值,也仍然无法 insert 成功

还有一个问题,insert 的时候,能不能通过类型的 Value() 看以下是否为 nil,如果为 nil 就不要拼 insert 的 sql 文了 现在的现象是,使用了类似 sql.NullSting 的类型,然后在定义 model 时直接使用了 sql.NullSting,而没用 *sql.NullSting 然后 new(Model),这个字段就必然不是 nil,但是它的 Value() 是 nil 啊,但是 insert sql 会把这个字段拼上,导致数据库如果不允许为 null,但是有默认值,也仍然无法 insert 成功
Author
Contributor

@Lunny Xiao 我本地这样该的,报错就好了,但不知道这样改是不是最优的

func setColumnTime(bean interface{}, col *schemas.Column, t time.Time) {
	v, err := col.ValueOf(bean)
	if err != nil {
		return
	}

	// add sta
	if v.Kind() == reflect.Ptr {
		typ := v.Type()
		if _, ok := typ.MethodByName("ConvertTime"); ok {
			timeConvertFn := v.MethodByName("ConvertTime")
			params := []reflect.Value{reflect.ValueOf(t)}
			timeConvertFn.Call(params)
			return
		}
	} else if v.CanAddr() {
		typ := v.Addr().Type()
		if _, ok := typ.MethodByName("ConvertTime"); ok {
			timeConvertFn := v.Addr().MethodByName("ConvertTime")
			params := []reflect.Value{reflect.ValueOf(t)}
			timeConvertFn.Call(params)
			return
		}
	}
	// add end

	if v.CanSet() {
		switch v.Type().Kind() {
		case reflect.Struct:
			v.Set(reflect.ValueOf(t).Convert(v.Type()))
		case reflect.Int, reflect.Int64, reflect.Int32:
			v.SetInt(t.Unix())
		case reflect.Uint, reflect.Uint64, reflect.Uint32:
			v.SetUint(uint64(t.Unix()))
		}
	}
}
func (v *Time) ConvertTime(t time.Time) {
    v.Time = t
}
@Lunny Xiao 我本地这样该的,报错就好了,但不知道这样改是不是最优的 ```go func setColumnTime(bean interface{}, col *schemas.Column, t time.Time) { v, err := col.ValueOf(bean) if err != nil { return } // add sta if v.Kind() == reflect.Ptr { typ := v.Type() if _, ok := typ.MethodByName("ConvertTime"); ok { timeConvertFn := v.MethodByName("ConvertTime") params := []reflect.Value{reflect.ValueOf(t)} timeConvertFn.Call(params) return } } else if v.CanAddr() { typ := v.Addr().Type() if _, ok := typ.MethodByName("ConvertTime"); ok { timeConvertFn := v.Addr().MethodByName("ConvertTime") params := []reflect.Value{reflect.ValueOf(t)} timeConvertFn.Call(params) return } } // add end if v.CanSet() { switch v.Type().Kind() { case reflect.Struct: v.Set(reflect.ValueOf(t).Convert(v.Type())) case reflect.Int, reflect.Int64, reflect.Int32: v.SetInt(t.Unix()) case reflect.Uint, reflect.Uint64, reflect.Uint32: v.SetUint(uint64(t.Unix())) } } } ``` ```go func (v *Time) ConvertTime(t time.Time) { v.Time = t } ```
lunny added the
kind
enhancement
label 2022-02-16 13:47:33 +00:00
Sign in to join this conversation.
No Milestone
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: xorm/xorm#2099
No description provided.