Repository: pingcap/tidb (Go)

Issue:
Update JSON type column from JSON `'null'` to database `NULL` dost not work
## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)

<!-- a step by step guide for reproducing the bug. -->

```sql
CREATE TABLE `t1` (
  `id` int(11) NOT NULL,
  `json` json DEFAULT NULL,
  PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
```

```sql
mysql> INSERT INTO t1 VALUES(1, 'null');
Query OK, 1 row affected (0.01 sec)

mysql> SELECT IFNULL(json, 'it is db null') FROM t1;
+-------------------------------+
| IFNULL(json, 'it is db null') |
+-------------------------------+
| null                          |
+-------------------------------+
1 row in set (0.01 sec)

mysql> UPDATE `t1` SET json = null WHERE id = 1;
Query OK, 0 rows affected (0.01 sec)
Rows matched: 1  Changed: 0  Warnings: 0

mysql> SELECT IFNULL(json, 'it is db null') FROM t1;
+-------------------------------+
| IFNULL(json, 'it is db null') |
+-------------------------------+
| null                          |
+-------------------------------+
1 row in set (0.00 sec)
``` 

If you change from other values to `NULL`, it works.

```sql
mysql> UPDATE `t1` SET json = '{}' WHERE id = 1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> UPDATE `t1` SET json = null WHERE id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT IFNULL(json, 'it is db null') FROM t1;
+-------------------------------+
| IFNULL(json, 'it is db null') |
+-------------------------------+
| it is db null                 |
+-------------------------------+
1 row in set (0.00 sec)
```

### 2. What did you expect to see? (Required)

Should work when updating `NULL` value for the JSON type column with `'null'` value.

### 3. What did you see instead (Required)

Update JSON type column from JSON 'null' to database NULL does not work, as the result `Changed: 0`.

### 4. What is your TiDB version? (Required)

<!-- Paste the output of SELECT tidb_version() -->

```
mysql> SELECT tidb_version()\G
*************************** 1. row ***************************
tidb_version(): Release Version: v6.2.0
Edition: Community
Git Commit Hash: daf2b17cdfe30c02ce282361009fb5bdb05f2b0e
Git Branch: heads/refs/tags/v6.2.0
UTC Build Time: 2022-08-22 13:38:40
GoVersion: go1.18.5
Race Enabled: false
TiKV Min Version: 6.2.0-alpha
Check Table Before Drop: false
Store: tikv
1 row in set (0.00 sec)
```



Discussion:

Patch:
diff --git a/types/datum.go b/types/datum.go
index bb294083d8efa..34639cdf10bdb 100644
--- a/types/datum.go
+++ b/types/datum.go
@@ -855,6 +855,11 @@ func (d *Datum) compareMysqlSet(sc *stmtctx.StatementContext, set Set, comparer
 }
 
 func (d *Datum) compareMysqlJSON(_ *stmtctx.StatementContext, target BinaryJSON) (int, error) {
+	// json is not equal with NULL
+	if d.k == KindNull {
+		return 1, nil
+	}
+
 	origin, err := d.ToMysqlJSON()
 	if err != nil {
 		return 0, errors.Trace(err)


Test patch:
diff --git a/types/datum_test.go b/types/datum_test.go
index 637c1cbc4664e..8d06d7439596e 100644
--- a/types/datum_test.go
+++ b/types/datum_test.go
@@ -676,3 +676,31 @@ func TestProduceDecWithSpecifiedTp(t *testing.T) {
 		}
 	}
 }
+
+func TestNULLNotEqualWithOthers(t *testing.T) {
+	datums := []Datum{
+		NewIntDatum(0),
+		NewUintDatum(0),
+		NewFloat32Datum(0),
+		NewFloat64Datum(0),
+		NewDatum(math.Inf(0)),
+		NewDecimalDatum(NewDecFromStringForTest("0")),
+		NewStringDatum(""),
+		NewCollationStringDatum("", charset.CollationBin),
+		NewDurationDatum(Duration{Duration: time.Duration(0)}),
+		NewTimeDatum(ZeroTime),
+		NewBytesDatum([]byte("")),
+		NewBinaryLiteralDatum([]byte{}),
+		NewMysqlBitDatum(NewBinaryLiteralFromUint(0, 4)),
+		NewJSONDatum(CreateBinaryJSON(nil)),
+		MinNotNullDatum(),
+		MaxValueDatum(),
+	}
+	nullDatum := NewDatum(nil)
+	sc := new(stmtctx.StatementContext)
+	for _, d := range datums {
+		result, err := d.Compare(sc, &nullDatum, collate.GetBinaryCollator())
+		require.NoError(t, err)
+		require.NotEqual(t, 0, result)
+	}
+}