Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

executor: use sys session to build view for info_schema.columns retrieval (#33946) #34251

Merged
merged 3 commits into from
Feb 27, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions executor/infoschema_reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -981,3 +981,61 @@ 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 TestJoinSystemTableContainsView(t *testing.T) {
store, clean := testkit.CreateMockStore(t)
defer clean()
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
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"))
}
}
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)
}