Repository: pingcap/tidb (Go)

Issue:
LOAD DATA consuming 100% CPU and never finishing
## Bug Report

Please answer these questions before submitting your issue. Thanks!
```sql
<!-- Create loaddata3.bat file -->

number     row data
1          row 1     
2          row 2     
error      12345678901234567890123456789012345678901234567890
3          row 3     
wrong end  12345678901234567890123456789012345678901234567890

```
### 1. Minimal reproduce step (Required)

<!-- a step by step guide for reproducing the bug. -->
```sql
create table t1 (a int, b char(10)) charset latin1;
load data local infile '~/pingcap/Github/tidb-test/MYSQL_TEST/std_data/loaddata3.dat' ignore into table t1 fields terminated by '' enclosed by '' ignore 1 lines;
select * from t1;

```
### 2. What did you expect to see? (Required)
```sql

mysql> create table t1 (a int, b char(10)) charset latin1;
Query OK, 0 rows affected (0.03 sec)

mysql> load data local infile '~/pingcap/Github/tidb-test/MYSQL_TEST/std_data/loaddata3.dat' ignore into table t1 fields terminated by '' enclosed by '' ignore 1 lines;
Query OK, 5 rows affected, 4 warnings (0.02 sec)
Records: 5  Deleted: 0  Skipped: 0  Warnings: 4

mysql> select * from t1;
+------+------------+
| a    | b          |
+------+------------+
|    1 | row 1      |
|    2 | row 2      |
|    0 | 1234567890 |
|    3 | row 3      |
|    0 | 1234567890 |
+------+------------+
5 rows in set (0.00 sec)


```

### 3. What did you see instead (Required)

Nothing for tidb 

### 4. What is your TiDB version? (Required)

<!-- Paste the output of SELECT tidb_version() -->
```sql

| Release Version: v5.4.0
Edition: Community
Git Commit Hash: 55f3b24c1c9f506bd652ef1d162283541e428872
Git Branch: heads/refs/tags/v5.4.0
UTC Build Time: 2022-01-25 08:41:05
GoVersion: go1.16.4
Race Enabled: false
TiKV Min Version: v3.0.0-60965b006877ca7234adaced7890d7b029ed1306
Check Table Before Drop: false |
```


Discussion:
I can reproduce this issue against master:
![image](https://user-images.githubusercontent.com/57982/159365458-f7e0ebda-a593-457e-894d-67e5a9f86fd9.png)

From a simple `LOAD DATA`, the statement never finishes.
Also including from `SHOW PROCESSLIST`. The connection does not respond to KILL:

```sql
tidb> kill tidb 415;
Query OK, 0 rows affected (0.00 sec)

tidb> show processlist;
+------+------+-----------------+------+---------+------+------------+------------------------------------------------------------------------------------------------------+
| Id   | User | Host            | db   | Command | Time | State      | Info                                                                                                 |
+------+------+-----------------+------+---------+------+------------+------------------------------------------------------------------------------------------------------+
|  419 | root | 127.0.0.1:42456 | NULL | Query   |    0 | autocommit | show processlist                                                                                     |
|  415 | root | 127.0.0.1:42452 | test | Query   |  318 | autocommit | load data local infile '/tmp/t'  ignore into table t1 fields terminated by '' enclosed by '' ignore  |
+------+------+-----------------+------+---------+------+------------+------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
```
The infinite loop is caused by [here](https://github.com/pingcap/tidb/blob/e3eea88801f8e541cab564f9789c748369fe759c/executor/load_data.go#L480) (`fieldTermLen` is 0). I found that we doesn't support fixed-row format actually, maybe just returning an error is a quick fix. What do you think @cfzjywxk ?
@zyguan 
Agree, a quick fix is needed.



Patch:
diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go
index 0da9f93dee9d8..c7759f3c8e5a5 100644
--- a/planner/core/planbuilder.go
+++ b/planner/core/planbuilder.go
@@ -3913,6 +3913,10 @@ func (b *PlanBuilder) buildSelectPlanOfInsert(ctx context.Context, insert *ast.I
 }
 
 func (b *PlanBuilder) buildLoadData(ctx context.Context, ld *ast.LoadDataStmt) (Plan, error) {
+	// quick fix for https://github.com/pingcap/tidb/issues/33298
+	if ld.FieldsInfo != nil && len(ld.FieldsInfo.Terminated) == 0 {
+		return nil, ErrNotSupportedYet.GenWithStackByArgs("load data with empty field terminator")
+	}
 	p := LoadData{
 		IsLocal:            ld.IsLocal,
 		OnDuplicate:        ld.OnDuplicate,


Test patch:
diff --git a/executor/write_test.go b/executor/write_test.go
index d205b85a246df..d1f633b60d6ce 100644
--- a/executor/write_test.go
+++ b/executor/write_test.go
@@ -1974,6 +1974,24 @@ func TestIssue18681(t *testing.T) {
 	require.Equal(t, uint16(0), sc.WarningCount())
 }
 
+func TestIssue33298(t *testing.T) {
+	store, clean := testkit.CreateMockStore(t)
+	defer clean()
+	tk := testkit.NewTestKit(t, store)
+	ctx := tk.Session().(sessionctx.Context)
+	defer ctx.SetValue(executor.LoadDataVarKey, nil)
+
+	tk.MustExec("use test")
+	tk.MustExec("drop table if exists load_data_test")
+	tk.MustExec("create table load_data_test (a varchar(10), b varchar(10))")
+
+	// According to https://dev.mysql.com/doc/refman/8.0/en/load-data.html , fixed-row format should be used when fields
+	// terminated by '' and enclosed by ''. However, tidb doesn't support it yet and empty terminator leads to infinite
+	// loop in `indexOfTerminator` (see https://github.com/pingcap/tidb/issues/33298).
+	require.Error(t, tk.ExecToErr("load data local infile '/tmp/nonexistence.csv' into table load_data_test fields terminated by ''"))
+	require.Error(t, tk.ExecToErr("load data local infile '/tmp/nonexistence.csv' into table load_data_test fields terminated by '' enclosed by ''"))
+}
+
 func TestLoadData(t *testing.T) {
 	trivialMsg := "Records: 1  Deleted: 0  Skipped: 0  Warnings: 0"
 	store, clean := testkit.CreateMockStore(t)