[parser] *: set charset and collate for string literals correctly (#761)

* done

* address comment

* fix

* revert
This commit is contained in:
kennytm
2020-03-05 20:01:28 +08:00
committed by Ti Chi Robot
parent 2f1915d785
commit b255e058e5
8 changed files with 107 additions and 104 deletions

View File

@ -65,7 +65,7 @@ type ValueExpr interface {
}
// NewValueExpr creates a ValueExpr with value, and sets default field type.
var NewValueExpr func(interface{}) ValueExpr
var NewValueExpr func(value interface{}, charset string, collate string) ValueExpr
// NewParamMarkerExpr creates a ParamMarkerExpr.
var NewParamMarkerExpr func(offset int) ParamMarkerExpr

View File

@ -17,6 +17,7 @@ import (
. "github.com/pingcap/check"
. "github.com/pingcap/parser/ast"
"github.com/pingcap/parser/format"
"github.com/pingcap/parser/mysql"
)
var _ = Suite(&testExpressionsSuite{})
@ -88,7 +89,7 @@ func (tc *testExpressionsSuite) TestExpresionsVisitorCover(c *C) {
{&PositionExpr{}, 0, 0},
{&RowExpr{Values: []ExprNode{ce, ce}}, 2, 2},
{&UnaryOperationExpr{V: ce}, 1, 1},
{NewValueExpr(0), 0, 0},
{NewValueExpr(0, mysql.DefaultCharset, mysql.DefaultCollationName), 0, 0},
{&ValuesExpr{Column: &ColumnNameExpr{Name: &ColumnName{}}}, 0, 0},
{&VariableExpr{Value: ce}, 1, 1},
}

View File

@ -17,6 +17,7 @@ import (
. "github.com/pingcap/check"
"github.com/pingcap/parser"
. "github.com/pingcap/parser/ast"
"github.com/pingcap/parser/mysql"
"github.com/pingcap/parser/test_driver"
)
@ -26,7 +27,7 @@ type testFunctionsSuite struct {
}
func (ts *testFunctionsSuite) TestFunctionsVisitorCover(c *C) {
valueExpr := NewValueExpr(42)
valueExpr := NewValueExpr(42, mysql.DefaultCharset, mysql.DefaultCollationName)
stmts := []Node{
&AggregateFuncExpr{Args: []ExprNode{valueExpr}},
&FuncCallExpr{Args: []ExprNode{valueExpr}},

View File

@ -18,6 +18,7 @@ import (
"github.com/pingcap/parser"
. "github.com/pingcap/parser/ast"
"github.com/pingcap/parser/auth"
"github.com/pingcap/parser/mysql"
)
var _ = Suite(&testMiscSuite{})
@ -44,7 +45,7 @@ func (visitor1) Enter(in Node) (Node, bool) {
}
func (ts *testMiscSuite) TestMiscVisitorCover(c *C) {
valueExpr := NewValueExpr(42)
valueExpr := NewValueExpr(42, mysql.DefaultCharset, mysql.DefaultCollationName)
stmts := []Node{
&AdminStmt{},
&AlterUserStmt{},

View File

@ -10571,7 +10571,7 @@ yynewstate:
}
case 182:
{
parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionComment, Expr: ast.NewValueExpr(yyS[yypt-0].ident)}
parser.yyVAL.item = &ast.ColumnOption{Tp: ast.ColumnOptionComment, Expr: ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation)}
}
case 183:
{
@ -10864,7 +10864,7 @@ yynewstate:
}
case 234:
{
parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP"), Args: []ast.ExprNode{ast.NewValueExpr(yyS[yypt-1].item)}}
parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP"), Args: []ast.ExprNode{ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)}}
}
case 235:
{
@ -10888,15 +10888,15 @@ yynewstate:
}
case 244:
{
parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].expr)
parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].expr, parser.charset, parser.collation)
}
case 245:
{
parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Plus, V: ast.NewValueExpr(yyS[yypt-0].item)}
parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Plus, V: ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation)}
}
case 246:
{
parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Minus, V: ast.NewValueExpr(yyS[yypt-0].item)}
parser.yyVAL.expr = &ast.UnaryOperationExpr{Op: opcode.Minus, V: ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation)}
}
case 250:
{
@ -11856,7 +11856,7 @@ yynewstate:
}
case 439:
{
expr := ast.NewValueExpr(yyS[yypt-0].item)
expr := ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation)
parser.yyVAL.item = []ast.ExprNode{expr}
}
case 440:
@ -12369,27 +12369,27 @@ yynewstate:
}
case 907:
{
parser.yyVAL.expr = ast.NewValueExpr(false)
parser.yyVAL.expr = ast.NewValueExpr(false, parser.charset, parser.collation)
}
case 908:
{
parser.yyVAL.expr = ast.NewValueExpr(nil)
parser.yyVAL.expr = ast.NewValueExpr(nil, parser.charset, parser.collation)
}
case 909:
{
parser.yyVAL.expr = ast.NewValueExpr(true)
parser.yyVAL.expr = ast.NewValueExpr(true, parser.charset, parser.collation)
}
case 910:
{
parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item)
parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation)
}
case 911:
{
parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item)
parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation)
}
case 912:
{
parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item)
parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation)
}
case 913:
{
@ -12403,7 +12403,7 @@ yynewstate:
yylex.AppendError(yylex.Errorf("Get collation error for charset: %s", yyS[yypt-1].ident))
return 1
}
expr := ast.NewValueExpr(yyS[yypt-0].ident)
expr := ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation)
tp := expr.GetType()
tp.Charset = yyS[yypt-1].ident
tp.Collate = co
@ -12414,22 +12414,22 @@ yynewstate:
}
case 915:
{
parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item)
parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation)
}
case 916:
{
parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item)
parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation)
}
case 917:
{
expr := ast.NewValueExpr(yyS[yypt-0].ident)
expr := ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation)
parser.yyVAL.expr = expr
}
case 918:
{
valExpr := yyS[yypt-1].expr.(ast.ValueExpr)
strLit := valExpr.GetString()
expr := ast.NewValueExpr(strLit + yyS[yypt-0].ident)
expr := ast.NewValueExpr(strLit+yyS[yypt-0].ident, parser.charset, parser.collation)
// Fix #4239, use first string literal as projection name.
if valExpr.GetProjectionOffset() >= 0 {
expr.SetProjectionOffset(valExpr.GetProjectionOffset())
@ -12712,7 +12712,7 @@ yynewstate:
case 975:
{
// See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_convert
charset1 := ast.NewValueExpr(yyS[yypt-1].item)
charset1 := ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)
parser.yyVAL.expr = &ast.FuncCallExpr{
FnName: model.NewCIStr(yyS[yypt-5].ident),
Args: []ast.ExprNode{yyS[yypt-3].expr, charset1},
@ -12728,12 +12728,12 @@ yynewstate:
}
case 978:
{
expr := ast.NewValueExpr(yyS[yypt-0].ident)
expr := ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation)
parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONExtract), Args: []ast.ExprNode{yyS[yypt-2].expr, expr}}
}
case 979:
{
expr := ast.NewValueExpr(yyS[yypt-0].ident)
expr := ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation)
extract := &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONExtract), Args: []ast.ExprNode{yyS[yypt-2].expr, expr}}
parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONUnquote), Args: []ast.ExprNode{extract}}
}
@ -12783,7 +12783,7 @@ yynewstate:
}
case 1036:
{
nilVal := ast.NewValueExpr(nil)
nilVal := ast.NewValueExpr(nil, parser.charset, parser.collation)
args := yyS[yypt-1].item.([]ast.ExprNode)
parser.yyVAL.expr = &ast.FuncCallExpr{
FnName: model.NewCIStr(ast.CharFunc),
@ -12792,7 +12792,7 @@ yynewstate:
}
case 1037:
{
charset1 := ast.NewValueExpr(yyS[yypt-1].item)
charset1 := ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)
args := yyS[yypt-3].item.([]ast.ExprNode)
parser.yyVAL.expr = &ast.FuncCallExpr{
FnName: model.NewCIStr(ast.CharFunc),
@ -12801,17 +12801,17 @@ yynewstate:
}
case 1038:
{
expr := ast.NewValueExpr(yyS[yypt-0].ident)
expr := ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation)
parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.DateLiteral), Args: []ast.ExprNode{expr}}
}
case 1039:
{
expr := ast.NewValueExpr(yyS[yypt-0].ident)
expr := ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation)
parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.TimeLiteral), Args: []ast.ExprNode{expr}}
}
case 1040:
{
expr := ast.NewValueExpr(yyS[yypt-0].ident)
expr := ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation)
parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.TimestampLiteral), Args: []ast.ExprNode{expr}}
}
case 1041:
@ -12830,7 +12830,7 @@ yynewstate:
{
// This is ODBC syntax for date and time literals.
// See: https://dev.mysql.com/doc/refman/5.7/en/date-and-time-literals.html
expr := ast.NewValueExpr(yyS[yypt-1].ident)
expr := ast.NewValueExpr(yyS[yypt-1].ident, parser.charset, parser.collation)
parser.yyVAL.expr = &ast.FuncCallExpr{FnName: model.NewCIStr(yyS[yypt-2].ident), Args: []ast.ExprNode{expr}}
}
case 1045:
@ -12954,7 +12954,7 @@ yynewstate:
}
case 1061:
{
nilVal := ast.NewValueExpr(nil)
nilVal := ast.NewValueExpr(nil, parser.charset, parser.collation)
direction := &ast.TrimDirectionExpr{Direction: yyS[yypt-3].item.(ast.TrimDirectionType)}
parser.yyVAL.expr = &ast.FuncCallExpr{
FnName: model.NewCIStr(yyS[yypt-5].ident),
@ -12980,14 +12980,14 @@ yynewstate:
{
parser.yyVAL.expr = &ast.FuncCallExpr{
FnName: model.NewCIStr(yyS[yypt-6].ident),
Args: []ast.ExprNode{yyS[yypt-4].expr, ast.NewValueExpr("CHAR"), ast.NewValueExpr(yyS[yypt-1].item)},
Args: []ast.ExprNode{yyS[yypt-4].expr, ast.NewValueExpr("CHAR", parser.charset, parser.collation), ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)},
}
}
case 1065:
{
parser.yyVAL.expr = &ast.FuncCallExpr{
FnName: model.NewCIStr(yyS[yypt-6].ident),
Args: []ast.ExprNode{yyS[yypt-4].expr, ast.NewValueExpr("BINARY"), ast.NewValueExpr(yyS[yypt-1].item)},
Args: []ast.ExprNode{yyS[yypt-4].expr, ast.NewValueExpr("BINARY", parser.charset, parser.collation), ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)},
}
}
case 1067:
@ -13033,7 +13033,7 @@ yynewstate:
objNameExpr := &ast.TableNameExpr{
Name: yyS[yypt-3].item.(*ast.TableName),
}
valueExpr := ast.NewValueExpr(yyS[yypt-1].item)
valueExpr := ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)
parser.yyVAL.expr = &ast.FuncCallExpr{
FnName: model.NewCIStr(ast.SetVal),
Args: []ast.ExprNode{objNameExpr, valueExpr},
@ -13117,7 +13117,7 @@ yynewstate:
}
case 1091:
{
args := []ast.ExprNode{ast.NewValueExpr(1)}
args := []ast.ExprNode{ast.NewValueExpr(1, parser.charset, parser.collation)}
if yyS[yypt-0].item != nil {
parser.yyVAL.expr = &ast.WindowFuncExpr{F: yyS[yypt-4].ident, Args: args, Spec: *(yyS[yypt-0].item.(*ast.WindowSpec))}
} else {
@ -13216,11 +13216,11 @@ yynewstate:
}
case 1104:
{
parser.yyVAL.item = ast.NewValueExpr(",")
parser.yyVAL.item = ast.NewValueExpr(",", parser.charset, parser.collation)
}
case 1105:
{
parser.yyVAL.item = ast.NewValueExpr(yyS[yypt-0].ident)
parser.yyVAL.item = ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation)
}
case 1106:
{
@ -13236,7 +13236,7 @@ yynewstate:
}
case 1109:
{
expr := ast.NewValueExpr(yyS[yypt-1].item)
expr := ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)
parser.yyVAL.item = expr
}
case 1110:
@ -13884,7 +13884,7 @@ yynewstate:
}
case 1223:
{
parser.yyVAL.item = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewValueExpr(yyS[yypt-1].item)}
parser.yyVAL.item = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)}
}
case 1224:
{
@ -13912,7 +13912,7 @@ yynewstate:
}
case 1230:
{
parser.yyVAL.item = ast.FrameBound{Type: ast.Following, Expr: ast.NewValueExpr(yyS[yypt-1].item)}
parser.yyVAL.item = ast.FrameBound{Type: ast.Following, Expr: ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)}
}
case 1231:
{
@ -14001,7 +14001,7 @@ yynewstate:
}
case 1250:
{
args := []ast.ExprNode{ast.NewValueExpr(yyS[yypt-1].item)}
args := []ast.ExprNode{ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)}
if yyS[yypt-0].item != nil {
args = append(args, yyS[yypt-0].item.(ast.ExprNode))
}
@ -14009,7 +14009,7 @@ yynewstate:
}
case 1251:
{
args := []ast.ExprNode{ast.NewValueExpr(yyS[yypt-1].item)}
args := []ast.ExprNode{ast.NewValueExpr(yyS[yypt-1].item, parser.charset, parser.collation)}
if yyS[yypt-0].item != nil {
args = append(args, yyS[yypt-0].item.(ast.ExprNode))
}
@ -14262,7 +14262,7 @@ yynewstate:
}
case 1312:
{
parser.yyVAL.item = ast.NewValueExpr(yyS[yypt-0].item)
parser.yyVAL.item = ast.NewValueExpr(yyS[yypt-0].item, parser.charset, parser.collation)
}
case 1313:
{
@ -14661,21 +14661,21 @@ yynewstate:
case 1372:
{
varAssigns := []*ast.VariableAssignment{}
expr := ast.NewValueExpr(yyS[yypt-0].ident)
expr := ast.NewValueExpr(yyS[yypt-0].ident, parser.charset, parser.collation)
varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_isolation", Value: expr, IsSystem: true})
parser.yyVAL.item = varAssigns
}
case 1373:
{
varAssigns := []*ast.VariableAssignment{}
expr := ast.NewValueExpr("0")
expr := ast.NewValueExpr("0", parser.charset, parser.collation)
varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_read_only", Value: expr, IsSystem: true})
parser.yyVAL.item = varAssigns
}
case 1374:
{
varAssigns := []*ast.VariableAssignment{}
expr := ast.NewValueExpr("1")
expr := ast.NewValueExpr("1", parser.charset, parser.collation)
varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_read_only", Value: expr, IsSystem: true})
parser.yyVAL.item = varAssigns
}
@ -14697,7 +14697,7 @@ yynewstate:
}
case 1379:
{
parser.yyVAL.expr = ast.NewValueExpr("ON")
parser.yyVAL.expr = ast.NewValueExpr("ON", parser.charset, parser.collation)
}
case 1384:
{
@ -14745,22 +14745,22 @@ yynewstate:
{
parser.yyVAL.item = &ast.VariableAssignment{
Name: ast.SetNames,
Value: ast.NewValueExpr(yyS[yypt-0].item.(string)),
Value: ast.NewValueExpr(yyS[yypt-0].item.(string), parser.charset, parser.collation),
}
}
case 1392:
{
parser.yyVAL.item = &ast.VariableAssignment{
Name: ast.SetNames,
Value: ast.NewValueExpr(yyS[yypt-2].item.(string)),
Value: ast.NewValueExpr(yyS[yypt-2].item.(string), parser.charset, parser.collation),
}
}
case 1393:
{
parser.yyVAL.item = &ast.VariableAssignment{
Name: ast.SetNames,
Value: ast.NewValueExpr(yyS[yypt-2].item.(string)),
ExtendValue: ast.NewValueExpr(yyS[yypt-0].item.(string)),
Value: ast.NewValueExpr(yyS[yypt-2].item.(string), parser.charset, parser.collation),
ExtendValue: ast.NewValueExpr(yyS[yypt-0].item.(string), parser.charset, parser.collation),
}
}
case 1394:
@ -14774,7 +14774,7 @@ yynewstate:
}
case 1396:
{
parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item.(string))
parser.yyVAL.expr = ast.NewValueExpr(yyS[yypt-0].item.(string), parser.charset, parser.collation)
}
case 1397:
{

View File

@ -2550,7 +2550,7 @@ ColumnOption:
}
| "COMMENT" stringLit
{
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionComment, Expr: ast.NewValueExpr($2)}
$$ = &ast.ColumnOption{Tp: ast.ColumnOptionComment, Expr: ast.NewValueExpr($2, parser.charset, parser.collation)}
}
| ConstraintKeywordOpt "CHECK" '(' Expression ')' EnforcedOrNotOrNotNullOpt
{
@ -2891,7 +2891,7 @@ NowSymOptionFraction:
}
| NowSymFunc '(' NUM ')'
{
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP"), Args: []ast.ExprNode{ast.NewValueExpr($3)}}
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr("CURRENT_TIMESTAMP"), Args: []ast.ExprNode{ast.NewValueExpr($3, parser.charset, parser.collation)}}
}
NextValueForSequence:
@ -2934,15 +2934,15 @@ NowSym:
SignedLiteral:
Literal
{
$$ = ast.NewValueExpr($1)
$$ = ast.NewValueExpr($1, parser.charset, parser.collation)
}
| '+' NumLiteral
{
$$ = &ast.UnaryOperationExpr{Op: opcode.Plus, V: ast.NewValueExpr($2)}
$$ = &ast.UnaryOperationExpr{Op: opcode.Plus, V: ast.NewValueExpr($2, parser.charset, parser.collation)}
}
| '-' NumLiteral
{
$$ = &ast.UnaryOperationExpr{Op: opcode.Minus, V: ast.NewValueExpr($2)}
$$ = &ast.UnaryOperationExpr{Op: opcode.Minus, V: ast.NewValueExpr($2, parser.charset, parser.collation)}
}
NumLiteral:
@ -4173,7 +4173,7 @@ FuncDatetimePrecListOpt:
FuncDatetimePrecList:
intLit
{
expr := ast.NewValueExpr($1)
expr := ast.NewValueExpr($1, parser.charset, parser.collation)
$$ = []ast.ExprNode{expr}
}
@ -5171,27 +5171,27 @@ ODBCDateTimeType:
Literal:
"FALSE"
{
$$ = ast.NewValueExpr(false)
$$ = ast.NewValueExpr(false, parser.charset, parser.collation)
}
| "NULL"
{
$$ = ast.NewValueExpr(nil)
$$ = ast.NewValueExpr(nil, parser.charset, parser.collation)
}
| "TRUE"
{
$$ = ast.NewValueExpr(true)
$$ = ast.NewValueExpr(true, parser.charset, parser.collation)
}
| floatLit
{
$$ = ast.NewValueExpr($1)
$$ = ast.NewValueExpr($1, parser.charset, parser.collation)
}
| decLit
{
$$ = ast.NewValueExpr($1)
$$ = ast.NewValueExpr($1, parser.charset, parser.collation)
}
| intLit
{
$$ = ast.NewValueExpr($1)
$$ = ast.NewValueExpr($1, parser.charset, parser.collation)
}
| StringLiteral %prec lowerThanStringLitToken
{
@ -5205,7 +5205,7 @@ Literal:
yylex.AppendError(yylex.Errorf("Get collation error for charset: %s", $1))
return 1
}
expr := ast.NewValueExpr($2)
expr := ast.NewValueExpr($2, parser.charset, parser.collation)
tp := expr.GetType()
tp.Charset = $1
tp.Collate = co
@ -5216,24 +5216,24 @@ Literal:
}
| hexLit
{
$$ = ast.NewValueExpr($1)
$$ = ast.NewValueExpr($1, parser.charset, parser.collation)
}
| bitLit
{
$$ = ast.NewValueExpr($1)
$$ = ast.NewValueExpr($1, parser.charset, parser.collation)
}
StringLiteral:
stringLit
{
expr := ast.NewValueExpr($1)
expr := ast.NewValueExpr($1, parser.charset, parser.collation)
$$ = expr
}
| StringLiteral stringLit
{
valExpr := $1.(ast.ValueExpr)
strLit := valExpr.GetString()
expr := ast.NewValueExpr(strLit + $2)
expr := ast.NewValueExpr(strLit+$2, parser.charset, parser.collation)
// Fix #4239, use first string literal as projection name.
if valExpr.GetProjectionOffset() >= 0 {
expr.SetProjectionOffset(valExpr.GetProjectionOffset())
@ -5544,7 +5544,7 @@ SimpleExpr:
| "CONVERT" '(' Expression "USING" CharsetName ')'
{
// See https://dev.mysql.com/doc/refman/5.7/en/cast-functions.html#function_convert
charset1 := ast.NewValueExpr($5)
charset1 := ast.NewValueExpr($5, parser.charset, parser.collation)
$$ = &ast.FuncCallExpr{
FnName: model.NewCIStr($1),
Args: []ast.ExprNode{$3, charset1},
@ -5560,12 +5560,12 @@ SimpleExpr:
}
| SimpleIdent jss stringLit
{
expr := ast.NewValueExpr($3)
expr := ast.NewValueExpr($3, parser.charset, parser.collation)
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONExtract), Args: []ast.ExprNode{$1, expr}}
}
| SimpleIdent juss stringLit
{
expr := ast.NewValueExpr($3)
expr := ast.NewValueExpr($3, parser.charset, parser.collation)
extract := &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONExtract), Args: []ast.ExprNode{$1, expr}}
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.JSONUnquote), Args: []ast.ExprNode{extract}}
}
@ -5680,7 +5680,7 @@ FunctionCallKeyword:
}
| "CHAR" '(' ExpressionList ')'
{
nilVal := ast.NewValueExpr(nil)
nilVal := ast.NewValueExpr(nil, parser.charset, parser.collation)
args := $3.([]ast.ExprNode)
$$ = &ast.FuncCallExpr{
FnName: model.NewCIStr(ast.CharFunc),
@ -5689,7 +5689,7 @@ FunctionCallKeyword:
}
| "CHAR" '(' ExpressionList "USING" CharsetName ')'
{
charset1 := ast.NewValueExpr($5)
charset1 := ast.NewValueExpr($5, parser.charset, parser.collation)
args := $3.([]ast.ExprNode)
$$ = &ast.FuncCallExpr{
FnName: model.NewCIStr(ast.CharFunc),
@ -5698,17 +5698,17 @@ FunctionCallKeyword:
}
| "DATE" stringLit
{
expr := ast.NewValueExpr($2)
expr := ast.NewValueExpr($2, parser.charset, parser.collation)
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.DateLiteral), Args: []ast.ExprNode{expr}}
}
| "TIME" stringLit
{
expr := ast.NewValueExpr($2)
expr := ast.NewValueExpr($2, parser.charset, parser.collation)
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.TimeLiteral), Args: []ast.ExprNode{expr}}
}
| "TIMESTAMP" stringLit
{
expr := ast.NewValueExpr($2)
expr := ast.NewValueExpr($2, parser.charset, parser.collation)
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr(ast.TimestampLiteral), Args: []ast.ExprNode{expr}}
}
| "INSERT" '(' ExpressionListOpt ')'
@ -5727,7 +5727,7 @@ FunctionCallKeyword:
{
// This is ODBC syntax for date and time literals.
// See: https://dev.mysql.com/doc/refman/5.7/en/date-and-time-literals.html
expr := ast.NewValueExpr($3)
expr := ast.NewValueExpr($3, parser.charset, parser.collation)
$$ = &ast.FuncCallExpr{FnName: model.NewCIStr($2), Args: []ast.ExprNode{expr}}
}
@ -5853,7 +5853,7 @@ FunctionCallNonKeyword:
}
| builtinTrim '(' TrimDirection "FROM" Expression ')'
{
nilVal := ast.NewValueExpr(nil)
nilVal := ast.NewValueExpr(nil, parser.charset, parser.collation)
direction := &ast.TrimDirectionExpr{Direction: $3.(ast.TrimDirectionType)}
$$ = &ast.FuncCallExpr{
FnName: model.NewCIStr($1),
@ -5879,14 +5879,14 @@ FunctionCallNonKeyword:
{
$$ = &ast.FuncCallExpr{
FnName: model.NewCIStr($1),
Args: []ast.ExprNode{$3, ast.NewValueExpr("CHAR"), ast.NewValueExpr($6)},
Args: []ast.ExprNode{$3, ast.NewValueExpr("CHAR", parser.charset, parser.collation), ast.NewValueExpr($6, parser.charset, parser.collation)},
}
}
| weightString '(' Expression "AS" "BINARY" FieldLen ')'
{
$$ = &ast.FuncCallExpr{
FnName: model.NewCIStr($1),
Args: []ast.ExprNode{$3, ast.NewValueExpr("BINARY"), ast.NewValueExpr($6)},
Args: []ast.ExprNode{$3, ast.NewValueExpr("BINARY", parser.charset, parser.collation), ast.NewValueExpr($6, parser.charset, parser.collation)},
}
}
| FunctionNameSequence
@ -5947,7 +5947,7 @@ FunctionNameSequence:
objNameExpr := &ast.TableNameExpr{
Name: $3.(*ast.TableName),
}
valueExpr := ast.NewValueExpr($5)
valueExpr := ast.NewValueExpr($5, parser.charset, parser.collation)
$$ = &ast.FuncCallExpr{
FnName: model.NewCIStr(ast.SetVal),
Args: []ast.ExprNode{objNameExpr, valueExpr},
@ -6034,7 +6034,7 @@ SumExpr:
}
| builtinCount '(' '*' ')' OptWindowingClause
{
args := []ast.ExprNode{ast.NewValueExpr(1)}
args := []ast.ExprNode{ast.NewValueExpr(1, parser.charset, parser.collation)}
if $5 != nil {
$$ = &ast.WindowFuncExpr{F: $1, Args: args, Spec: *($5.(*ast.WindowSpec))}
} else {
@ -6134,11 +6134,11 @@ SumExpr:
OptGConcatSeparator:
{
$$ = ast.NewValueExpr(",")
$$ = ast.NewValueExpr(",", parser.charset, parser.collation)
}
| "SEPARATOR" stringLit
{
$$ = ast.NewValueExpr($2)
$$ = ast.NewValueExpr($2, parser.charset, parser.collation)
}
FunctionCallGeneric:
@ -6157,7 +6157,7 @@ FuncDatetimePrec:
}
| '(' intLit ')'
{
expr := ast.NewValueExpr($2)
expr := ast.NewValueExpr($2, parser.charset, parser.collation)
$$ = expr
}
@ -6902,7 +6902,7 @@ WindowFrameStart:
}
| NumLiteral "PRECEDING"
{
$$ = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewValueExpr($1)}
$$ = ast.FrameBound{Type: ast.Preceding, Expr: ast.NewValueExpr($1, parser.charset, parser.collation)}
}
| paramMarker "PRECEDING"
{
@ -6934,7 +6934,7 @@ WindowFrameBound:
}
| NumLiteral "FOLLOWING"
{
$$ = ast.FrameBound{Type: ast.Following, Expr: ast.NewValueExpr($1)}
$$ = ast.FrameBound{Type: ast.Following, Expr: ast.NewValueExpr($1, parser.charset, parser.collation)}
}
| paramMarker "FOLLOWING"
{
@ -7031,7 +7031,7 @@ OptLeadLagInfo:
}
| ',' NumLiteral OptLLDefault
{
args := []ast.ExprNode{ast.NewValueExpr($2)}
args := []ast.ExprNode{ast.NewValueExpr($2, parser.charset, parser.collation)}
if $3 != nil {
args = append(args, $3.(ast.ExprNode))
}
@ -7039,7 +7039,7 @@ OptLeadLagInfo:
}
| ',' paramMarker OptLLDefault
{
args := []ast.ExprNode{ast.NewValueExpr($2)}
args := []ast.ExprNode{ast.NewValueExpr($2, parser.charset, parser.collation)}
if $3 != nil {
args = append(args, $3.(ast.ExprNode))
}
@ -7336,7 +7336,7 @@ LimitClause:
LimitOption:
LengthNum
{
$$ = ast.NewValueExpr($1)
$$ = ast.NewValueExpr($1, parser.charset, parser.collation)
}
| paramMarker
{
@ -7791,21 +7791,21 @@ TransactionChar:
"ISOLATION" "LEVEL" IsolationLevel
{
varAssigns := []*ast.VariableAssignment{}
expr := ast.NewValueExpr($3)
expr := ast.NewValueExpr($3, parser.charset, parser.collation)
varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_isolation", Value: expr, IsSystem: true})
$$ = varAssigns
}
| "READ" "WRITE"
{
varAssigns := []*ast.VariableAssignment{}
expr := ast.NewValueExpr("0")
expr := ast.NewValueExpr("0", parser.charset, parser.collation)
varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_read_only", Value: expr, IsSystem: true})
$$ = varAssigns
}
| "READ" "ONLY"
{
varAssigns := []*ast.VariableAssignment{}
expr := ast.NewValueExpr("1")
expr := ast.NewValueExpr("1", parser.charset, parser.collation)
varAssigns = append(varAssigns, &ast.VariableAssignment{Name: "tx_read_only", Value: expr, IsSystem: true})
$$ = varAssigns
}
@ -7831,7 +7831,7 @@ IsolationLevel:
SetExpr:
"ON"
{
$$ = ast.NewValueExpr("ON")
$$ = ast.NewValueExpr("ON", parser.charset, parser.collation)
}
| ExprOrDefault
@ -7889,22 +7889,22 @@ VariableAssignment:
{
$$ = &ast.VariableAssignment{
Name: ast.SetNames,
Value: ast.NewValueExpr($2.(string)),
Value: ast.NewValueExpr($2.(string), parser.charset, parser.collation),
}
}
| "NAMES" CharsetName "COLLATE" "DEFAULT"
{
$$ = &ast.VariableAssignment{
Name: ast.SetNames,
Value: ast.NewValueExpr($2.(string)),
Value: ast.NewValueExpr($2.(string), parser.charset, parser.collation),
}
}
| "NAMES" CharsetName "COLLATE" StringName
{
$$ = &ast.VariableAssignment{
Name: ast.SetNames,
Value: ast.NewValueExpr($2.(string)),
ExtendValue: ast.NewValueExpr($4.(string)),
Value: ast.NewValueExpr($2.(string), parser.charset, parser.collation),
ExtendValue: ast.NewValueExpr($4.(string), parser.charset, parser.collation),
}
}
| "NAMES" "DEFAULT"
@ -7920,7 +7920,7 @@ VariableAssignment:
CharsetNameOrDefault:
CharsetName
{
$$ = ast.NewValueExpr($1.(string))
$$ = ast.NewValueExpr($1.(string), parser.charset, parser.collation)
}
| "DEFAULT"
{

View File

@ -148,13 +148,13 @@ func (n *ValueExpr) Format(w io.Writer) {
}
// newValueExpr creates a ValueExpr with value, and sets default field type.
func newValueExpr(value interface{}) ast.ValueExpr {
func newValueExpr(value interface{}, charset string, collate string) ast.ValueExpr {
if ve, ok := value.(*ValueExpr); ok {
return ve
}
ve := &ValueExpr{}
ve.SetValue(value)
DefaultTypeForValue(value, &ve.Type)
DefaultTypeForValue(value, &ve.Type, charset, collate)
ve.projectionOffset = -1
return ve
}

View File

@ -431,7 +431,7 @@ func SetBinChsClnFlag(ft *types.FieldType) {
const DefaultFsp = int8(0)
// DefaultTypeForValue returns the default FieldType for the value.
func DefaultTypeForValue(value interface{}, tp *types.FieldType) {
func DefaultTypeForValue(value interface{}, tp *types.FieldType, charset string, collate string) {
switch x := value.(type) {
case nil:
tp.Tp = mysql.TypeNull
@ -465,7 +465,7 @@ func DefaultTypeForValue(value interface{}, tp *types.FieldType) {
// TODO: tp.Flen should be len(x) * 3 (max bytes length of CharsetUTF8)
tp.Flen = len(x)
tp.Decimal = types.UnspecifiedLength
tp.Charset, tp.Collate = charset.GetDefaultCharsetAndCollate()
tp.Charset, tp.Collate = charset, collate
case float32:
tp.Tp = mysql.TypeFloat
s := strconv.FormatFloat(float64(x), 'f', -1, 32)