Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support \N shortcut for null #3943

Merged
merged 18 commits into from
Aug 1, 2017

Conversation

hongyuanw
Copy link
Contributor

For this issue #3685

Support select \N; , allow \N as shortcut for NULL, this sql will return NULL value

Like this :
tidb> select \N;
+------+
| NULL |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

@zhexuany
Copy link
Contributor

@hanfei1991 @tiancaiamao PTAL.

@shenli shenli added the contribution This PR is from a community contributor. label Jul 29, 2017
parser/lexer.go Outdated

if ch0 == '\\' {
// support \N as shortcut for NULL
if s.r.charByIndex(pos.Offset+1) == 'N' {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use s.r.peek()?

Copy link
Contributor Author

@hongyuanw hongyuanw Jul 29, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shenli
Before using s.r.peek()s.r inc() must be called first, because current offset is pointed to '\'.

I want to know if next element is 'N', and don't wanna change offset at the same time .

If next element is not 'N', and s.r.inc() + s.r.peek() are called, we must back to previous offset, it is not convenient .

Copy link
Contributor

@winkyao winkyao Jul 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simplely add initTokenString("\N", null) in the ruleTable init.

@choleraehyq
Copy link
Contributor

I think you can simply add initTokenString("\N", null) at https://github.com/pingcap/tidb/blob/master/parser/misc.go#L122 .

@tiancaiamao

Copy link
Contributor

@winkyao winkyao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@winkyao winkyao added the status/LGT1 Indicates that a PR has LGTM 1. label Jul 30, 2017
@@ -306,6 +307,10 @@ func (trs *tidbResultSet) Columns() ([]*ColumnInfo, error) {
}
var columns []*ColumnInfo
for _, v := range fields {
if v.ColumnAsName.O == "\\N" {
v.ColumnAsName = model.NewCIStr("NULL")
}
Copy link
Contributor

@choleraehyq choleraehyq Jul 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's ugly to deal with it as a exception here. Would you consider renaming column here https://github.com/pingcap/tidb/blob/master/plan/logical_plan_builder.go#L433 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@choleraehyq You are right, doing this work in driver_tidb.go is not good . I have changed it.

@@ -431,6 +431,11 @@ func (b *planBuilder) buildProjection(p LogicalPlan, fields []*ast.SelectField,
}
}
}

if colName.O == "\\N" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a test case for this?
You can add a test case like select \N; and check the column name and row value.

@choleraehyq
Copy link
Contributor

choleraehyq commented Jul 31, 2017

LGTM
What will happen if a user column is named "\N"?

@XuHuaiyu XuHuaiyu added status/LGT2 Indicates that a PR has LGTM 2. and removed status/LGT1 Indicates that a PR has LGTM 1. labels Jul 31, 2017
@choleraehyq choleraehyq added status/LGT1 Indicates that a PR has LGTM 1. and removed status/LGT2 Indicates that a PR has LGTM 2. labels Jul 31, 2017
@tiancaiamao
Copy link
Contributor

Hi, @yuanwhy
You can modify the Scanner.Lex add a special rule:

case null:
    v.item  = nil
    v.ident = "NULL"

and reset changes in plan/logical_plan_builder.go

@hongyuanw
Copy link
Contributor Author

hongyuanw commented Jul 31, 2017

@choleraehyq
if user input is select "\N", output will show this :
tidb> select "\N";
+------+
| "\N" |
+------+
| N |
+------+

in mysql , like this :
mysql> select "\N";
+------+
| N |
+------+
| N |
+------+

mysql column name is "\N", but tidb is N . However, it is another issue , select "a" can test this :
tidb> select "a";
+------+
| "a" |
+------+
| a |
+------+

mysql> select "a";
+---+
| a |
+---+
| a |
+---+

I will add test case for select "\N".

@choleraehyq
Copy link
Contributor

choleraehyq commented Jul 31, 2017

@yuanwhy

create table test (`\N` int);
insert into test values (1);
select * from test;

MySQL:
+------+
| \N |
+------+
| 1 |
+------+
will your PR change column name \N to NULL automatically?

@hongyuanw
Copy link
Contributor Author

hongyuanw commented Jul 31, 2017

1、
@tiancaiamao

case null:
v.item = nil
v.ident = "NULL"

this code in Scanner.Lex doesn't work , because the column name \N is set in parser.go

lastField.SetText(src[lastField.Offset:lastEnd])

That is, parser doesn't use v.ident

2、
@choleraehyq

I have changed code to fix below issue

create table test (\N int);
insert into test values (1);
select * from test;

And some test cases have been added, like :

mysql> select * from test;
+------+
| \N |
+------+
| 1 |
+------+

mysql> select \N from test;
+------+
| NULL |
+------+
| NULL |
+------+

fields, err = rs.Fields()
c.Check(err, IsNil)
c.Check(len(fields), Equals, 1)
c.Check(fields[0].Column.Name.O, Equals, `NULL`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test

select `\N` from test

?
In MySQL this will return \N column.

@@ -426,8 +426,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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

%s/NUll/NULL

@choleraehyq
Copy link
Contributor

Nice done.
LGTM.

@choleraehyq choleraehyq added status/LGT2 Indicates that a PR has LGTM 2. and removed status/LGT1 Indicates that a PR has LGTM 1. labels Aug 1, 2017
@tiancaiamao tiancaiamao merged commit 2745333 into pingcap:master Aug 1, 2017
@hongyuanw hongyuanw deleted the support-shortcut-for-null branch August 1, 2017 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contribution This PR is from a community contributor. status/LGT2 Indicates that a PR has LGTM 2.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants