Repository: pingcap/tidb
File: pkg/planner/core/preprocess.go (Go)

Code before:
			return
		}
	}
}

func (p *preprocessor) updateStateFromStaleReadProcessor() error {
	if p.initedLastSnapshotTS {
		return nil
	}

	if p.IsStaleness = p.staleReadProcessor.IsStaleness(); p.IsStaleness {
		p.LastSnapshotTS = p.staleReadProcessor.GetStalenessReadTS()
		p.SnapshotTSEvaluator = p.staleReadProcessor.GetStalenessTSEvaluatorForPrepare()
		p.InfoSchema = p.staleReadProcessor.GetStalenessInfoSchema()
		p.InfoSchema = &infoschema.SessionExtendedInfoSchema{InfoSchema: p.InfoSchema}
		// If the select statement was like 'select * from t as of timestamp ...' or in a stale read transaction
		// or is affected by the tidb_read_staleness session variable, then the statement will be makred as isStaleness
		// in stmtCtx
		if p.flag&initTxnContextProvider != 0 {
			p.sctx.GetSessionVars().StmtCtx.IsStaleness = true
			if !p.sctx.GetSessionVars().InTxn() {
				txnManager := sessiontxn.GetTxnManager(p.sctx)
				enterType := sessiontxn.EnterNewTxnWithReplaceProvider
				if !p.sctx.GetSessionVars().IsAutocommit() {
					// start a stale-read transaction so that subsequent reads reuse the same snapshot.
					enterType = sessiontxn.EnterNewTxnWithBeginStmt
				}
				newTxnRequest := &sessiontxn.EnterNewTxnRequest{
					Type:     enterType,
					Provider: staleread.NewStalenessTxnContextProvider(p.sctx, p.LastSnapshotTS, p.InfoSchema),
				}
				if err := txnManager.EnterNewTxn(context.TODO(), newTxnRequest); err != nil {
					return err
				}
				if err := txnManager.OnStmtStart(context.TODO(), txnManager.GetCurrentStmt()); err != nil {
					return err
				}
				p.sctx.GetSessionVars().TxnCtx.StaleReadTs = p.LastSnapshotTS
			}
		}
	}
	p.initedLastSnapshotTS = true
	return nil
}

// ensureInfoSchema get the infoschema from the preprocessor.
// there some situations:
//   - the stmt specifies the schema version.
//   - session variable
//   - transaction context
func (p *preprocessor) ensureInfoSchema() infoschema.InfoSchema {

Review comment (suggestion):
`EnterNewTxnWithBeginStmt` seems only be used by by `begin` / `start tarnsaction` only. How about still to use `EnterNewTxnWithReplaceProvider` and check the `IsAutocommit` in `EnterNewTxnWithReplaceProvider:: enterNewStaleTxnWithReplaceProvider ` and if `IsAutocommit ` returns true, you can call `activateStaleTxn`.

https://github.com/pingcap/tidb/blob/bbeaafdd7b9e863629cd0a6c73dd4fe4fa95a08a/pkg/sessiontxn/staleread/provider.go#L78-L88

https://github.com/pingcap/tidb/blob/bbeaafdd7b9e863629cd0a6c73dd4fe4fa95a08a/pkg/sessiontxn/staleread/provider.go#L141-L155

Code after:
			return
		}
	}
}

func (p *preprocessor) updateStateFromStaleReadProcessor() error {
	if p.initedLastSnapshotTS {
		return nil
	}

	if p.IsStaleness = p.staleReadProcessor.IsStaleness(); p.IsStaleness {
		p.LastSnapshotTS = p.staleReadProcessor.GetStalenessReadTS()
		p.SnapshotTSEvaluator = p.staleReadProcessor.GetStalenessTSEvaluatorForPrepare()
		p.InfoSchema = p.staleReadProcessor.GetStalenessInfoSchema()
		p.InfoSchema = &infoschema.SessionExtendedInfoSchema{InfoSchema: p.InfoSchema}
		// If the select statement was like 'select * from t as of timestamp ...' or in a stale read transaction
		// or is affected by the tidb_read_staleness session variable, then the statement will be makred as isStaleness
		// in stmtCtx
		if p.flag&initTxnContextProvider != 0 {
			p.sctx.GetSessionVars().StmtCtx.IsStaleness = true
			if !p.sctx.GetSessionVars().InTxn() {
				txnManager := sessiontxn.GetTxnManager(p.sctx)
				newTxnRequest := &sessiontxn.EnterNewTxnRequest{
					Type:     sessiontxn.EnterNewTxnWithReplaceProvider,
					Provider: staleread.NewStalenessTxnContextProvider(p.sctx, p.LastSnapshotTS, p.InfoSchema),
				}
				if err := txnManager.EnterNewTxn(context.TODO(), newTxnRequest); err != nil {
					return err
				}
				if err := txnManager.OnStmtStart(context.TODO(), txnManager.GetCurrentStmt()); err != nil {
					return err
				}
				p.sctx.GetSessionVars().TxnCtx.StaleReadTs = p.LastSnapshotTS
			}
		}
	}
	p.initedLastSnapshotTS = true
	return nil
}

// ensureInfoSchema get the infoschema from the preprocessor.
// there some situations:
//   - the stmt specifies the schema version.
//   - session variable
//   - transaction context
func (p *preprocessor) ensureInfoSchema() infoschema.InfoSchema {
	if p.InfoSchema != nil {
		return p.InfoSchema
	}

	p.InfoSchema = sessiontxn.GetTxnManager(p.sctx).GetTxnInfoSchema()