Repository: pingcap/tidb (Go)

Issue:
`null div 0` for  partition key expression is incorrect 
## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)
```sql
create table t05(a int) partition by hash (a div 0) partitions 10;
insert into t05 values (NULL);
select  null div 0
```
<!-- a step by step guide for reproducing the bug. -->

### 2. What did you expect to see? (Required)
```sql
mysql > create table t05 (a int) partition by hash (a div 0) partitions 10;
Query OK, 0 rows affected
Time: 0.088s
mysql > insert into t05 values (NULL);
Query OK, 1 row affected
Time: 0.047s
mysql > select * from t05;
+--------+
| a      |
+--------+
| <null> |
+--------+

```
### 3. What did you see instead (Required)
```sql
mysql > create table t05(a int) partition by hash (a div 0) partitions 10;
Query OK, 0 rows affected
Time: 0.218s
mysql > insert into t05 values (NULL);
(1365, 'Division by 0')
mysql root@172.16.4.131:test> select  null div 0
+------------+
| null div 0 |
+------------+
| <null>     |
+------------+
```
### 4. What is your TiDB version? (Required)

<!-- Paste the output of SELECT tidb_version() -->
```sql
mysql > select tidb_version()\G
***************************[ 1. row ]***************************
tidb_version() | Release Version: v5.0.0
Edition: Community
Git Commit Hash: bdac0885cd11bdf571aad9353bfc24e13554b91c
Git Branch: heads/refs/tags/v5.0.0
UTC Build Time: 2021-04-06 16:36:29
GoVersion: go1.13
Race Enabled: false
TiKV Min Version: v3.0.0-60965b006877ca7234adaced7890d7b029ed1306
Check Table Before Drop: false
```



Discussion:
/assign
## 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

<!--
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

<!--
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_arithmetic.go b/expression/builtin_arithmetic.go
index c1a50abc5039e..57bb98ff40051 100644
--- a/expression/builtin_arithmetic.go
+++ b/expression/builtin_arithmetic.go
@@ -780,20 +780,19 @@ func (s *builtinArithmeticIntDivideIntSig) evalInt(row chunk.Row) (int64, bool,
 }
 
 func (s *builtinArithmeticIntDivideIntSig) evalIntWithCtx(sctx sessionctx.Context, row chunk.Row) (int64, bool, error) {
-	b, isNull, err := s.args[1].EvalInt(sctx, row)
-	if isNull || err != nil {
-		return 0, isNull, err
+	b, bIsNull, err := s.args[1].EvalInt(sctx, row)
+	if bIsNull || err != nil {
+		return 0, bIsNull, err
+	}
+	a, aIsNull, err := s.args[0].EvalInt(sctx, row)
+	if aIsNull || err != nil {
+		return 0, aIsNull, err
 	}
 
 	if b == 0 {
 		return 0, true, handleDivisionByZeroError(sctx)
 	}
 
-	a, isNull, err := s.args[0].EvalInt(sctx, row)
-	if isNull || err != nil {
-		return 0, isNull, err
-	}
-
 	var (
 		ret int64
 		val uint64


Test patch:
diff --git a/executor/executor_test.go b/executor/executor_test.go
index b03b90435a5e2..c6a070efd8684 100644
--- a/executor/executor_test.go
+++ b/executor/executor_test.go
@@ -8249,3 +8249,15 @@ func (s *testSuite) TestIssue23609(c *C) {
 	tk.MustQuery("select * from t1 where a < b").Check(testkit.Rows())
 	c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0))
 }
+
+func (s *testSuite1) TestIssue24091(c *C) {
+	tk := testkit.NewTestKit(c, s.store)
+	tk.MustExec("use test;")
+	tk.MustExec("drop table if exists t;")
+	defer tk.MustExec("drop table if exists t;")
+	tk.MustExec("create table t(a int) partition by hash (a div 0) partitions 10;")
+	tk.MustExec("insert into t values (NULL);")
+
+	tk.MustQuery("select null div 0;").Check(testkit.Rows("<nil>"))
+	tk.MustQuery("select * from t;").Check(testkit.Rows("<nil>"))
+}