Skip to content

Commit

Permalink
executor: use sys session to build view for info_schema.columns ret…
Browse files Browse the repository at this point in the history
…rieval (#33946) (#34251)

close #32459
  • Loading branch information
ti-srebot authored Feb 27, 2023
1 parent bfeca0e commit 3e5bbbe
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 2 deletions.
60 changes: 60 additions & 0 deletions executor/infoschema_reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -981,3 +981,63 @@ func (s *testInfoschemaTableSuite) TestTablesPKType(c *C) {
tk.MustQuery("SELECT TIDB_PK_TYPE FROM information_schema.tables where table_schema = 'test' and table_name = 't_common'").Check(testkit.Rows("CLUSTERED"))
tk.MustQuery("SELECT TIDB_PK_TYPE FROM information_schema.tables where table_schema = 'INFORMATION_SCHEMA' and table_name = 'TABLES'").Check(testkit.Rows("NONCLUSTERED"))
}

// https://github.com/pingcap/tidb/issues/32459.
func (s *testInfoschemaTableSuite) TestJoinSystemTableContainsView(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t;")
tk.MustExec("drop view if exists v;")
tk.MustExec("create table t (a timestamp, b int);")
tk.MustExec("insert into t values (null, 100);")
tk.MustExec("create view v as select * from t;")
// This is used by grafana when TiDB is specified as the data source.
// See https://github.com/grafana/grafana/blob/e86b6662a187c77656f72bef3b0022bf5ced8b98/public/app/plugins/datasource/mysql/meta_query.ts#L31
for i := 0; i < 10; i++ {
tk.MustQuery(`
SELECT
table_name as table_name,
( SELECT
column_name as column_name
FROM information_schema.columns c
WHERE
c.table_schema = t.table_schema AND
c.table_name = t.table_name AND
c.data_type IN ('timestamp', 'datetime')
ORDER BY ordinal_position LIMIT 1
) AS time_column,
( SELECT
column_name AS column_name
FROM information_schema.columns c
WHERE
c.table_schema = t.table_schema AND
c.table_name = t.table_name AND
c.data_type IN('float', 'int', 'bigint')
ORDER BY ordinal_position LIMIT 1
) AS value_column
FROM information_schema.tables t
WHERE
t.table_schema = database() AND
EXISTS
( SELECT 1
FROM information_schema.columns c
WHERE
c.table_schema = t.table_schema AND
c.table_name = t.table_name AND
c.data_type IN ('timestamp', 'datetime')
) AND
EXISTS
( SELECT 1
FROM information_schema.columns c
WHERE
c.table_schema = t.table_schema AND
c.table_name = t.table_name AND
c.data_type IN('float', 'int', 'bigint')
)
LIMIT 1
;
`).Check(testkit.Rows("t a b"))
}
tk.MustExec("drop table if exists t;")
tk.MustExec("drop view if exists v;")
}
27 changes: 25 additions & 2 deletions executor/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -1761,7 +1761,13 @@ func (e *ShowExec) fetchShowBuiltins() error {
// Because view's underlying table's column could change or recreate, so view's column type may change over time.
// To avoid this situation we need to generate a logical plan and extract current column types from Schema.
func tryFillViewColumnType(ctx context.Context, sctx sessionctx.Context, is infoschema.InfoSchema, dbName model.CIStr, tbl *model.TableInfo) error {
if tbl.IsView() {
if !tbl.IsView() {
return nil
}
// We need to run the build plan process in another session because there may be
// multiple goroutines running at the same time while session is not goroutine-safe.
// Take joining system table as an example, `fetchBuildSideRows` and `fetchProbeSideChunks` can be run concurrently.
return runWithSystemSession(sctx, func(s sessionctx.Context) error {
// Retrieve view columns info.
planBuilder, _ := plannercore.NewPlanBuilder(
plannercore.PlanBuilderOptNoExecution{}).Init(sctx, is, &hint.BlockHintProcessor{})
Expand All @@ -1780,6 +1786,23 @@ func tryFillViewColumnType(ctx context.Context, sctx sessionctx.Context, is info
} else {
return err
}
return nil
})
}

func runWithSystemSession(sctx sessionctx.Context, fn func(sessionctx.Context) error) error {
b := &baseExecutor{ctx: sctx}
sysCtx, err := b.getSysSession()
if err != nil {
return err
}
return nil
// TODO(tangenta): remove the CurrentDB assignment after
// https://github.com/pingcap/tidb/issues/34090 is fixed.
originDB := sysCtx.GetSessionVars().CurrentDB
sysCtx.GetSessionVars().CurrentDB = sctx.GetSessionVars().CurrentDB
defer func() {
sysCtx.GetSessionVars().CurrentDB = originDB
}()
defer b.releaseSysSession(sysCtx)
return fn(sysCtx)
}

0 comments on commit 3e5bbbe

Please sign in to comment.