Skip to content

Commit

Permalink
parser,plan: support \N shortcut for null (#3943)
Browse files Browse the repository at this point in the history
  • Loading branch information
hongyuanw authored and tiancaiamao committed Aug 1, 2017
1 parent 7874e98 commit 2745333
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 1 deletion.
62 changes: 62 additions & 0 deletions executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,68 @@ func (s *testSuite) TestSelectWithoutFrom(c *C) {
r.Check(testkit.Rows("string"))
}

func (s *testSuite) TestSelectBackslashN(c *C) {
defer func() {
s.cleanEnv(c)
testleak.AfterTest(c)()
}()
tk := testkit.NewTestKit(c, s.store)

sql := `select \N;`
r := tk.MustQuery(sql)
r.Check(testkit.Rows("<nil>"))
rs, err := tk.Exec(sql)
c.Check(err, IsNil)
fields, err := rs.Fields()
c.Check(err, IsNil)
c.Check(len(fields), Equals, 1)
c.Check(fields[0].Column.Name.O, Equals, "NULL")

sql = `select "\N";`
r = tk.MustQuery(sql)
r.Check(testkit.Rows("N"))
rs, err = tk.Exec(sql)
c.Check(err, IsNil)
fields, err = rs.Fields()
c.Check(err, IsNil)
c.Check(len(fields), Equals, 1)
c.Check(fields[0].Column.Name.O, Equals, `"\N"`)

tk.MustExec("use test;")
tk.MustExec("create table test (`\\N` int);")
tk.MustExec("insert into test values (1);")
tk.CheckExecResult(1, 0)
sql = "select * from test;"
r = tk.MustQuery(sql)
r.Check(testkit.Rows("1"))
rs, err = tk.Exec(sql)
c.Check(err, IsNil)
fields, err = rs.Fields()
c.Check(err, IsNil)
c.Check(len(fields), Equals, 1)
c.Check(fields[0].Column.Name.O, Equals, `\N`)

sql = "select \\N from test;"
r = tk.MustQuery(sql)
r.Check(testkit.Rows("<nil>"))
rs, err = tk.Exec(sql)
c.Check(err, IsNil)
fields, err = rs.Fields()
c.Check(err, IsNil)
c.Check(len(fields), Equals, 1)
c.Check(fields[0].Column.Name.O, Equals, `NULL`)

sql = "select `\\N` from test;"
r = tk.MustQuery(sql)
r.Check(testkit.Rows("1"))
rs, err = tk.Exec(sql)
c.Check(err, IsNil)
fields, err = rs.Fields()
c.Check(err, IsNil)
c.Check(len(fields), Equals, 1)
c.Check(fields[0].Column.Name.O, Equals, `\N`)
}

func (s *testSuite) TestSelectLimit(c *C) {
tk := testkit.NewTestKit(c, s.store)
defer func() {
Expand Down
1 change: 1 addition & 0 deletions parser/lexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ func (s *testLexerSuite) TestLiteral(c *C) {
{".1_t_1_x", int('.')},
{"N'some text'", underscoreCS},
{"n'some text'", underscoreCS},
{"\\N", null},
}
runTest(c, table)
}
Expand Down
1 change: 1 addition & 0 deletions parser/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ func init() {
initTokenString("<>", neqSynonym)
initTokenString("<<", lsh)
initTokenString(">>", rsh)
initTokenString("\\N", null)

initTokenFunc("@", startWithAt)
initTokenFunc("/", startWithSlash)
Expand Down
8 changes: 7 additions & 1 deletion plan/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,14 @@ func (b *planBuilder) buildProjection(p LogicalPlan, fields []*ast.SelectField,
if _, ok := innerExpr.(*ast.ValueExpr); ok && innerExpr.Text() != "" {
colName = model.NewCIStr(innerExpr.Text())
} else {
//Change column name \N to NULL, just when original sql contains \N column
fieldText := field.Text()
if fieldText == "\\N" {
fieldText = "NULL"
}

// Remove special comment code for field part, see issue #3739 for detail.
colName = model.NewCIStr(parser.SpecFieldPattern.ReplaceAllStringFunc(field.Text(), parser.TrimComment))
colName = model.NewCIStr(parser.SpecFieldPattern.ReplaceAllStringFunc(fieldText, parser.TrimComment))
}
}
}
Expand Down

0 comments on commit 2745333

Please sign in to comment.