Skip to content

Commit 61ee84e

Browse files
authored
ttl,ddl: disable ttl for fk and temp table (#39581) (#39598)
close #39351, close #39364
1 parent 9ba51af commit 61ee84e

File tree

8 files changed

+81
-3
lines changed

8 files changed

+81
-3
lines changed

ddl/ddl_api.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -2116,7 +2116,7 @@ func checkTableInfoValidWithStmt(ctx sessionctx.Context, tbInfo *model.TableInfo
21162116
}
21172117
}
21182118
if tbInfo.TTLInfo != nil {
2119-
if err := checkTTLInfoValid(ctx, tbInfo); err != nil {
2119+
if err := checkTTLInfoValid(ctx, s.Table.Schema, tbInfo); err != nil {
21202120
return errors.Trace(err)
21212121
}
21222122
}
@@ -5371,7 +5371,7 @@ func (d *ddl) AlterTableTTLInfoOrEnable(ctx sessionctx.Context, ident ast.Ident,
53715371
var job *model.Job
53725372
if ttlInfo != nil {
53735373
tblInfo.TTLInfo = ttlInfo
5374-
err = checkTTLInfoValid(ctx, tblInfo)
5374+
err = checkTTLInfoValid(ctx, ident.Schema, tblInfo)
53755375
if err != nil {
53765376
return err
53775377
}

ddl/foreign_key.go

+3
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,9 @@ func checkTableForeignKey(referTblInfo, tblInfo *model.TableInfo, fkInfo *model.
268268
if referTblInfo.TempTableType != model.TempTableNone || tblInfo.TempTableType != model.TempTableNone {
269269
return infoschema.ErrCannotAddForeign
270270
}
271+
if referTblInfo.TTLInfo != nil {
272+
return dbterror.ErrUnsupportedTTLReferencedByFK
273+
}
271274

272275
// check refer columns in parent table.
273276
for i := range fkInfo.RefCols {

ddl/ttl.go

+22-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/pingcap/tidb/parser/format"
2727
"github.com/pingcap/tidb/parser/model"
2828
"github.com/pingcap/tidb/sessionctx"
29+
"github.com/pingcap/tidb/sessiontxn"
2930
"github.com/pingcap/tidb/types"
3031
"github.com/pingcap/tidb/util/dbterror"
3132
)
@@ -83,11 +84,15 @@ func onTTLInfoChange(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err er
8384
return ver, nil
8485
}
8586

86-
func checkTTLInfoValid(ctx sessionctx.Context, tblInfo *model.TableInfo) error {
87+
func checkTTLInfoValid(ctx sessionctx.Context, schema model.CIStr, tblInfo *model.TableInfo) error {
8788
if err := checkTTLIntervalExpr(ctx, tblInfo.TTLInfo); err != nil {
8889
return err
8990
}
9091

92+
if err := checkTTLTableSuitable(ctx, schema, tblInfo); err != nil {
93+
return err
94+
}
95+
9196
return checkTTLInfoColumnType(tblInfo)
9297
}
9398

@@ -119,6 +124,22 @@ func checkTTLInfoColumnType(tblInfo *model.TableInfo) error {
119124
return nil
120125
}
121126

127+
// checkTTLTableSuitable returns whether this table is suitable to be a TTL table
128+
// A temporary table or a parent table referenced by a foreign key cannot be TTL table
129+
func checkTTLTableSuitable(ctx sessionctx.Context, schema model.CIStr, tblInfo *model.TableInfo) error {
130+
if tblInfo.TempTableType != model.TempTableNone {
131+
return dbterror.ErrTempTableNotAllowedWithTTL
132+
}
133+
134+
// checks even when the foreign key check is not enabled, to keep safe
135+
is := sessiontxn.GetTxnManager(ctx).GetTxnInfoSchema()
136+
if referredFK := checkTableHasForeignKeyReferred(is, schema.L, tblInfo.Name.L, nil, true); referredFK != nil {
137+
return dbterror.ErrUnsupportedTTLReferencedByFK
138+
}
139+
140+
return nil
141+
}
142+
122143
func checkDropColumnWithTTLConfig(tblInfo *model.TableInfo, colName string) error {
123144
if tblInfo.TTLInfo != nil {
124145
if tblInfo.TTLInfo.ColumnName.L == colName {

errno/errcode.go

+2
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,8 @@ const (
10401040
ErrUnsupportedColumnInTTLConfig = 8148
10411041
ErrTTLColumnCannotDrop = 8149
10421042
ErrSetTTLEnableForNonTTLTable = 8150
1043+
ErrTempTableNotAllowedWithTTL = 8151
1044+
ErrUnsupportedTTLReferencedByFK = 8152
10431045

10441046
// Error codes used by TiDB ddl package
10451047
ErrUnsupportedDDLOperation = 8200

errno/errname.go

+2
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,8 @@ var MySQLErrName = map[uint16]*mysql.ErrMessage{
10351035
ErrUnsupportedColumnInTTLConfig: mysql.Message("Field '%-.192s' is of a not supported type for TTL config, expect DATETIME, DATE or TIMESTAMP", nil),
10361036
ErrTTLColumnCannotDrop: mysql.Message("Cannot drop column '%-.192s': needed in TTL config", nil),
10371037
ErrSetTTLEnableForNonTTLTable: mysql.Message("Cannot set TTL_ENABLE on a table without TTL config", nil),
1038+
ErrTempTableNotAllowedWithTTL: mysql.Message("Set TTL for temporary table is not allowed", nil),
1039+
ErrUnsupportedTTLReferencedByFK: mysql.Message("Set TTL for a table referenced by foreign key is not allowed", nil),
10381040

10391041
ErrWarnOptimizerHintInvalidInteger: mysql.Message("integer value is out of range in '%s'", nil),
10401042
ErrWarnOptimizerHintUnsupportedHint: mysql.Message("Optimizer hint %s is not supported by TiDB and is ignored", nil),

errors.toml

+10
Original file line numberDiff line numberDiff line change
@@ -1216,6 +1216,16 @@ error = '''
12161216
Cannot set TTL_ENABLE on a table without TTL config
12171217
'''
12181218

1219+
["ddl:8151"]
1220+
error = '''
1221+
Set TTL for temporary table is not allowed
1222+
'''
1223+
1224+
["ddl:8152"]
1225+
error = '''
1226+
Set TTL for a table referenced by foreign key is not allowed
1227+
'''
1228+
12191229
["ddl:8200"]
12201230
error = '''
12211231
Unsupported shard_row_id_bits for table with primary key as row id

executor/ddl_test.go

+36
Original file line numberDiff line numberDiff line change
@@ -1582,3 +1582,39 @@ func TestAlterTTLInfo(t *testing.T) {
15821582

15831583
tk.MustGetErrMsg("ALTER TABLE t TTL_ENABLE = 'OFF'", "[ddl:8150]Cannot set TTL_ENABLE on a table without TTL config")
15841584
}
1585+
1586+
func TestDisableTTLForTempTable(t *testing.T) {
1587+
parser.TTLFeatureGate = true
1588+
1589+
store := testkit.CreateMockStore(t)
1590+
tk := testkit.NewTestKit(t, store)
1591+
tk.MustExec("use test")
1592+
1593+
tk.MustGetDBError("CREATE TEMPORARY TABLE t (created_at datetime) TTL = `created_at` + INTERVAL 5 DAY", dbterror.ErrTempTableNotAllowedWithTTL)
1594+
}
1595+
1596+
func TestDisableTTLForFKParentTable(t *testing.T) {
1597+
parser.TTLFeatureGate = true
1598+
1599+
store := testkit.CreateMockStore(t)
1600+
tk := testkit.NewTestKit(t, store)
1601+
tk.MustExec("use test")
1602+
1603+
// alter ttl for a FK parent table is not allowed
1604+
tk.MustExec("set global tidb_enable_foreign_key='ON'")
1605+
tk.MustExec("CREATE TABLE t (id int primary key, created_at datetime)")
1606+
tk.MustExec("CREATE TABLE t_1 (t_id int, foreign key fk_t_id(t_id) references t(id))")
1607+
tk.MustGetDBError("ALTER TABLE t TTL = created_at + INTERVAL 5 YEAR", dbterror.ErrUnsupportedTTLReferencedByFK)
1608+
tk.MustExec("drop table t,t_1")
1609+
1610+
// refuse to reference TTL key when create table
1611+
tk.MustExec("CREATE TABLE t (id int primary key, created_at datetime) TTL = created_at + INTERVAL 5 YEAR")
1612+
tk.MustGetDBError("CREATE TABLE t_1 (t_id int, foreign key fk_t_id(t_id) references t(id))", dbterror.ErrUnsupportedTTLReferencedByFK)
1613+
tk.MustExec("drop table t")
1614+
1615+
// refuse to add foreign key reference TTL table
1616+
tk.MustExec("CREATE TABLE t (id int primary key, created_at datetime) TTL = created_at + INTERVAL 5 YEAR")
1617+
tk.MustExec("CREATE TABLE t_1 (t_id int)")
1618+
tk.MustGetDBError("ALTER TABLE t_1 ADD FOREIGN KEY fk_t_id(t_id) references t(id)", dbterror.ErrUnsupportedTTLReferencedByFK)
1619+
tk.MustExec("drop table t,t_1")
1620+
}

util/dbterror/ddl_terror.go

+4
Original file line numberDiff line numberDiff line change
@@ -423,4 +423,8 @@ var (
423423
ErrTTLColumnCannotDrop = ClassDDL.NewStd(mysql.ErrTTLColumnCannotDrop)
424424
// ErrSetTTLEnableForNonTTLTable returns when the `TTL_ENABLE` option is set on a non-TTL table
425425
ErrSetTTLEnableForNonTTLTable = ClassDDL.NewStd(mysql.ErrSetTTLEnableForNonTTLTable)
426+
// ErrTempTableNotAllowedWithTTL returns when setting TTL config for a temp table
427+
ErrTempTableNotAllowedWithTTL = ClassDDL.NewStd(mysql.ErrTempTableNotAllowedWithTTL)
428+
// ErrUnsupportedTTLReferencedByFK returns when the TTL config is set for a table referenced by foreign key
429+
ErrUnsupportedTTLReferencedByFK = ClassDDL.NewStd(mysql.ErrUnsupportedTTLReferencedByFK)
426430
)

0 commit comments

Comments
 (0)