Skip to content

Commit 3e5bbbe

Browse files
authored
executor: use sys session to build view for info_schema.columns retrieval (#33946) (#34251)
close #32459
1 parent bfeca0e commit 3e5bbbe

File tree

2 files changed

+85
-2
lines changed

2 files changed

+85
-2
lines changed

executor/infoschema_reader_test.go

+60
Original file line numberDiff line numberDiff line change
@@ -981,3 +981,63 @@ func (s *testInfoschemaTableSuite) TestTablesPKType(c *C) {
981981
tk.MustQuery("SELECT TIDB_PK_TYPE FROM information_schema.tables where table_schema = 'test' and table_name = 't_common'").Check(testkit.Rows("CLUSTERED"))
982982
tk.MustQuery("SELECT TIDB_PK_TYPE FROM information_schema.tables where table_schema = 'INFORMATION_SCHEMA' and table_name = 'TABLES'").Check(testkit.Rows("NONCLUSTERED"))
983983
}
984+
985+
// https://github.com/pingcap/tidb/issues/32459.
986+
func (s *testInfoschemaTableSuite) TestJoinSystemTableContainsView(c *C) {
987+
tk := testkit.NewTestKit(c, s.store)
988+
tk.MustExec("use test")
989+
tk.MustExec("drop table if exists t;")
990+
tk.MustExec("drop view if exists v;")
991+
tk.MustExec("create table t (a timestamp, b int);")
992+
tk.MustExec("insert into t values (null, 100);")
993+
tk.MustExec("create view v as select * from t;")
994+
// This is used by grafana when TiDB is specified as the data source.
995+
// See https://github.com/grafana/grafana/blob/e86b6662a187c77656f72bef3b0022bf5ced8b98/public/app/plugins/datasource/mysql/meta_query.ts#L31
996+
for i := 0; i < 10; i++ {
997+
tk.MustQuery(`
998+
SELECT
999+
table_name as table_name,
1000+
( SELECT
1001+
column_name as column_name
1002+
FROM information_schema.columns c
1003+
WHERE
1004+
c.table_schema = t.table_schema AND
1005+
c.table_name = t.table_name AND
1006+
c.data_type IN ('timestamp', 'datetime')
1007+
ORDER BY ordinal_position LIMIT 1
1008+
) AS time_column,
1009+
( SELECT
1010+
column_name AS column_name
1011+
FROM information_schema.columns c
1012+
WHERE
1013+
c.table_schema = t.table_schema AND
1014+
c.table_name = t.table_name AND
1015+
c.data_type IN('float', 'int', 'bigint')
1016+
ORDER BY ordinal_position LIMIT 1
1017+
) AS value_column
1018+
FROM information_schema.tables t
1019+
WHERE
1020+
t.table_schema = database() AND
1021+
EXISTS
1022+
( SELECT 1
1023+
FROM information_schema.columns c
1024+
WHERE
1025+
c.table_schema = t.table_schema AND
1026+
c.table_name = t.table_name AND
1027+
c.data_type IN ('timestamp', 'datetime')
1028+
) AND
1029+
EXISTS
1030+
( SELECT 1
1031+
FROM information_schema.columns c
1032+
WHERE
1033+
c.table_schema = t.table_schema AND
1034+
c.table_name = t.table_name AND
1035+
c.data_type IN('float', 'int', 'bigint')
1036+
)
1037+
LIMIT 1
1038+
;
1039+
`).Check(testkit.Rows("t a b"))
1040+
}
1041+
tk.MustExec("drop table if exists t;")
1042+
tk.MustExec("drop view if exists v;")
1043+
}

executor/show.go

+25-2
Original file line numberDiff line numberDiff line change
@@ -1761,7 +1761,13 @@ func (e *ShowExec) fetchShowBuiltins() error {
17611761
// Because view's underlying table's column could change or recreate, so view's column type may change over time.
17621762
// To avoid this situation we need to generate a logical plan and extract current column types from Schema.
17631763
func tryFillViewColumnType(ctx context.Context, sctx sessionctx.Context, is infoschema.InfoSchema, dbName model.CIStr, tbl *model.TableInfo) error {
1764-
if tbl.IsView() {
1764+
if !tbl.IsView() {
1765+
return nil
1766+
}
1767+
// We need to run the build plan process in another session because there may be
1768+
// multiple goroutines running at the same time while session is not goroutine-safe.
1769+
// Take joining system table as an example, `fetchBuildSideRows` and `fetchProbeSideChunks` can be run concurrently.
1770+
return runWithSystemSession(sctx, func(s sessionctx.Context) error {
17651771
// Retrieve view columns info.
17661772
planBuilder, _ := plannercore.NewPlanBuilder(
17671773
plannercore.PlanBuilderOptNoExecution{}).Init(sctx, is, &hint.BlockHintProcessor{})
@@ -1780,6 +1786,23 @@ func tryFillViewColumnType(ctx context.Context, sctx sessionctx.Context, is info
17801786
} else {
17811787
return err
17821788
}
1789+
return nil
1790+
})
1791+
}
1792+
1793+
func runWithSystemSession(sctx sessionctx.Context, fn func(sessionctx.Context) error) error {
1794+
b := &baseExecutor{ctx: sctx}
1795+
sysCtx, err := b.getSysSession()
1796+
if err != nil {
1797+
return err
17831798
}
1784-
return nil
1799+
// TODO(tangenta): remove the CurrentDB assignment after
1800+
// https://github.com/pingcap/tidb/issues/34090 is fixed.
1801+
originDB := sysCtx.GetSessionVars().CurrentDB
1802+
sysCtx.GetSessionVars().CurrentDB = sctx.GetSessionVars().CurrentDB
1803+
defer func() {
1804+
sysCtx.GetSessionVars().CurrentDB = originDB
1805+
}()
1806+
defer b.releaseSysSession(sysCtx)
1807+
return fn(sysCtx)
17851808
}

0 commit comments

Comments
 (0)