From 6a4b909c7dd3524eb5827d5fa0ec3787e49987d5 Mon Sep 17 00:00:00 2001 From: YangKeao Date: Thu, 1 Dec 2022 05:18:01 -0500 Subject: [PATCH] parser: add global variable to control ttl syntax (#39483) close pingcap/tidb#39482 --- executor/ddl_test.go | 5 +++++ executor/showtest/BUILD.bazel | 1 + executor/showtest/show_test.go | 3 +++ parser/BUILD.bazel | 1 + parser/ast/ddl_test.go | 3 +++ parser/parser.go | 12 ++++++++++++ parser/parser.y | 12 ++++++++++++ parser/parser_test.go | 20 ++++++++++++++++++++ parser/ttlfeaturegate.go | 17 +++++++++++++++++ ttl/cache/BUILD.bazel | 1 + ttl/cache/table_test.go | 5 +++++ 11 files changed, 80 insertions(+) create mode 100644 parser/ttlfeaturegate.go diff --git a/executor/ddl_test.go b/executor/ddl_test.go index d4e9ed4c1b425..9128d52bedca9 100644 --- a/executor/ddl_test.go +++ b/executor/ddl_test.go @@ -34,6 +34,7 @@ import ( "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/meta" "github.com/pingcap/tidb/meta/autoid" + "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" "github.com/pingcap/tidb/parser/terror" @@ -1524,6 +1525,8 @@ func TestRenameMultiTables(t *testing.T) { } func TestCreateTableWithTTL(t *testing.T) { + parser.TTLFeatureGate = true + store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) tk.MustExec("use test") @@ -1543,6 +1546,8 @@ func TestCreateTableWithTTL(t *testing.T) { } func TestAlterTTLInfo(t *testing.T) { + parser.TTLFeatureGate = true + store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) tk.MustExec("use test") diff --git a/executor/showtest/BUILD.bazel b/executor/showtest/BUILD.bazel index 807e00c8e88ec..aa61ad5bacd3b 100644 --- a/executor/showtest/BUILD.bazel +++ b/executor/showtest/BUILD.bazel @@ -15,6 +15,7 @@ go_test( "//executor", "//infoschema", "//meta/autoid", + "//parser", "//parser/auth", "//parser/model", "//parser/mysql", diff --git a/executor/showtest/show_test.go b/executor/showtest/show_test.go index 4f7157b190488..27ac4138e57ec 100644 --- a/executor/showtest/show_test.go +++ b/executor/showtest/show_test.go @@ -23,6 +23,7 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/tidb/executor" "github.com/pingcap/tidb/infoschema" + "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/parser/mysql" @@ -1991,6 +1992,8 @@ func TestShowLimitReturnRow(t *testing.T) { } func TestShowTTLOption(t *testing.T) { + parser.TTLFeatureGate = true + store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) diff --git a/parser/BUILD.bazel b/parser/BUILD.bazel index f52b1fc9ac4f3..e6b5bed7c4075 100644 --- a/parser/BUILD.bazel +++ b/parser/BUILD.bazel @@ -9,6 +9,7 @@ go_library( "lexer.go", "misc.go", "parser.go", + "ttlfeaturegate.go", "yy_parser.go", ], importpath = "github.com/pingcap/tidb/parser", diff --git a/parser/ast/ddl_test.go b/parser/ast/ddl_test.go index e6107f34513ec..fed5c1c759fbf 100644 --- a/parser/ast/ddl_test.go +++ b/parser/ast/ddl_test.go @@ -16,6 +16,7 @@ package ast_test import ( "testing" + "github.com/pingcap/tidb/parser" . "github.com/pingcap/tidb/parser/ast" "github.com/pingcap/tidb/parser/format" "github.com/stretchr/testify/require" @@ -842,6 +843,8 @@ func TestFlashBackDatabaseRestore(t *testing.T) { } func TestTableOptionTTLRestore(t *testing.T) { + parser.TTLFeatureGate = true + sourceSQL1 := "create table t (created_at datetime) ttl = created_at + INTERVAL 1 YEAR" sourceSQL2 := "alter table t ttl_enable = 'OFF'" sourceSQL3 := "alter table t remove ttl" diff --git a/parser/parser.go b/parser/parser.go index 57a5f94d6ed3c..59c1caac4992f 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -11924,6 +11924,10 @@ yynewstate: } case 38: { + if !TTLFeatureGate { + yylex.AppendError(ErrSyntax) + return 1 + } parser.yyVAL.item = &ast.AlterTableSpec{ Tp: ast.AlterTableRemoveTTL, } @@ -20038,6 +20042,10 @@ yynewstate: } case 2153: { + if !TTLFeatureGate { + yylex.AppendError(ErrSyntax) + return 1 + } parser.yyVAL.item = &ast.TableOption{ Tp: ast.TableOptionTTL, ColumnName: &ast.ColumnName{Name: model.NewCIStr(yyS[yypt-4].ident)}, @@ -20047,6 +20055,10 @@ yynewstate: } case 2154: { + if !TTLFeatureGate { + yylex.AppendError(ErrSyntax) + return 1 + } onOrOff := strings.ToLower(yyS[yypt-0].ident) if onOrOff == "on" { parser.yyVAL.item = &ast.TableOption{Tp: ast.TableOptionTTLEnable, BoolValue: true} diff --git a/parser/parser.y b/parser/parser.y index 350372ffa1c61..3c27a8498b7fe 100644 --- a/parser/parser.y +++ b/parser/parser.y @@ -1741,6 +1741,10 @@ AlterTableSpecSingleOpt: } | "REMOVE" "TTL" { + if !TTLFeatureGate { + yylex.AppendError(ErrSyntax) + return 1 + } $$ = &ast.AlterTableSpec{ Tp: ast.AlterTableRemoveTTL, } @@ -11779,6 +11783,10 @@ TableOption: } | "TTL" EqOpt Identifier '+' "INTERVAL" Literal TimeUnit { + if !TTLFeatureGate { + yylex.AppendError(ErrSyntax) + return 1 + } $$ = &ast.TableOption{ Tp: ast.TableOptionTTL, ColumnName: &ast.ColumnName{Name: model.NewCIStr($3)}, @@ -11788,6 +11796,10 @@ TableOption: } | "TTL_ENABLE" EqOpt stringLit { + if !TTLFeatureGate { + yylex.AppendError(ErrSyntax) + return 1 + } onOrOff := strings.ToLower($3) if onOrOff == "on" { $$ = &ast.TableOption{Tp: ast.TableOptionTTLEnable, BoolValue: true} diff --git a/parser/parser_test.go b/parser/parser_test.go index a881cfd15d5ad..99c2d49710e0e 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -7014,6 +7014,8 @@ func TestIntervalPartition(t *testing.T) { } func TestTTLTableOption(t *testing.T) { + parser.TTLFeatureGate = true + table := []testCase{ // create table with various temporal interval {"create table t (created_at datetime) TTL = created_at + INTERVAL 3.1415 YEAR", true, "CREATE TABLE `t` (`created_at` DATETIME) TTL = `created_at` + INTERVAL 3.1415 YEAR"}, @@ -7041,3 +7043,21 @@ func TestTTLTableOption(t *testing.T) { RunTest(t, table, false) } + +func TestTTLFeatureGate(t *testing.T) { + parser.TTLFeatureGate = false + + table := []testCase{ + {"create table t (created_at datetime) TTL = created_at + INTERVAL 3.1415 YEAR", false, ""}, + {"create table t (created_at datetime) TTL_ENABLE = 'OFF'", false, ""}, + {"create table t (created_at datetime) TTL created_at + INTERVAL 1 YEAR TTL_ENABLE 'OFF'", false, ""}, + {"create table t (created_at datetime) /*T![ttl] ttl=created_at + INTERVAL 1 YEAR ttl_enable='ON'*/", false, ""}, + {"alter table t TTL = created_at + INTERVAL 1 MONTH", false, ""}, + {"alter table t TTL_ENABLE = 'ON'", false, ""}, + {"alter table t TTL = created_at + INTERVAL 1 MONTH TTL_ENABLE 'OFF'", false, ""}, + {"alter table t /*T![ttl] ttl=created_at + INTERVAL 1 YEAR ttl_enable='ON'*/", false, ""}, + {"alter table t remove ttl", false, ""}, + } + + RunTest(t, table, false) +} diff --git a/parser/ttlfeaturegate.go b/parser/ttlfeaturegate.go new file mode 100644 index 0000000000000..d18633f137afe --- /dev/null +++ b/parser/ttlfeaturegate.go @@ -0,0 +1,17 @@ +// Copyright 2019 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package parser + +// TTLFeatureGate determines whether to enable the ttl related syntax in parser +var TTLFeatureGate = false diff --git a/ttl/cache/BUILD.bazel b/ttl/cache/BUILD.bazel index a1c84de044dbf..5ca508152da7b 100644 --- a/ttl/cache/BUILD.bazel +++ b/ttl/cache/BUILD.bazel @@ -26,6 +26,7 @@ go_test( flaky = True, deps = [ ":cache", + "//parser", "//parser/model", "//testkit", "//testkit/testsetup", diff --git a/ttl/cache/table_test.go b/ttl/cache/table_test.go index fb450bd768f54..5c2ecdef89d84 100644 --- a/ttl/cache/table_test.go +++ b/ttl/cache/table_test.go @@ -20,6 +20,7 @@ import ( "testing" "time" + "github.com/pingcap/tidb/parser" "github.com/pingcap/tidb/parser/model" "github.com/pingcap/tidb/testkit" "github.com/pingcap/tidb/ttl/cache" @@ -28,6 +29,8 @@ import ( ) func TestNewTTLTable(t *testing.T) { + parser.TTLFeatureGate = true + cases := []struct { db string tbl string @@ -161,6 +164,8 @@ func TestNewTTLTable(t *testing.T) { } func TestEvalTTLExpireTime(t *testing.T) { + parser.TTLFeatureGate = true + store, do := testkit.CreateMockStoreAndDomain(t) tk := testkit.NewTestKit(t, store) tk.MustExec("create table test.t(a int, t datetime) ttl = `t` + interval 1 day")