Skip to content

Commit

Permalink
ttl,ddl: disable ttl for fk and temp table (#39581) (#39598)
Browse files Browse the repository at this point in the history
close #39351, close #39364
  • Loading branch information
ti-chi-bot authored Dec 19, 2022
1 parent 9ba51af commit 61ee84e
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 3 deletions.
4 changes: 2 additions & 2 deletions ddl/ddl_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2116,7 +2116,7 @@ func checkTableInfoValidWithStmt(ctx sessionctx.Context, tbInfo *model.TableInfo
}
}
if tbInfo.TTLInfo != nil {
if err := checkTTLInfoValid(ctx, tbInfo); err != nil {
if err := checkTTLInfoValid(ctx, s.Table.Schema, tbInfo); err != nil {
return errors.Trace(err)
}
}
Expand Down Expand Up @@ -5371,7 +5371,7 @@ func (d *ddl) AlterTableTTLInfoOrEnable(ctx sessionctx.Context, ident ast.Ident,
var job *model.Job
if ttlInfo != nil {
tblInfo.TTLInfo = ttlInfo
err = checkTTLInfoValid(ctx, tblInfo)
err = checkTTLInfoValid(ctx, ident.Schema, tblInfo)
if err != nil {
return err
}
Expand Down
3 changes: 3 additions & 0 deletions ddl/foreign_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,9 @@ func checkTableForeignKey(referTblInfo, tblInfo *model.TableInfo, fkInfo *model.
if referTblInfo.TempTableType != model.TempTableNone || tblInfo.TempTableType != model.TempTableNone {
return infoschema.ErrCannotAddForeign
}
if referTblInfo.TTLInfo != nil {
return dbterror.ErrUnsupportedTTLReferencedByFK
}

// check refer columns in parent table.
for i := range fkInfo.RefCols {
Expand Down
23 changes: 22 additions & 1 deletion ddl/ttl.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/pingcap/tidb/parser/format"
"github.com/pingcap/tidb/parser/model"
"github.com/pingcap/tidb/sessionctx"
"github.com/pingcap/tidb/sessiontxn"
"github.com/pingcap/tidb/types"
"github.com/pingcap/tidb/util/dbterror"
)
Expand Down Expand Up @@ -83,11 +84,15 @@ func onTTLInfoChange(d *ddlCtx, t *meta.Meta, job *model.Job) (ver int64, err er
return ver, nil
}

func checkTTLInfoValid(ctx sessionctx.Context, tblInfo *model.TableInfo) error {
func checkTTLInfoValid(ctx sessionctx.Context, schema model.CIStr, tblInfo *model.TableInfo) error {
if err := checkTTLIntervalExpr(ctx, tblInfo.TTLInfo); err != nil {
return err
}

if err := checkTTLTableSuitable(ctx, schema, tblInfo); err != nil {
return err
}

return checkTTLInfoColumnType(tblInfo)
}

Expand Down Expand Up @@ -119,6 +124,22 @@ func checkTTLInfoColumnType(tblInfo *model.TableInfo) error {
return nil
}

// checkTTLTableSuitable returns whether this table is suitable to be a TTL table
// A temporary table or a parent table referenced by a foreign key cannot be TTL table
func checkTTLTableSuitable(ctx sessionctx.Context, schema model.CIStr, tblInfo *model.TableInfo) error {
if tblInfo.TempTableType != model.TempTableNone {
return dbterror.ErrTempTableNotAllowedWithTTL
}

// checks even when the foreign key check is not enabled, to keep safe
is := sessiontxn.GetTxnManager(ctx).GetTxnInfoSchema()
if referredFK := checkTableHasForeignKeyReferred(is, schema.L, tblInfo.Name.L, nil, true); referredFK != nil {
return dbterror.ErrUnsupportedTTLReferencedByFK
}

return nil
}

func checkDropColumnWithTTLConfig(tblInfo *model.TableInfo, colName string) error {
if tblInfo.TTLInfo != nil {
if tblInfo.TTLInfo.ColumnName.L == colName {
Expand Down
2 changes: 2 additions & 0 deletions errno/errcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,8 @@ const (
ErrUnsupportedColumnInTTLConfig = 8148
ErrTTLColumnCannotDrop = 8149
ErrSetTTLEnableForNonTTLTable = 8150
ErrTempTableNotAllowedWithTTL = 8151
ErrUnsupportedTTLReferencedByFK = 8152

// Error codes used by TiDB ddl package
ErrUnsupportedDDLOperation = 8200
Expand Down
2 changes: 2 additions & 0 deletions errno/errname.go
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,8 @@ var MySQLErrName = map[uint16]*mysql.ErrMessage{
ErrUnsupportedColumnInTTLConfig: mysql.Message("Field '%-.192s' is of a not supported type for TTL config, expect DATETIME, DATE or TIMESTAMP", nil),
ErrTTLColumnCannotDrop: mysql.Message("Cannot drop column '%-.192s': needed in TTL config", nil),
ErrSetTTLEnableForNonTTLTable: mysql.Message("Cannot set TTL_ENABLE on a table without TTL config", nil),
ErrTempTableNotAllowedWithTTL: mysql.Message("Set TTL for temporary table is not allowed", nil),
ErrUnsupportedTTLReferencedByFK: mysql.Message("Set TTL for a table referenced by foreign key is not allowed", nil),

ErrWarnOptimizerHintInvalidInteger: mysql.Message("integer value is out of range in '%s'", nil),
ErrWarnOptimizerHintUnsupportedHint: mysql.Message("Optimizer hint %s is not supported by TiDB and is ignored", nil),
Expand Down
10 changes: 10 additions & 0 deletions errors.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,16 @@ error = '''
Cannot set TTL_ENABLE on a table without TTL config
'''

["ddl:8151"]
error = '''
Set TTL for temporary table is not allowed
'''

["ddl:8152"]
error = '''
Set TTL for a table referenced by foreign key is not allowed
'''

["ddl:8200"]
error = '''
Unsupported shard_row_id_bits for table with primary key as row id
Expand Down
36 changes: 36 additions & 0 deletions executor/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1582,3 +1582,39 @@ func TestAlterTTLInfo(t *testing.T) {

tk.MustGetErrMsg("ALTER TABLE t TTL_ENABLE = 'OFF'", "[ddl:8150]Cannot set TTL_ENABLE on a table without TTL config")
}

func TestDisableTTLForTempTable(t *testing.T) {
parser.TTLFeatureGate = true

store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")

tk.MustGetDBError("CREATE TEMPORARY TABLE t (created_at datetime) TTL = `created_at` + INTERVAL 5 DAY", dbterror.ErrTempTableNotAllowedWithTTL)
}

func TestDisableTTLForFKParentTable(t *testing.T) {
parser.TTLFeatureGate = true

store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")

// alter ttl for a FK parent table is not allowed
tk.MustExec("set global tidb_enable_foreign_key='ON'")
tk.MustExec("CREATE TABLE t (id int primary key, created_at datetime)")
tk.MustExec("CREATE TABLE t_1 (t_id int, foreign key fk_t_id(t_id) references t(id))")
tk.MustGetDBError("ALTER TABLE t TTL = created_at + INTERVAL 5 YEAR", dbterror.ErrUnsupportedTTLReferencedByFK)
tk.MustExec("drop table t,t_1")

// refuse to reference TTL key when create table
tk.MustExec("CREATE TABLE t (id int primary key, created_at datetime) TTL = created_at + INTERVAL 5 YEAR")
tk.MustGetDBError("CREATE TABLE t_1 (t_id int, foreign key fk_t_id(t_id) references t(id))", dbterror.ErrUnsupportedTTLReferencedByFK)
tk.MustExec("drop table t")

// refuse to add foreign key reference TTL table
tk.MustExec("CREATE TABLE t (id int primary key, created_at datetime) TTL = created_at + INTERVAL 5 YEAR")
tk.MustExec("CREATE TABLE t_1 (t_id int)")
tk.MustGetDBError("ALTER TABLE t_1 ADD FOREIGN KEY fk_t_id(t_id) references t(id)", dbterror.ErrUnsupportedTTLReferencedByFK)
tk.MustExec("drop table t,t_1")
}
4 changes: 4 additions & 0 deletions util/dbterror/ddl_terror.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,4 +423,8 @@ var (
ErrTTLColumnCannotDrop = ClassDDL.NewStd(mysql.ErrTTLColumnCannotDrop)
// ErrSetTTLEnableForNonTTLTable returns when the `TTL_ENABLE` option is set on a non-TTL table
ErrSetTTLEnableForNonTTLTable = ClassDDL.NewStd(mysql.ErrSetTTLEnableForNonTTLTable)
// ErrTempTableNotAllowedWithTTL returns when setting TTL config for a temp table
ErrTempTableNotAllowedWithTTL = ClassDDL.NewStd(mysql.ErrTempTableNotAllowedWithTTL)
// ErrUnsupportedTTLReferencedByFK returns when the TTL config is set for a table referenced by foreign key
ErrUnsupportedTTLReferencedByFK = ClassDDL.NewStd(mysql.ErrUnsupportedTTLReferencedByFK)
)

0 comments on commit 61ee84e

Please sign in to comment.