-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ddl:In non-strict sql mode, fix column type is text /blob/json default value null not processed. #7230
Conversation
…ue null not processed.
ddl/ddl_api.go
Outdated
@@ -244,10 +244,15 @@ func buildColumnAndConstraint(ctx sessionctx.Context, offset int, | |||
|
|||
// checkColumnCantHaveDefaultValue checks the column can have value as default or not. | |||
// Now, TEXT/BLOB/JSON can't have not null value as default. | |||
func checkColumnCantHaveDefaultValue(col *table.Column, value interface{}) (err error) { | |||
func checkColumnCantHaveDefaultValue(ctx sessionctx.Context, col *table.Column, value interface{}) (err error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about this?
func checkColumnCantHaveDefaultValue(ctx sessionctx.Context, col *table.Column, value interface{}) (error, bool, interface{}) {
if value != nil && (col.Tp == mysql.TypeJSON ||
col.Tp == mysql.TypeTinyBlob || col.Tp == mysql.TypeMediumBlob ||
col.Tp == mysql.TypeLongBlob || col.Tp == mysql.TypeBlob) {
if !ctx.GetSessionVars().SQLMode.HasStrictMode() && value == "" {
sc := ctx.GetSessionVars().StmtCtx
sc.AppendWarning(errBlobCantHaveDefault.GenByArgs(col.Name.O))
if col.Tp == mysql.TypeJSON {
return nil, true, `null`
}
return nil, false, nil
}
// TEXT/BLOB/JSON can't have not null default values.
return errBlobCantHaveDefault.GenByArgs(col.Name.O), false, nil
}
return nil, true, value
}
and in line 322:
err, hasDefaultValue, value = checkColumnCantHaveDefaultValue(ctx, col, value);
if err != nil {
return nil, nil, errors.Trace(err)
}
if hasDefaultValue {
col.DefaultValue = value
removeOnUpdateNowFlag(col)
}
and in line 1443
err, hasDefaultValue, value = checkColumnCantHaveDefaultValue(ctx, col, value)
if err != nil {
return errors.Trace(err)
}
if hasDefaultValue {
col.DefaultValue = value
}
then we can remove ignoreNullDefaultValuesForColumns
function
is := domain.GetDomain(ctx).InfoSchema() | ||
tblInfo, err := is.TableByName(model.NewCIStr("test"), model.NewCIStr("text_default_text")) | ||
c.Assert(err, IsNil) | ||
c.Assert(tblInfo.Meta().Columns[0].DefaultValue, Equals, "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the DefaultValue
should be nil
, not be ""
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DefaultValue
should be ""
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the default value of the column is null, DefaultValue
is ""
.
ddl/db_test.go
Outdated
is = domain.GetDomain(ctx).InfoSchema() | ||
tblInfo, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("text_default_blob")) | ||
c.Assert(err, IsNil) | ||
c.Assert(tblInfo.Meta().Columns[0].DefaultValue, Equals, "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have explained.
ddl/db_test.go
Outdated
is = domain.GetDomain(ctx).InfoSchema() | ||
tblInfo, err = is.TableByName(model.NewCIStr("test"), model.NewCIStr("text_default_json")) | ||
c.Assert(err, IsNil) | ||
c.Assert(tblInfo.Meta().Columns[0].DefaultValue, Equals, `null`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
I got it, It should be null....
ddl/ddl_api.go
Outdated
// In non-strict SQL mode, if the column type is json and the default value is null, it is initialized to an empty array. | ||
if col.Tp == mysql.TypeJSON && value == "" { | ||
col.DefaultValue = `null` | ||
hasDefaultValue = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this line can be remove
ddl/ddl_api.go
Outdated
if value != nil && (col.Tp == mysql.TypeJSON || | ||
col.Tp == mysql.TypeTinyBlob || col.Tp == mysql.TypeMediumBlob || | ||
col.Tp == mysql.TypeLongBlob || col.Tp == mysql.TypeBlob) { | ||
if !ctx.GetSessionVars().SQLMode.HasStrictMode() && value == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What will happen when SQL mode change, create a table with SQLMode A and use it wit SQLMode B ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In non-strict SQL mode, if the default value of the column is an empty string, can ignore it, the table can be created successfully.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand.
/run-all-tests |
|
||
s.tk.MustExec("set sql_mode='';") | ||
s.tk.MustExec("drop table if exists text_default_text;") | ||
s.tk.MustExec("create table text_default_text(c1 text not null default '');") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add test about show create table text_default_text
and show create table test_text_default_value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@winkyao Done.
dbf0876
to
40aad3e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
/rebuild |
/run-all-tests |
@tiancaiamao @winkyao PTAL. |
ddl/ddl_api.go
Outdated
if value != nil && (col.Tp == mysql.TypeJSON || | ||
col.Tp == mysql.TypeTinyBlob || col.Tp == mysql.TypeMediumBlob || | ||
col.Tp == mysql.TypeLongBlob || col.Tp == mysql.TypeBlob) { | ||
if !ctx.GetSessionVars().SQLMode.HasStrictMode() && value == "" { | ||
// In non-strict SQL mode, if the default value of the column is an empty string, can ignore it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/can ignore it/the default value can be ignored
ddl/ddl_api.go
Outdated
if value != nil && (col.Tp == mysql.TypeJSON || | ||
col.Tp == mysql.TypeTinyBlob || col.Tp == mysql.TypeMediumBlob || | ||
col.Tp == mysql.TypeLongBlob || col.Tp == mysql.TypeBlob) { | ||
if !ctx.GetSessionVars().SQLMode.HasStrictMode() && value == "" { | ||
// In non-strict SQL mode, if the default value of the column is an empty string, can ignore it. | ||
if col.Tp == mysql.TypeBlob || col.Tp == mysql.TypeLongBlob && value == "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
&& value == ""
is redundant because it has been tested at line 261
ddl/ddl_api.go
Outdated
@@ -253,14 +253,24 @@ func buildColumnAndConstraint(ctx sessionctx.Context, offset int, | |||
|
|||
// checkColumnCantHaveDefaultValue checks the column can have value as default or not. | |||
// Now, TEXT/BLOB/JSON can't have not null value as default. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update comment... in strict mode, TEXT/BLOB/JSON can't have not null value as default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO, this function signature is very strange:
why checkColumnCantHaveDefaultValue
return a boolean value hasDefaultValue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do agree with tiancaiamao.
ddl/db_test.go
Outdated
s.tk.MustExec("drop table if exists text_default_text;") | ||
s.tk.MustExec("create table text_default_text(c1 text not null default '');") | ||
s.tk.MustQuery(`show create table text_default_text`).Check(testutil.RowsWithSep("|", | ||
""+ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove this line?
ddl/ddl_api.go
Outdated
} | ||
sc := ctx.GetSessionVars().StmtCtx | ||
sc.AppendWarning(errBlobCantHaveDefault.GenByArgs(col.Name.O)) | ||
return hasDefaultValue, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can return a specific error here, then remove hasDefaultValue. You can test the specific error in the caller to set the hasDefaultValue.
@tiancaiamao @winkyao PTAL. |
ddl/ddl_api.go
Outdated
sc.AppendWarning(errBlobCantHaveDefault.GenByArgs(col.Name.O)) | ||
return hasDefaultValue, value, nil | ||
} | ||
// In strict SQL mode. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In strict SQL mode or default value is not an empty string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reset LGTM
LGTM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
What have you changed? (mandatory)
master branch
sql-mode-compatible branch
What is the type of the changes? (mandatory)
Improvement
How has this PR been tested? (mandatory)
Unit tests.
Does this PR affect documentation (docs/docs-cn) update? (mandatory)
No
Does this PR affect tidb-ansible update? (mandatory)
No
Does this PR need to be added to the release notes? (mandatory)
No