Skip to content

Commit 99dfe90

Browse files
committed
executor: use sys session to build a view for info_schema.columns retrieval
1 parent ab39717 commit 99dfe90

File tree

2 files changed

+77
-3
lines changed

2 files changed

+77
-3
lines changed

executor/infoschema_reader_test.go

+58
Original file line numberDiff line numberDiff line change
@@ -638,3 +638,61 @@ func TestTablesPKType(t *testing.T) {
638638
tk.MustQuery("SELECT TIDB_PK_TYPE FROM information_schema.tables where table_schema = 'test' and table_name = 't_common'").Check(testkit.Rows("CLUSTERED"))
639639
tk.MustQuery("SELECT TIDB_PK_TYPE FROM information_schema.tables where table_schema = 'INFORMATION_SCHEMA' and table_name = 'TABLES'").Check(testkit.Rows("NONCLUSTERED"))
640640
}
641+
642+
// https://github.com/pingcap/tidb/issues/32459.
643+
func TestJoinSystemTableContainsView(t *testing.T) {
644+
store, clean := testkit.CreateMockStore(t)
645+
defer clean()
646+
tk := testkit.NewTestKit(t, store)
647+
tk.MustExec("use test")
648+
tk.MustExec("create table t (a timestamp, b int);")
649+
tk.MustExec("insert into t values (null, 100);")
650+
tk.MustExec("create view v as select * from t;")
651+
// This is used by grafana when TiDB is specified as the data source.
652+
// See https://github.com/grafana/grafana/blob/e86b6662a187c77656f72bef3b0022bf5ced8b98/public/app/plugins/datasource/mysql/meta_query.ts#L31
653+
for i := 0; i < 10; i++ {
654+
tk.MustQuery(`
655+
SELECT
656+
table_name as table_name,
657+
( SELECT
658+
column_name as column_name
659+
FROM information_schema.columns c
660+
WHERE
661+
c.table_schema = t.table_schema AND
662+
c.table_name = t.table_name AND
663+
c.data_type IN ('timestamp', 'datetime')
664+
ORDER BY ordinal_position LIMIT 1
665+
) AS time_column,
666+
( SELECT
667+
column_name AS column_name
668+
FROM information_schema.columns c
669+
WHERE
670+
c.table_schema = t.table_schema AND
671+
c.table_name = t.table_name AND
672+
c.data_type IN('float', 'int', 'bigint')
673+
ORDER BY ordinal_position LIMIT 1
674+
) AS value_column
675+
FROM information_schema.tables t
676+
WHERE
677+
t.table_schema = database() AND
678+
EXISTS
679+
( SELECT 1
680+
FROM information_schema.columns c
681+
WHERE
682+
c.table_schema = t.table_schema AND
683+
c.table_name = t.table_name AND
684+
c.data_type IN ('timestamp', 'datetime')
685+
) AND
686+
EXISTS
687+
( SELECT 1
688+
FROM information_schema.columns c
689+
WHERE
690+
c.table_schema = t.table_schema AND
691+
c.table_name = t.table_name AND
692+
c.data_type IN('float', 'int', 'bigint')
693+
)
694+
LIMIT 1
695+
;
696+
`).Check(testkit.Rows("t a b"))
697+
}
698+
}

executor/show.go

+19-3
Original file line numberDiff line numberDiff line change
@@ -1895,9 +1895,15 @@ func (e *ShowExec) fetchShowBuiltins() error {
18951895
// Because view's underlying table's column could change or recreate, so view's column type may change over time.
18961896
// To avoid this situation we need to generate a logical plan and extract current column types from Schema.
18971897
func tryFillViewColumnType(ctx context.Context, sctx sessionctx.Context, is infoschema.InfoSchema, dbName model.CIStr, tbl *model.TableInfo) error {
1898-
if tbl.IsView() {
1898+
if !tbl.IsView() {
1899+
return nil
1900+
}
1901+
// We need to run the build plan process in another session because there may be
1902+
// multiple goroutines running at the same time while session is not goroutine-safe.
1903+
// Take joining system table as an example, `fetchBuildSideRows` and `fetchProbeSideChunks` can be run concurrently.
1904+
return runWithSystemSession(sctx, func(s sessionctx.Context) error {
18991905
// Retrieve view columns info.
1900-
planBuilder, _ := plannercore.NewPlanBuilder().Init(sctx, is, &hint.BlockHintProcessor{})
1906+
planBuilder, _ := plannercore.NewPlanBuilder().Init(s, is, &hint.BlockHintProcessor{})
19011907
if viewLogicalPlan, err := planBuilder.BuildDataSourceFromView(ctx, dbName, tbl); err == nil {
19021908
viewSchema := viewLogicalPlan.Schema()
19031909
viewOutputNames := viewLogicalPlan.OutputNames()
@@ -1913,6 +1919,16 @@ func tryFillViewColumnType(ctx context.Context, sctx sessionctx.Context, is info
19131919
} else {
19141920
return err
19151921
}
1922+
return nil
1923+
})
1924+
}
1925+
1926+
func runWithSystemSession(sctx sessionctx.Context, fn func(sessionctx.Context) error) error {
1927+
b := &baseExecutor{ctx: sctx}
1928+
sysCtx, err := b.getSysSession()
1929+
if err != nil {
1930+
return err
19161931
}
1917-
return nil
1932+
defer b.releaseSysSession(sysCtx)
1933+
return fn(sysCtx)
19181934
}

0 commit comments

Comments
 (0)