Repository: pingcap/tidb (Go)

Issue:
The result of expression nullif is not correct
## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)
```
create table t(a int primary key);
insert into t values(1),(2);
select * from t where nullif(a,a) is null;
```
<!-- a step by step guide for reproducing the bug. -->

### 2. What did you expect to see? (Required)
```
+---+
| a |
+---+
| 1 |
| 2 |
+---+
```
### 3. What did you see instead (Required)
Empty set
### 4. What is your TiDB version? (Required)
Release Version: v4.0.0-beta.2-2287-g280d07c4a-dirty
Edition: Community
Git Commit Hash: 280d07c4a0bab259ed21466f1262e2409805daa5
Git Branch: master
UTC Build Time: 2021-03-05 11:03:56
GoVersion: go1.13
Race Enabled: false
TiKV Min Version: v3.0.0-60965b006877ca7234adaced7890d7b029ed1306
Check Table Before Drop: false
<!-- Paste the output of SELECT tidb_version() -->




Discussion:
The result of statement `select * from t where if(a,null,a) is null;` if also not correct.
Relate to https://github.com/pingcap/tidb/pull/23102, @guo-shaoge Could you take a look?
> Relate to #23102, @guo-shaoge Could you take a look?

Looks like same reason as https://github.com/pingcap/tidb/pull/23102. Trying to fix it.
## Please edit this comment or add a new comment to complete the following information

### Not a bug

1. Remove the 'type/bug' label
2. Add notes to indicate why it is not a bug

### Duplicate bug

1. Add the 'type/duplicate' label
2. Add the link to the original bug

### Bug

Note: Make Sure that 'component', and 'severity' labels are added
Example for how to fill out the template: https://github.com/pingcap/tidb/issues/20100

#### 1. Root Cause Analysis (RCA) (optional) 
<!-- Write down the reason why this bug occurs -->

#### 2. Symptom (optional)

<!-- What will the user see when this bug occurs. The error message may be in the terminal, log or monitoring -->

#### 3. All Trigger Conditions (optional)

<!-- All the user scenarios that may trigger this bug -->

#### 4. Workaround (optional)

#### 5. Affected versions
[4.0.0:v4.0.11],master
<!--
In the format of [start_version:end_version], multiple version ranges are
accepted. If the bug only affects the unreleased version, please input:
"unreleased". For example:

Notes:
  1. Do not use any white spaces in '[]'.
  2. The range in '[]' is a closed interval
  3. The version format is `v$Major.$Minor.$Patch`, the $Majoy and $Minor
     number in a version range should be the same. [v3.0.1:v3.1.2] is
     invalid because the $Minor number of the version range is different.

Example 1: [v3.0.1:v3.0.5], [v4.0.1:v4.0.5]
Example 2: unreleased
-->

#### 6. Fixed versions
master
<!--
The first released version that contains this fix in each minor version. If the bug's affected version has been released, the fixed version should be a detailed version number; If the bug doesn't affect any released version, the fixed version can be "master";  

Example 1: v3.0.13, v4.0.5
Example 2: master
-->



Patch:
diff --git a/expression/builtin_control.go b/expression/builtin_control.go
index f33705c5768f8..13f539648e049 100644
--- a/expression/builtin_control.go
+++ b/expression/builtin_control.go
@@ -68,6 +68,8 @@ func InferType4ControlFuncs(lexp, rexp Expression) *types.FieldType {
 	resultFieldType := &types.FieldType{}
 	if lhs.Tp == mysql.TypeNull {
 		*resultFieldType = *rhs
+		// If any of arg is NULL, result type need unset NotNullFlag.
+		types.SetTypeFlag(&resultFieldType.Flag, mysql.NotNullFlag, false)
 		// If both arguments are NULL, make resulting type BINARY(0).
 		if rhs.Tp == mysql.TypeNull {
 			resultFieldType.Tp = mysql.TypeString
@@ -76,6 +78,7 @@ func InferType4ControlFuncs(lexp, rexp Expression) *types.FieldType {
 		}
 	} else if rhs.Tp == mysql.TypeNull {
 		*resultFieldType = *lhs
+		types.SetTypeFlag(&resultFieldType.Flag, mysql.NotNullFlag, false)
 	} else {
 		resultFieldType = types.AggFieldType([]*types.FieldType{lhs, rhs})
 		evalType := types.AggregateEvalType([]*types.FieldType{lhs, rhs}, &resultFieldType.Flag)


Test patch:
diff --git a/expression/integration_test.go b/expression/integration_test.go
index 52f9bddb713e0..95a6e0faae9c6 100644
--- a/expression/integration_test.go
+++ b/expression/integration_test.go
@@ -3806,6 +3806,17 @@ func (s *testIntegrationSuite) TestCompareBuiltin(c *C) {
 	result.Check(testkit.Rows("0"))
 }
 
+// #23157: make sure if Nullif expr is correct combined with IsNull expr.
+func (s *testIntegrationSuite) TestNullifWithIsNull(c *C) {
+	tk := testkit.NewTestKit(c, s.store)
+	tk.MustExec("use test")
+	tk.MustExec("drop table if exists t")
+	tk.MustExec("create table t(a int not null);")
+	tk.MustExec("insert into t values(1),(2);")
+	rows := tk.MustQuery("select * from t where nullif(a,a) is null;")
+	rows.Check(testkit.Rows("1", "2"))
+}
+
 func (s *testIntegrationSuite) TestAggregationBuiltin(c *C) {
 	defer s.cleanEnv(c)
 	tk := testkit.NewTestKit(c, s.store)