Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion br/pkg/restore/snap_client/systable_restore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ func TestCheckPrivilegeTableRowsCollateCompatibility(t *testing.T) {
//
// The above variables are in the file br/pkg/restore/systable_restore.go
func TestMonitorTheSystemTableIncremental(t *testing.T) {
require.Equal(t, int64(254), session.CurrentBootstrapVersion)
require.Equal(t, int64(255), session.CurrentBootstrapVersion)
}

func TestIsStatsTemporaryTable(t *testing.T) {
Expand Down
9 changes: 5 additions & 4 deletions pkg/parser/ast/expressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,8 @@ type PatternLikeOrIlikeExpr struct {
IsLike bool

Escape byte
// EscapeExplicit indicates whether ESCAPE clause is specified explicitly.
EscapeExplicit bool

PatChars []byte
PatTypes []byte
Expand Down Expand Up @@ -933,10 +935,9 @@ func (n *PatternLikeOrIlikeExpr) Restore(ctx *format.RestoreCtx) error {
return errors.Annotate(err, "An error occurred while restore PatternLikeOrIlikeExpr.Pattern")
}

escape := string(n.Escape)
if escape != "\\" {
if n.EscapeExplicit && n.Escape != '\\' {
ctx.WriteKeyWord(" ESCAPE ")
ctx.WriteString(escape)
ctx.WriteString(string(n.Escape))
}
return nil
}
Expand All @@ -959,7 +960,7 @@ func (n *PatternLikeOrIlikeExpr) Format(w io.Writer) {
}

n.Pattern.Format(w)
if n.Escape != '\\' {
if n.EscapeExplicit && n.Escape != '\\' {
fmt.Fprint(w, " ESCAPE ")
fmt.Fprintf(w, "'%c'", n.Escape)
}
Expand Down
48 changes: 31 additions & 17 deletions pkg/parser/parser.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 41 additions & 27 deletions pkg/parser/parser.y
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ import (
"github.com/pingcap/tidb/pkg/parser/types"
"github.com/pingcap/tidb/pkg/parser/duration"
)

type likeEscapeSpec struct {
escape string
explicit bool
}
%}

%union {
Expand Down Expand Up @@ -1121,6 +1126,7 @@ import (
%type <item>
AdminShowSlow "Admin Show Slow statement"
AdminStmtLimitOpt "Admin show ddl jobs limit option"
LikeOrIlikeEscapeOpt "like or ilike escape option"
AllOrPartitionNameList "All or partition name list"
AlgorithmClause "Alter table algorithm"
AlterJobOptionList "Alter job option list"
Expand Down Expand Up @@ -1641,7 +1647,6 @@ import (
FieldTerminator "Field terminator"
FlashbackToNewName "Flashback to new name"
HashString "Hashed string"
LikeOrIlikeEscapeOpt "like or ilike escape option"
OptCharset "Optional Character setting"
OptCollate "Optional Collate setting"
PasswordOpt "Password option"
Expand Down Expand Up @@ -1799,17 +1804,17 @@ SplitIndexListOpt:
{
$$ = nil
}
| SplitIndexList %prec lowerThanComma
| SplitIndexList %prec lowerThanComma
{
$$ = $1.([]*ast.SplitIndexOption)
}

SplitIndexList:
SplitIndexOption
SplitIndexOption
{
$$ = []*ast.SplitIndexOption{$1.(*ast.SplitIndexOption)}
}
| SplitIndexList SplitIndexOption
| SplitIndexList SplitIndexOption
{
$$ = append($1.([]*ast.SplitIndexOption), $2.(*ast.SplitIndexOption))
}
Expand All @@ -1819,22 +1824,22 @@ SplitIndexOption:
{
$$ = &ast.SplitIndexOption{
PrimaryKey: true,
IndexName: ast.NewCIStr(mysql.PrimaryKeyName),
SplitOpt: $4.(*ast.SplitOption),
IndexName: ast.NewCIStr(mysql.PrimaryKeyName),
SplitOpt: $4.(*ast.SplitOption),
}
}
| "SPLIT" "INDEX" Identifier SplitOptionBetween
{
$$ = &ast.SplitIndexOption{
IndexName: ast.NewCIStr($3),
SplitOpt: $4.(*ast.SplitOption),
SplitOpt: $4.(*ast.SplitOption),
}
}
| "SPLIT" SplitOptionBetween
{
$$ = &ast.SplitIndexOption{
TableLevel: true,
SplitOpt: $2.(*ast.SplitOption),
SplitOpt: $2.(*ast.SplitOption),
}
}

Expand Down Expand Up @@ -2221,8 +2226,8 @@ AlterTableSpecSingleOpt:
| SplitIndexOption
{
$$ = &ast.AlterTableSpec{
Tp: ast.AlterTableSplitIndex,
SplitIndex: $1.(*ast.SplitIndexOption),
Tp: ast.AlterTableSplitIndex,
SplitIndex: $1.(*ast.SplitIndexOption),
}
}
| "SPLIT" "MAXVALUE" "PARTITION" "LESS" "THAN" '(' BitExpr ')'
Expand Down Expand Up @@ -6619,36 +6624,44 @@ PredicateExpr:
}
| BitExpr LikeOrNotOp SimpleExpr LikeOrIlikeEscapeOpt
{
escape := $4
escapeSpec := $4.(*likeEscapeSpec)
escape := escapeSpec.escape
explicit := escapeSpec.explicit
if len(escape) > 1 {
yylex.AppendError(ErrWrongArguments.GenWithStackByArgs("ESCAPE"))
return 1
} else if len(escape) == 0 {
escape = "\\"
explicit = false
}
$$ = &ast.PatternLikeOrIlikeExpr{
Expr: $1,
Pattern: $3,
Not: !$2.(bool),
Escape: escape[0],
IsLike: true,
Expr: $1,
Pattern: $3,
Not: !$2.(bool),
Escape: escape[0],
EscapeExplicit: explicit,
IsLike: true,
}
}
| BitExpr IlikeOrNotOp SimpleExpr LikeOrIlikeEscapeOpt
{
escape := $4
escapeSpec := $4.(*likeEscapeSpec)
escape := escapeSpec.escape
explicit := escapeSpec.explicit
if len(escape) > 1 {
yylex.AppendError(ErrWrongArguments.GenWithStackByArgs("ESCAPE"))
return 1
} else if len(escape) == 0 {
escape = "\\"
explicit = false
}
$$ = &ast.PatternLikeOrIlikeExpr{
Expr: $1,
Pattern: $3,
Not: !$2.(bool),
Escape: escape[0],
IsLike: false,
Expr: $1,
Pattern: $3,
Not: !$2.(bool),
Escape: escape[0],
EscapeExplicit: explicit,
IsLike: false,
}
}
| BitExpr RegexpOrNotOp SimpleExpr
Expand All @@ -6668,11 +6681,11 @@ RegexpSym:
LikeOrIlikeEscapeOpt:
%prec empty
{
$$ = "\\"
$$ = &likeEscapeSpec{escape: "\\", explicit: false}
}
| "ESCAPE" stringLit
{
$$ = $2
$$ = &likeEscapeSpec{escape: $2, explicit: true}
}

Field:
Expand Down Expand Up @@ -12411,9 +12424,10 @@ ShowLikeOrWhereOpt:
| "LIKE" SimpleExpr
{
$$ = &ast.PatternLikeOrIlikeExpr{
Pattern: $2,
Escape: '\\',
IsLike: true,
Pattern: $2,
Escape: '\\',
EscapeExplicit: false,
IsLike: true,
}
}
| "WHERE" Expression
Expand Down
4 changes: 4 additions & 0 deletions pkg/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7083,6 +7083,10 @@ func (checker *nodeTextCleaner) Enter(in ast.Node) (out ast.Node, skipChildren b
}

switch node := in.(type) {
case *ast.PatternLikeOrIlikeExpr:
if node.Escape == '\\' {
node.EscapeExplicit = false
}
case *ast.CreateTableStmt:
for _, opt := range node.Options {
switch opt.Tp {
Expand Down
16 changes: 13 additions & 3 deletions pkg/planner/core/expression_rewriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2177,6 +2177,16 @@ func (er *expressionRewriter) patternLikeOrIlikeToExpression(v *ast.PatternLikeO
return
}

escape := v.Escape
sessionVars, err := expropt.SessionVarsPropReader{}.GetSessionVars(er.sctx.GetEvalCtx())
if err != nil {
er.err = err
return
}
if sessionVars.EnableNoBackslashEscapesInLike && !v.EscapeExplicit && er.sctx.GetEvalCtx().SQLMode().HasNoBackslashEscapesMode() {
escape = 0
}

char, col := er.sctx.GetCharsetInfo()
var function expression.Expression
fieldType := &types.FieldType{}
Expand All @@ -2189,7 +2199,7 @@ func (er *expressionRewriter) patternLikeOrIlikeToExpression(v *ast.PatternLikeO
return
}
if !isNull {
patValue, patTypes := stringutil.CompilePattern(patString, v.Escape)
patValue, patTypes := stringutil.CompilePattern(patString, escape)
if stringutil.IsExactMatch(patTypes) && er.ctxStack[l-2].GetType(er.sctx.GetEvalCtx()).EvalType() == types.ETString {
op := ast.EQ
if v.Not {
Expand All @@ -2208,9 +2218,9 @@ func (er *expressionRewriter) patternLikeOrIlikeToExpression(v *ast.PatternLikeO
if !v.IsLike {
funcName = ast.Ilike
}
types.DefaultTypeForValue(int(v.Escape), fieldType, char, col)
types.DefaultTypeForValue(int(escape), fieldType, char, col)
function = er.notToExpression(v.Not, funcName, &v.Type,
er.ctxStack[l-2], er.ctxStack[l-1], &expression.Constant{Value: types.NewIntDatum(int64(v.Escape)), RetType: fieldType})
er.ctxStack[l-2], er.ctxStack[l-1], &expression.Constant{Value: types.NewIntDatum(int64(escape)), RetType: fieldType})
}

er.ctxStackPop(2)
Expand Down
12 changes: 11 additions & 1 deletion pkg/session/upgrade_def.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,10 @@ const (
// Add index on start_time for mysql.tidb_runaway_watch and done_time for mysql.tidb_runaway_watch_done
// to improve the performance of runaway watch sync loop.
version254 = 254

// version255
// Add tidb_enable_no_backslash_escapes_in_like global variable.
version255 = 255
)

// versionedUpgradeFunction is a struct that holds the upgrade function related
Expand All @@ -491,7 +495,7 @@ type versionedUpgradeFunction struct {

// currentBootstrapVersion is defined as a variable, so we can modify its value for testing.
// please make sure this is the largest version
var currentBootstrapVersion int64 = version254
var currentBootstrapVersion int64 = version255

var (
// this list must be ordered by version in ascending order, and the function
Expand Down Expand Up @@ -670,6 +674,7 @@ var (
{version: version252, fn: upgradeToVer252},
{version: version253, fn: upgradeToVer253},
{version: version254, fn: upgradeToVer254},
{version: version255, fn: upgradeToVer255},
}
)

Expand Down Expand Up @@ -2049,3 +2054,8 @@ func upgradeToVer254(s sessionapi.Session, _ int64) {
doReentrantDDL(s, "ALTER TABLE mysql.tidb_runaway_watch ADD INDEX idx_start_time(start_time) COMMENT 'accelerate the speed when syncing new watch records'", dbterror.ErrDupKeyName)
doReentrantDDL(s, "ALTER TABLE mysql.tidb_runaway_watch_done ADD INDEX idx_done_time(done_time) COMMENT 'accelerate the speed when syncing done watch records'", dbterror.ErrDupKeyName)
}

func upgradeToVer255(s sessionapi.Session, _ int64) {
// Keep old behavior for upgraded clusters.
initGlobalVariableIfNotExists(s, vardef.TiDBEnableNoBackslashEscapesInLike, vardef.Off)
}
Loading