time.Time默认值不再是 0001-01-01 00:00:00 了吗? #1066
Labels
No Label
backport/done
backport/v1
blocked
db
oracle
db
sqlserver
duplicate
feature
cache
frontport/done
frontport/main
invalid
kind
breaking
kind
bug
kind
build
kind
dependencies
kind
docs
kind
driver
kind
enhancement
kind
feature
kind
performance
kind
proposal
kind
question
kind
refactor
kind
testing
need
feedback
need
test
proposal:accepted
RaspBerry Pi
regression
skip-changelog
upstream
wip
wontfix
No Milestone
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: xorm/xorm#1066
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
数据库:
注意:login_time 是NOT NULL
model:
Insert代码:
对于以前的版本(0.5以前?),以上语句不会出错,因为生成的语句是:
而升级到现在的版本后(dep ensure -update):
以上的插入代码会出错,因为生成的语句变成了:
这样导致以前设置了NOT NULL字段的数据表,在插入的时候,会报错:
导致无法完美无缝的将xorm迁移到新版
@lunny 瞅瞅?
同时,即使指定了默认值,生成的语句也不是按照默认值来的
生成的语句依然是:
此时,指定了
not null
,所以 time.Time在这里又变成了 "" ,而不是之前的 interface{}(nil).此时,如果mysql数据的sql_mode设置的是严格模式(一般情况下都是严格模式),这这种日期会被认为是非法的日期,从而导致插入数据库不成功。
xorm 生成sql的表现如果这么不可控的话,如果遇上特定sql_mode的设置,更容易出问题。
避免这么多不可控因素最好的方案就是,对于 time.Time 的默认值,首先按照 struct tag中定义的 default value来传递,如果struct tag 中没有定义default 值,那么应该采用golang的默认值: '0001-01-01 00:00:00' ,而不是一会儿是 "", 一会又是 interface{}(nil)
@lunny 来帮忙看看是不是这么个情况?或者可以代码中可以手动指定 session级别的sql_mode?
升级xorm后,sql中的time.Time默认值变为 interface{}(nil)
指定字段NOT NULL后,sql中的time.Time默认值为"",
均无法满足原有数据库字段NOT NULL DEFAULT '0000-00-00 00:00:00'的要求.(msyql5.7 严格模式下)
因此,目前一个兼容方案是 当 time.Time isZero,插入数据时省略该字段
这个地方需要XORM改进,当字段为time.Time类型且IsZero时,如果有默认值则使用默认值,如果没有默认值则为nil
暂时以你最后那个comment作为临时解决方案
没有默认值时,建议最好不要用nil. 原因有三:
第一, golang中 time.Time 和 nil 是不能直接相等的,time.Time 的默认值不是 nil
第二,如果采用nil为默认值,会导致更新数据库中NOT NULL字段的时候报错“不允许为null”
第三,虽然golang中 '0001-01-01 00:00:00' 和 '0000-00-00 00:00:00' 是一样的,但是在数据库为严格模式下,'0000-00-00' 这类时间会被认为是非法的时间,而'0001-01-01'则不会被认为为非法。
所以,最好的方案是最终还是采用和以前的版本一样的 '0001-01-01 00:00:00',既能保持向后兼容,又能不会受到 sql_mode 的限制。
当然最完美的方案就是,优先按照用户指定的 struct_tag 中的 default value来,用户没有指定,则采用golang的time.Time 的默认值
这样可以正常进行,
但是,这样,任然会报 Error 1048: Column 'end_time' cannot be null
这是为啥???
@eleztian 有可能是一个bug
现在怎么处理啊