Repository: pingcap/tidb (Go)

Issue:
USE_INDEX_MERGE on table with generated column causes a server crash
Consider the following statements:

```sql
CREATE TABLE t0(c0 INT, c1 INT AS (c0));
CREATE INDEX i0 ON t0(c1);
SELECT /*+ USE_INDEX_MERGE(t0, c0_2) */ t0.c0 FROM t0 UNION ALL SELECT 0 FROM t0;
```
Unexpectedly, the `SELECT` causes `tidb-server` to crash with the following stack trace:

```
runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow

runtime stack:
runtime.throw(0x29650fa, 0xe)
	/usr/lib/go-1.13/src/runtime/panic.go:774 +0x72
runtime.newstack()
	/usr/lib/go-1.13/src/runtime/stack.go:1046 +0x6e9
runtime.morestack()
	/usr/lib/go-1.13/src/runtime/asm_amd64.s:449 +0x8f

goroutine 341 [running]:
github.com/pingcap/tidb/expression.extractDependentColumns(0xc033bc0000, 0x49243a, 0x52c800, 0x2d61900, 0xc0294a2820, 0x0, 0x0, 0x0)
	/tidb/expression/util.go:96 +0x25c fp=0xc04965a378 sp=0xc04965a370 pc=0x1b0f88c
github.com/pingcap/tidb/expression.extractDependentColumns(0xc033bc0000, 0x492439, 0x52c800, 0x2d61900, 0xc0294a2820, 0x0, 0x0, 0x0)
	/tidb/expression/util.go:101 +0x1c4 fp=0xc04965a3e8 sp=0xc04965a378 pc=0x1b0f7f4
github.com/pingcap/tidb/expression.extractDependentColumns(0xc033bc0000, 0x492438, 0x52c800, 0x2d61900, 0xc0294a2820, 0x0, 0x0, 0x0)
	/tidb/expression/util.go:101 +0x1c4 fp=0xc04965a458 sp=0xc04965a3e8 pc=0x1b0f7f4
github.com/pingcap/tidb/expression.extractDependentColumns(0xc033bc0000, 0x492437, 0x52c800, 0x2d61900, 0xc0294a2820, 0x0, 0x0, 0x0)
[...]
github.com/pingcap/tidb/expression.extractDependentColumns(0xc033bc0000, 0x4923d7, 0x52c800, 0x2d61900, 0xc0294a2820, 0x0, 0x0, 0x0)
	/tidb/expression/util.go:101 +0x1c4 fp=0xc04965cec8 sp=0xc04965ce58 pc=0x1b0f7f4
...additional frames elided...
created by github.com/pingcap/tidb/server.(*Server).Run
	/tidb/server/server.go:333 +0x709
```

Environment:
```
mysql> select tidb_version();
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tidb_version()                                                                                                                                                                                                                                                                                          |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Release Version: v4.0.0-beta.2-160-g82529c886
Git Commit Hash: 82529c886cb1cfff7810476a136acf81284bac6e
Git Branch: master
UTC Build Time: 2020-04-01 11:44:27
GoVersion: go1.13.4
Race Enabled: false
TiKV Min Version: v3.0.0-60965b006877ca7234adaced7890d7b029ed1306
Check Table Before Drop: false |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
```


Discussion:
@eurekaka PTAL
It has nothing to do with index merge here.

```
SELECT t0.c0 FROM t0 UNION ALL SELECT 0 FROM t0;
```

would cause stack overflow as well. @wjhuang2016 PTAL



Patch:
diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go
index 388320a758f91..9fe7930425de0 100644
--- a/planner/core/logical_plan_builder.go
+++ b/planner/core/logical_plan_builder.go
@@ -2824,7 +2824,7 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as
 				if err != nil {
 					return nil, err
 				}
-				colExpr.VirtualExpr = expr
+				colExpr.VirtualExpr = expr.Clone()
 			}
 		}
 	}


Test patch:
diff --git a/expression/integration_test.go b/expression/integration_test.go
index 49738e08a833b..ed5248de42f08 100755
--- a/expression/integration_test.go
+++ b/expression/integration_test.go
@@ -6010,3 +6010,12 @@ func (s *testIntegrationSuite) TestIssue15790(c *C) {
 	tk.MustQuery("SELECT * FROM t0 WHERE -10000000000000000000 | t0.c0 UNION all SELECT * FROM t0;").Check(testkit.Rows("0", "0"))
 	tk.MustExec("drop table t0;")
 }
+
+func (s *testIntegrationSuite) TestIssue15992(c *C) {
+	tk := testkit.NewTestKitWithInit(c, s.store)
+	tk.MustExec("use test;")
+	tk.MustExec("CREATE TABLE t0(c0 INT, c1 INT AS (c0));")
+	tk.MustExec("CREATE INDEX i0 ON t0(c1);")
+	tk.MustQuery("SELECT t0.c0 FROM t0 UNION ALL SELECT 0 FROM t0;").Check(testkit.Rows())
+	tk.MustExec("drop table t0;")
+}