Skip to content

Commit

Permalink
*: only create TemporaryTableAttachedInfoSchema if needed (#37196)
Browse files Browse the repository at this point in the history
close #37195
  • Loading branch information
lcwangchao authored Aug 18, 2022
1 parent a1d1356 commit 44f684e
Show file tree
Hide file tree
Showing 11 changed files with 69 additions and 14 deletions.
21 changes: 19 additions & 2 deletions ddl/db_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3801,8 +3801,15 @@ func TestCreateTempTableInTxn(t *testing.T) {
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("begin")
tk.MustExec("create temporary table t1(id int)")
tk.MustQuery("select * from t1")
// new created temporary table should be visible
tk.MustExec("create temporary table t1(id int primary key, v int)")
tk.MustQuery("select * from t1").Check(testkit.Rows())
// new inserted data should be visible
tk.MustExec("insert into t1 values(123, 456)")
tk.MustQuery("select * from t1 where id=123").Check(testkit.Rows("123 456"))
// truncate table will clear data but table still visible
tk.MustExec("truncate table t1")
tk.MustQuery("select * from t1 where id=123").Check(testkit.Rows())
tk.MustExec("commit")

tk1 := testkit.NewTestKit(t, store)
Expand All @@ -3812,6 +3819,16 @@ func TestCreateTempTableInTxn(t *testing.T) {
tk1.MustExec("create temporary table t1(id int)")
tk1.MustExec("insert into tt select * from t1")
tk1.MustExec("drop table tt")

tk2 := testkit.NewTestKit(t, store)
tk2.MustExec("use test")
tk2.MustExec("create table t2(id int primary key, v int)")
tk2.MustExec("insert into t2 values(234, 567)")
tk2.MustExec("begin")
// create a new temporary table with the same name will override physical table
tk2.MustExec("create temporary table t2(id int primary key, v int)")
tk2.MustQuery("select * from t2 where id=234").Check(testkit.Rows())
tk2.MustExec("commit")
}

// See https://github.com/pingcap/tidb/issues/29327
Expand Down
14 changes: 9 additions & 5 deletions domain/domain.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ import (
"google.golang.org/grpc/keepalive"
)

// NewMockDomain is only used for test
func NewMockDomain() *Domain {
do := &Domain{
infoCache: infoschema.NewCache(1),
}
do.infoCache.Insert(infoschema.MockInfoSchema(nil), 1)
return do
}

// Domain represents a storage space. Different domains can use the same database name.
// Multiple domains can be used in parallel without synchronization.
type Domain struct {
Expand Down Expand Up @@ -332,11 +341,6 @@ func canSkipSchemaCheckerDDL(tp model.ActionType) bool {

// InfoSchema gets the latest information schema from domain.
func (do *Domain) InfoSchema() infoschema.InfoSchema {
if do.infoCache == nil {
// Return nil is for test purpose where domain is not well initialized in session context.
// In real implementation, the code will not reach here.
return nil
}
return do.infoCache.GetLatest()
}

Expand Down
7 changes: 6 additions & 1 deletion executor/ddl.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,12 @@ func (e *DDLExec) createSessionTemporaryTable(s *ast.CreateTableStmt) error {
return err
}

return e.tempTableDDL.CreateLocalTemporaryTable(dbInfo, tbInfo)
if err = e.tempTableDDL.CreateLocalTemporaryTable(dbInfo, tbInfo); err != nil {
return err
}

sessiontxn.GetTxnManager(e.ctx).OnLocalTemporaryTableCreated()
return nil
}

func (e *DDLExec) executeCreateView(s *ast.CreateViewStmt) error {
Expand Down
2 changes: 1 addition & 1 deletion planner/core/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ func MockContext() sessionctx.Context {
Client: &mock.Client{},
}
ctx.GetSessionVars().CurrentDB = "test"
do := &domain.Domain{}
do := domain.NewMockDomain()
if err := do.CreateStatsHandle(ctx); err != nil {
panic(fmt.Sprintf("create mock context panic: %+v", err))
}
Expand Down
2 changes: 1 addition & 1 deletion session/schema_amender_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ func TestAmendCollectAndGenMutations(t *testing.T) {
sessionVars: variable.NewSessionVars(),
}
se.mu.values = make(map[fmt.Stringer]interface{})
domain.BindDomain(se, &domain.Domain{})
domain.BindDomain(se, domain.NewMockDomain())
startStates := []model.SchemaState{model.StateNone, model.StateDeleteOnly, model.StateWriteOnly, model.StateWriteReorganization}
for _, startState := range startStates {
endStatMap := ConstOpAddIndex[startState]
Expand Down
8 changes: 8 additions & 0 deletions session/txnmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,14 @@ func (m *txnManager) OnStmtRetry(ctx context.Context) error {
return m.ctxProvider.OnStmtRetry(ctx)
}

// OnLocalTemporaryTableCreated is the hook that should be called when a temporary table created.
// The provider will update its state then
func (m *txnManager) OnLocalTemporaryTableCreated() {
if m.ctxProvider != nil {
m.ctxProvider.OnLocalTemporaryTableCreated()
}
}

func (m *txnManager) AdviseWarmup() error {
if m.ctxProvider != nil {
return m.ctxProvider.AdviseWarmup()
Expand Down
4 changes: 4 additions & 0 deletions sessiontxn/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ type TxnContextProvider interface {
OnStmtErrorForNextAction(point StmtErrorHandlePoint, err error) (StmtErrorAction, error)
// OnStmtRetry is the hook that should be called when a statement is retried internally.
OnStmtRetry(ctx context.Context) error
// OnLocalTemporaryTableCreated is the hook that should be called when a local temporary table created.
OnLocalTemporaryTableCreated()
// ActivateTxn activates the transaction.
ActivateTxn() (kv.Transaction, error)
}
Expand Down Expand Up @@ -177,6 +179,8 @@ type TxnManager interface {
OnStmtErrorForNextAction(point StmtErrorHandlePoint, err error) (StmtErrorAction, error)
// OnStmtRetry is the hook that should be called when a statement retry
OnStmtRetry(ctx context.Context) error
// OnLocalTemporaryTableCreated is the hook that should be called when a local temporary table created.
OnLocalTemporaryTableCreated()
// ActivateTxn activates the transaction.
ActivateTxn() (kv.Transaction, error)
// GetCurrentStmt returns the current statement node
Expand Down
6 changes: 6 additions & 0 deletions sessiontxn/isolation/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ func (p *baseTxnContextProvider) OnStmtRetry(ctx context.Context) error {
return nil
}

// OnLocalTemporaryTableCreated is the hook that should be called when a local temporary table created.
func (p *baseTxnContextProvider) OnLocalTemporaryTableCreated() {
p.infoSchema = temptable.AttachLocalTemporaryTableInfoSchema(p.sctx, p.infoSchema)
p.sctx.GetSessionVars().TxnCtx.InfoSchema = p.infoSchema
}

// OnStmtErrorForNextAction is the hook that should be called when a new statement get an error
func (p *baseTxnContextProvider) OnStmtErrorForNextAction(point sessiontxn.StmtErrorHandlePoint, err error) (sessiontxn.StmtErrorAction, error) {
switch point {
Expand Down
3 changes: 3 additions & 0 deletions sessiontxn/staleread/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,6 @@ func (p *StalenessTxnContextProvider) GetSnapshotWithStmtReadTS() (kv.Snapshot,
func (p *StalenessTxnContextProvider) GetSnapshotWithStmtForUpdateTS() (kv.Snapshot, error) {
return nil, errors.New("GetSnapshotWithStmtForUpdateTS not supported for stalenessTxnProvider")
}

// OnLocalTemporaryTableCreated will not be called for StalenessTxnContextProvider
func (p *StalenessTxnContextProvider) OnLocalTemporaryTableCreated() {}
2 changes: 1 addition & 1 deletion table/temptable/ddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func TestTruncateLocalTemporaryTable(t *testing.T) {
// truncate when empty
err := ddl.TruncateLocalTemporaryTable(model.NewCIStr("db1"), model.NewCIStr("t1"))
require.True(t, infoschema.ErrTableNotExists.Equal(err))
require.Equal(t, 0, sessVars.LocalTemporaryTables.(*infoschema.LocalTemporaryTables).Count())
require.Nil(t, sessVars.LocalTemporaryTables)
require.Nil(t, sessVars.TemporaryTableData)

// add one table
Expand Down
14 changes: 11 additions & 3 deletions table/temptable/infoschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@ import (

// AttachLocalTemporaryTableInfoSchema attach local temporary table information schema to is
func AttachLocalTemporaryTableInfoSchema(sctx sessionctx.Context, is infoschema.InfoSchema) infoschema.InfoSchema {
localTemporaryTables := getLocalTemporaryTables(sctx)
if localTemporaryTables == nil {
return is
}

if _, ok := is.(*infoschema.TemporaryTableAttachedInfoSchema); ok {
return is
}

localTemporaryTables := getLocalTemporaryTables(sctx)
return &infoschema.TemporaryTableAttachedInfoSchema{
InfoSchema: is,
LocalTemporaryTables: localTemporaryTables,
Expand All @@ -42,8 +46,12 @@ func DetachLocalTemporaryTableInfoSchema(is infoschema.InfoSchema) infoschema.In
}

func getLocalTemporaryTables(sctx sessionctx.Context) *infoschema.LocalTemporaryTables {
// Do not return nil so that new created tables can always be visited through the returned object.
return ensureLocalTemporaryTables(sctx)
localTemporaryTables := sctx.GetSessionVars().LocalTemporaryTables
if localTemporaryTables == nil {
return nil
}

return localTemporaryTables.(*infoschema.LocalTemporaryTables)
}

func ensureLocalTemporaryTables(sctx sessionctx.Context) *infoschema.LocalTemporaryTables {
Expand Down

0 comments on commit 44f684e

Please sign in to comment.