From e93d0611925514cd0a0c7f5f60efbb492b27fd27 Mon Sep 17 00:00:00 2001 From: tangenta Date: Tue, 10 Sep 2019 10:34:00 +0800 Subject: [PATCH 1/6] disallow dropping auto_increment column attribute --- ddl/db_integration_test.go | 11 +++++------ ddl/ddl_api.go | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/ddl/db_integration_test.go b/ddl/db_integration_test.go index 1e0501ce20b90..0a4dd3f9a2fa6 100644 --- a/ddl/db_integration_test.go +++ b/ddl/db_integration_test.go @@ -1534,7 +1534,7 @@ func (s *testIntegrationSuite3) TestAlterColumn(c *C) { expected = "CREATE TABLE `mc` (\n `a` bigint(20) NOT NULL,\n `b` bigint(20) DEFAULT NULL,\n `c` bigint(20) DEFAULT NULL,\n PRIMARY KEY (`a`),\n UNIQUE KEY `c` (`c`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" c.Assert(createSQL, Equals, expected) - // Dropping or keeping auto_increment is allowed, however adding is not allowed. + // Both dropping and adding auto_increment is not allowed. s.tk.MustExec("drop table if exists mc") s.tk.MustExec("create table mc(a int key auto_increment, b int)") s.tk.MustExec("alter table mc modify column a bigint auto_increment") // Keeps auto_increment @@ -1542,11 +1542,10 @@ func (s *testIntegrationSuite3) TestAlterColumn(c *C) { createSQL = result.Rows()[0][1] expected = "CREATE TABLE `mc` (\n `a` bigint(20) NOT NULL AUTO_INCREMENT,\n `b` int(11) DEFAULT NULL,\n PRIMARY KEY (`a`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" c.Assert(createSQL, Equals, expected) - s.tk.MustExec("alter table mc modify column a bigint") // Drops auto_increment - result = s.tk.MustQuery("show create table mc") - createSQL = result.Rows()[0][1] - expected = "CREATE TABLE `mc` (\n `a` bigint(20) NOT NULL,\n `b` int(11) DEFAULT NULL,\n PRIMARY KEY (`a`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" - c.Assert(createSQL, Equals, expected) + _, err = s.tk.Exec("alter table mc modify column a bigint") // Drops auto_increment + c.Assert(err, NotNil) + s.tk.MustExec("drop table mc") + s.tk.MustExec("create table mc(a bigint)") _, err = s.tk.Exec("alter table mc modify column a bigint auto_increment") // Adds auto_increment should throw error c.Assert(err, NotNil) diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index f9c6049f2d6ac..efad15c71224e 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -2687,8 +2687,8 @@ func (d *ddl) getModifiableColumnJob(ctx sessionctx.Context, ident ast.Ident, or } // We don't support modifying column from not_auto_increment to auto_increment. - if !mysql.HasAutoIncrementFlag(col.Flag) && mysql.HasAutoIncrementFlag(newCol.Flag) { - return nil, errUnsupportedModifyColumn.GenWithStackByArgs("set auto_increment") + if mysql.HasAutoIncrementFlag(col.Flag) != mysql.HasAutoIncrementFlag(newCol.Flag) { + return nil, errUnsupportedModifyColumn.GenWithStackByArgs("change auto_increment attribute") } // We support modifying the type definitions of 'null' to 'not null' now. From 5648a8a5ec35702b7271fc22d514abd70844fa5e Mon Sep 17 00:00:00 2001 From: tangenta Date: Tue, 10 Sep 2019 10:38:12 +0800 Subject: [PATCH 2/6] fix typo --- ddl/db_integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ddl/db_integration_test.go b/ddl/db_integration_test.go index 0a4dd3f9a2fa6..92d3dc8329486 100644 --- a/ddl/db_integration_test.go +++ b/ddl/db_integration_test.go @@ -1534,7 +1534,7 @@ func (s *testIntegrationSuite3) TestAlterColumn(c *C) { expected = "CREATE TABLE `mc` (\n `a` bigint(20) NOT NULL,\n `b` bigint(20) DEFAULT NULL,\n `c` bigint(20) DEFAULT NULL,\n PRIMARY KEY (`a`),\n UNIQUE KEY `c` (`c`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" c.Assert(createSQL, Equals, expected) - // Both dropping and adding auto_increment is not allowed. + // Both dropping and adding auto_increment are not allowed. s.tk.MustExec("drop table if exists mc") s.tk.MustExec("create table mc(a int key auto_increment, b int)") s.tk.MustExec("alter table mc modify column a bigint auto_increment") // Keeps auto_increment From 609c2580cae07f269e290e7381438521e6f3e35e Mon Sep 17 00:00:00 2001 From: tangenta Date: Tue, 10 Sep 2019 11:59:37 +0800 Subject: [PATCH 3/6] add AllowDropAutoInc to session variables --- ddl/db_integration_test.go | 13 +++++++++---- ddl/ddl_api.go | 8 ++++++-- sessionctx/variable/session.go | 6 ++++++ sessionctx/variable/sysvar.go | 1 + sessionctx/variable/tidb_vars.go | 4 ++++ sessionctx/variable/varsutil.go | 8 ++++++++ 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/ddl/db_integration_test.go b/ddl/db_integration_test.go index 92d3dc8329486..c2ebd15d5ee69 100644 --- a/ddl/db_integration_test.go +++ b/ddl/db_integration_test.go @@ -1534,7 +1534,7 @@ func (s *testIntegrationSuite3) TestAlterColumn(c *C) { expected = "CREATE TABLE `mc` (\n `a` bigint(20) NOT NULL,\n `b` bigint(20) DEFAULT NULL,\n `c` bigint(20) DEFAULT NULL,\n PRIMARY KEY (`a`),\n UNIQUE KEY `c` (`c`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" c.Assert(createSQL, Equals, expected) - // Both dropping and adding auto_increment are not allowed. + // Dropping or keeping auto_increment is allowed, however adding is not allowed. s.tk.MustExec("drop table if exists mc") s.tk.MustExec("create table mc(a int key auto_increment, b int)") s.tk.MustExec("alter table mc modify column a bigint auto_increment") // Keeps auto_increment @@ -1542,10 +1542,15 @@ func (s *testIntegrationSuite3) TestAlterColumn(c *C) { createSQL = result.Rows()[0][1] expected = "CREATE TABLE `mc` (\n `a` bigint(20) NOT NULL AUTO_INCREMENT,\n `b` int(11) DEFAULT NULL,\n PRIMARY KEY (`a`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" c.Assert(createSQL, Equals, expected) - _, err = s.tk.Exec("alter table mc modify column a bigint") // Drops auto_increment + _, err = s.tk.Exec("alter table mc modify column a bigint") // Droppping auto_increment is not allow when @@tidb_allow_drop_auto_inc == 'off' c.Assert(err, NotNil) - s.tk.MustExec("drop table mc") - s.tk.MustExec("create table mc(a bigint)") + s.tk.MustExec("set @@tidb_allow_drop_auto_inc = on") + s.tk.MustExec("alter table mc modify column a bigint") // Dropping auto_increment is ok when @@tidb_allow_drop_auto_inc == 'on' + result = s.tk.MustQuery("show create table mc") + createSQL = result.Rows()[0][1] + expected = "CREATE TABLE `mc` (\n `a` bigint(20) NOT NULL,\n `b` int(11) DEFAULT NULL,\n PRIMARY KEY (`a`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" + c.Assert(createSQL, Equals, expected) + _, err = s.tk.Exec("alter table mc modify column a bigint auto_increment") // Adds auto_increment should throw error c.Assert(err, NotNil) diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index efad15c71224e..c7d71d3d51519 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -2687,8 +2687,12 @@ func (d *ddl) getModifiableColumnJob(ctx sessionctx.Context, ident ast.Ident, or } // We don't support modifying column from not_auto_increment to auto_increment. - if mysql.HasAutoIncrementFlag(col.Flag) != mysql.HasAutoIncrementFlag(newCol.Flag) { - return nil, errUnsupportedModifyColumn.GenWithStackByArgs("change auto_increment attribute") + if !mysql.HasAutoIncrementFlag(col.Flag) && mysql.HasAutoIncrementFlag(newCol.Flag) { + return nil, errUnsupportedModifyColumn.GenWithStackByArgs("set auto_increment") + } + // Disallow modifying column from auto_increment to not auto_increment if the session variable `AllowDropAutoInc` is false. + if !ctx.GetSessionVars().AllowDropAutoInc && mysql.HasAutoIncrementFlag(col.Flag) && !mysql.HasAutoIncrementFlag(newCol.Flag) { + return nil, errUnsupportedModifyColumn.GenWithStackByArgs("drop auto_increment column attribute") } // We support modifying the type definitions of 'null' to 'not null' now. diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index 82517b454194d..7853106a9dac4 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -417,6 +417,9 @@ type SessionVars struct { // PrevStmt is used to store the previous executed statement in the current session. PrevStmt string + + // AllowDropAutoInc indicates whether a user can drop the auto_increment column attribute or not. + AllowDropAutoInc bool } // ConnectionInfo present connection used by audit. @@ -473,6 +476,7 @@ func NewSessionVars() *SessionVars { EnableIndexMerge: false, EnableNoopFuncs: DefTiDBEnableNoopFuncs, ReplicaRead: kv.ReplicaReadLeader, + AllowDropAutoInc: DefTiDBAllowDropAutoInc, } vars.Concurrency = Concurrency{ IndexLookupConcurrency: DefIndexLookupConcurrency, @@ -857,6 +861,8 @@ func (s *SessionVars) SetSystemVar(name string, val string) error { } else if strings.EqualFold(val, "leader") || len(val) == 0 { s.ReplicaRead = kv.ReplicaReadLeader } + case TiDBAllowDropAutoInc: + s.AllowDropAutoInc = TiDBOptOn(val) } s.systems[name] = val return nil diff --git a/sessionctx/variable/sysvar.go b/sessionctx/variable/sysvar.go index e1638c704da38..1ecd40b3c44c3 100644 --- a/sessionctx/variable/sysvar.go +++ b/sessionctx/variable/sysvar.go @@ -706,6 +706,7 @@ var defaultSysVars = []*SysVar{ {ScopeSession, TiDBExpensiveQueryTimeThreshold, strconv.Itoa(DefTiDBExpensiveQueryTimeThreshold)}, {ScopeGlobal | ScopeSession, TiDBEnableNoopFuncs, BoolToIntStr(DefTiDBEnableNoopFuncs)}, {ScopeSession, TiDBReplicaRead, "leader"}, + {ScopeSession, TiDBAllowDropAutoInc, BoolToIntStr(DefTiDBAllowDropAutoInc)}, } // SynonymsSysVariables is synonyms of system variables. diff --git a/sessionctx/variable/tidb_vars.go b/sessionctx/variable/tidb_vars.go index 2db918591efd3..82e9d2c47aba5 100644 --- a/sessionctx/variable/tidb_vars.go +++ b/sessionctx/variable/tidb_vars.go @@ -145,6 +145,9 @@ const ( // TiDBReplicaRead is used for reading data from replicas, followers for example. TiDBReplicaRead = "tidb_replica_read" + + // TiDBAllowDropAutoInc indicates whether a user can drop the auto_increment column attribute or not. + TiDBAllowDropAutoInc = "tidb_allow_drop_auto_inc" ) // TiDB system variable names that both in session and global scope. @@ -358,6 +361,7 @@ const ( DefTiDBWaitSplitRegionFinish = true DefWaitSplitRegionTimeout = 300 // 300s DefTiDBEnableNoopFuncs = false + DefTiDBAllowDropAutoInc = false ) // Process global variables. diff --git a/sessionctx/variable/varsutil.go b/sessionctx/variable/varsutil.go index 835f57ea3713a..3f054fddfb7b9 100644 --- a/sessionctx/variable/varsutil.go +++ b/sessionctx/variable/varsutil.go @@ -574,6 +574,14 @@ func ValidateSetSystemVar(vars *SessionVars, name string, value string) (string, default: return value, ErrWrongValueForVar.GenWithStackByArgs(TiDBTxnMode, value) } + case TiDBAllowDropAutoInc: + switch { + case strings.EqualFold(value, "ON") || value == "1": + return "on", nil + case strings.EqualFold(value, "OFF") || value == "0": + return "off", nil + } + return value, ErrWrongValueForVar.GenWithStackByArgs(name, value) } return value, nil } From 933d1ac46dbb4ccc460159d512b37f12066b2d65 Mon Sep 17 00:00:00 2001 From: tangenta Date: Tue, 10 Sep 2019 14:13:45 +0800 Subject: [PATCH 4/6] address comment --- ddl/ddl_api.go | 6 +++--- sessionctx/variable/session.go | 8 ++++---- sessionctx/variable/sysvar.go | 2 +- sessionctx/variable/tidb_vars.go | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ddl/ddl_api.go b/ddl/ddl_api.go index c7d71d3d51519..20d0d1a67f7f0 100644 --- a/ddl/ddl_api.go +++ b/ddl/ddl_api.go @@ -2690,9 +2690,9 @@ func (d *ddl) getModifiableColumnJob(ctx sessionctx.Context, ident ast.Ident, or if !mysql.HasAutoIncrementFlag(col.Flag) && mysql.HasAutoIncrementFlag(newCol.Flag) { return nil, errUnsupportedModifyColumn.GenWithStackByArgs("set auto_increment") } - // Disallow modifying column from auto_increment to not auto_increment if the session variable `AllowDropAutoInc` is false. - if !ctx.GetSessionVars().AllowDropAutoInc && mysql.HasAutoIncrementFlag(col.Flag) && !mysql.HasAutoIncrementFlag(newCol.Flag) { - return nil, errUnsupportedModifyColumn.GenWithStackByArgs("drop auto_increment column attribute") + // Disallow modifying column from auto_increment to not auto_increment if the session variable `AllowRemoveAutoInc` is false. + if !ctx.GetSessionVars().AllowRemoveAutoInc && mysql.HasAutoIncrementFlag(col.Flag) && !mysql.HasAutoIncrementFlag(newCol.Flag) { + return nil, errUnsupportedModifyColumn.GenWithStackByArgs("to remove auto_increment without @@tidb_allow_remove_auto_inc enabled") } // We support modifying the type definitions of 'null' to 'not null' now. diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index 7853106a9dac4..66970b58e9b79 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -418,8 +418,8 @@ type SessionVars struct { // PrevStmt is used to store the previous executed statement in the current session. PrevStmt string - // AllowDropAutoInc indicates whether a user can drop the auto_increment column attribute or not. - AllowDropAutoInc bool + // AllowRemoveAutoInc indicates whether a user can drop the auto_increment column attribute or not. + AllowRemoveAutoInc bool } // ConnectionInfo present connection used by audit. @@ -476,7 +476,7 @@ func NewSessionVars() *SessionVars { EnableIndexMerge: false, EnableNoopFuncs: DefTiDBEnableNoopFuncs, ReplicaRead: kv.ReplicaReadLeader, - AllowDropAutoInc: DefTiDBAllowDropAutoInc, + AllowRemoveAutoInc: DefTiDBAllowRemoveAutoInc, } vars.Concurrency = Concurrency{ IndexLookupConcurrency: DefIndexLookupConcurrency, @@ -862,7 +862,7 @@ func (s *SessionVars) SetSystemVar(name string, val string) error { s.ReplicaRead = kv.ReplicaReadLeader } case TiDBAllowDropAutoInc: - s.AllowDropAutoInc = TiDBOptOn(val) + s.AllowRemoveAutoInc = TiDBOptOn(val) } s.systems[name] = val return nil diff --git a/sessionctx/variable/sysvar.go b/sessionctx/variable/sysvar.go index 1ecd40b3c44c3..3acc576bcf8bd 100644 --- a/sessionctx/variable/sysvar.go +++ b/sessionctx/variable/sysvar.go @@ -706,7 +706,7 @@ var defaultSysVars = []*SysVar{ {ScopeSession, TiDBExpensiveQueryTimeThreshold, strconv.Itoa(DefTiDBExpensiveQueryTimeThreshold)}, {ScopeGlobal | ScopeSession, TiDBEnableNoopFuncs, BoolToIntStr(DefTiDBEnableNoopFuncs)}, {ScopeSession, TiDBReplicaRead, "leader"}, - {ScopeSession, TiDBAllowDropAutoInc, BoolToIntStr(DefTiDBAllowDropAutoInc)}, + {ScopeSession, TiDBAllowDropAutoInc, BoolToIntStr(DefTiDBAllowRemoveAutoInc)}, } // SynonymsSysVariables is synonyms of system variables. diff --git a/sessionctx/variable/tidb_vars.go b/sessionctx/variable/tidb_vars.go index 82e9d2c47aba5..7c9cd6d41fc69 100644 --- a/sessionctx/variable/tidb_vars.go +++ b/sessionctx/variable/tidb_vars.go @@ -147,7 +147,7 @@ const ( TiDBReplicaRead = "tidb_replica_read" // TiDBAllowDropAutoInc indicates whether a user can drop the auto_increment column attribute or not. - TiDBAllowDropAutoInc = "tidb_allow_drop_auto_inc" + TiDBAllowDropAutoInc = "tidb_allow_remove_auto_inc" ) // TiDB system variable names that both in session and global scope. @@ -361,7 +361,7 @@ const ( DefTiDBWaitSplitRegionFinish = true DefWaitSplitRegionTimeout = 300 // 300s DefTiDBEnableNoopFuncs = false - DefTiDBAllowDropAutoInc = false + DefTiDBAllowRemoveAutoInc = false ) // Process global variables. From e6f79dacd2b223c2c0794b5ed844b3a597f7e1c7 Mon Sep 17 00:00:00 2001 From: tangenta Date: Tue, 10 Sep 2019 14:16:35 +0800 Subject: [PATCH 5/6] rename TiDBAllowDropAutoInc --- sessionctx/variable/session.go | 2 +- sessionctx/variable/sysvar.go | 2 +- sessionctx/variable/tidb_vars.go | 4 ++-- sessionctx/variable/varsutil.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index 66970b58e9b79..4a02e21ba2600 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -861,7 +861,7 @@ func (s *SessionVars) SetSystemVar(name string, val string) error { } else if strings.EqualFold(val, "leader") || len(val) == 0 { s.ReplicaRead = kv.ReplicaReadLeader } - case TiDBAllowDropAutoInc: + case TiDBAllowRemoveAutoInc: s.AllowRemoveAutoInc = TiDBOptOn(val) } s.systems[name] = val diff --git a/sessionctx/variable/sysvar.go b/sessionctx/variable/sysvar.go index 3acc576bcf8bd..e28182eba7faf 100644 --- a/sessionctx/variable/sysvar.go +++ b/sessionctx/variable/sysvar.go @@ -706,7 +706,7 @@ var defaultSysVars = []*SysVar{ {ScopeSession, TiDBExpensiveQueryTimeThreshold, strconv.Itoa(DefTiDBExpensiveQueryTimeThreshold)}, {ScopeGlobal | ScopeSession, TiDBEnableNoopFuncs, BoolToIntStr(DefTiDBEnableNoopFuncs)}, {ScopeSession, TiDBReplicaRead, "leader"}, - {ScopeSession, TiDBAllowDropAutoInc, BoolToIntStr(DefTiDBAllowRemoveAutoInc)}, + {ScopeSession, TiDBAllowRemoveAutoInc, BoolToIntStr(DefTiDBAllowRemoveAutoInc)}, } // SynonymsSysVariables is synonyms of system variables. diff --git a/sessionctx/variable/tidb_vars.go b/sessionctx/variable/tidb_vars.go index 7c9cd6d41fc69..48a454cac6734 100644 --- a/sessionctx/variable/tidb_vars.go +++ b/sessionctx/variable/tidb_vars.go @@ -146,8 +146,8 @@ const ( // TiDBReplicaRead is used for reading data from replicas, followers for example. TiDBReplicaRead = "tidb_replica_read" - // TiDBAllowDropAutoInc indicates whether a user can drop the auto_increment column attribute or not. - TiDBAllowDropAutoInc = "tidb_allow_remove_auto_inc" + // TiDBAllowRemoveAutoInc indicates whether a user can drop the auto_increment column attribute or not. + TiDBAllowRemoveAutoInc = "tidb_allow_remove_auto_inc" ) // TiDB system variable names that both in session and global scope. diff --git a/sessionctx/variable/varsutil.go b/sessionctx/variable/varsutil.go index 3f054fddfb7b9..563f6ceb031d4 100644 --- a/sessionctx/variable/varsutil.go +++ b/sessionctx/variable/varsutil.go @@ -574,7 +574,7 @@ func ValidateSetSystemVar(vars *SessionVars, name string, value string) (string, default: return value, ErrWrongValueForVar.GenWithStackByArgs(TiDBTxnMode, value) } - case TiDBAllowDropAutoInc: + case TiDBAllowRemoveAutoInc: switch { case strings.EqualFold(value, "ON") || value == "1": return "on", nil From 8bb1d1450b0d4042356b47ea93743416389ef409 Mon Sep 17 00:00:00 2001 From: tangenta Date: Tue, 10 Sep 2019 14:27:02 +0800 Subject: [PATCH 6/6] update test --- ddl/db_integration_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ddl/db_integration_test.go b/ddl/db_integration_test.go index c2ebd15d5ee69..ab40d7790c883 100644 --- a/ddl/db_integration_test.go +++ b/ddl/db_integration_test.go @@ -1542,10 +1542,10 @@ func (s *testIntegrationSuite3) TestAlterColumn(c *C) { createSQL = result.Rows()[0][1] expected = "CREATE TABLE `mc` (\n `a` bigint(20) NOT NULL AUTO_INCREMENT,\n `b` int(11) DEFAULT NULL,\n PRIMARY KEY (`a`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin" c.Assert(createSQL, Equals, expected) - _, err = s.tk.Exec("alter table mc modify column a bigint") // Droppping auto_increment is not allow when @@tidb_allow_drop_auto_inc == 'off' + _, err = s.tk.Exec("alter table mc modify column a bigint") // Droppping auto_increment is not allow when @@tidb_allow_remove_auto_inc == 'off' c.Assert(err, NotNil) - s.tk.MustExec("set @@tidb_allow_drop_auto_inc = on") - s.tk.MustExec("alter table mc modify column a bigint") // Dropping auto_increment is ok when @@tidb_allow_drop_auto_inc == 'on' + s.tk.MustExec("set @@tidb_allow_remove_auto_inc = on") + s.tk.MustExec("alter table mc modify column a bigint") // Dropping auto_increment is ok when @@tidb_allow_remove_auto_inc == 'on' result = s.tk.MustQuery("show create table mc") createSQL = result.Rows()[0][1] expected = "CREATE TABLE `mc` (\n `a` bigint(20) NOT NULL,\n `b` int(11) DEFAULT NULL,\n PRIMARY KEY (`a`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"