func runStmt(ctx context.Context, s stmt.Statement, args ...interface{}) (rset.Recordset, error) { var err error var rs rset.Recordset // before every execution, we must clear affectedrows. variable.GetSessionVars(ctx).SetAffectedRows(0) switch s.(type) { case *stmts.PreparedStmt: ps := s.(*stmts.PreparedStmt) return runPreparedStmt(ctx, ps) case *stmts.ExecuteStmt: es := s.(*stmts.ExecuteStmt) rs, err = runExecute(ctx, es, args...) if err != nil { return nil, errors.Trace(err) } default: if s.IsDDL() { err = ctx.FinishTxn(false) if err != nil { return nil, errors.Trace(err) } } stmt.BindExecArgs(ctx, args) rs, err = s.Exec(ctx) stmt.ClearExecArgs(ctx) } // MySQL DDL should be auto-commit if err == nil && (s.IsDDL() || variable.ShouldAutocommit(ctx)) { err = ctx.FinishTxn(false) } return rs, errors.Trace(err) }
func (s *testColumnSuite) checkPublicColumn(c *C, ctx context.Context, d *ddl, tblInfo *model.TableInfo, handle int64, col *column.Col, row []types.Datum, columnValue interface{}) { t := testGetTable(c, d, s.dbInfo.ID, tblInfo.ID) _, err := ctx.GetTxn(true) c.Assert(err, IsNil) i := int64(0) oldRow := append(row, types.NewDatum(columnValue)) err = t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { c.Assert(data, DeepEquals, oldRow) i++ return true, nil }) c.Assert(err, IsNil) c.Assert(i, Equals, int64(1)) // Test add a new row. _, err = ctx.GetTxn(true) c.Assert(err, IsNil) newRow := types.MakeDatums(int64(11), int64(22), int64(33), int64(44)) handle, err = t.AddRecord(ctx, newRow) c.Assert(err, IsNil) _, err = ctx.GetTxn(true) c.Assert(err, IsNil) rows := [][]types.Datum{oldRow, newRow} i = int64(0) t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { c.Assert(data, DeepEquals, rows[i]) i++ return true, nil }) c.Assert(i, Equals, int64(2)) // Test remove a row. _, err = ctx.GetTxn(true) c.Assert(err, IsNil) err = t.RemoveRecord(ctx, handle, newRow) c.Assert(err, IsNil) _, err = ctx.GetTxn(true) c.Assert(err, IsNil) i = int64(0) t.IterRecords(ctx, t.FirstKey(), t.Cols(), func(h int64, data []types.Datum, cols []*column.Col) (bool, error) { c.Assert(data, DeepEquals, oldRow) i++ return true, nil }) c.Assert(i, Equals, int64(1)) err = ctx.FinishTxn(false) c.Assert(err, IsNil) s.testGetColumn(c, t, col.Name.L, true) }
func (d *ddl) startJob(ctx context.Context, job *model.Job) error { // for every DDL, we must commit current transaction. if err := ctx.FinishTxn(false); err != nil { return errors.Trace(err) } // Create a new job and queue it. err := kv.RunInNewTxn(d.store, true, func(txn kv.Transaction) error { t := meta.NewMeta(txn) var err error job.ID, err = t.GenGlobalID() if err != nil { return errors.Trace(err) } err = t.EnQueueDDLJob(job) return errors.Trace(err) }) if err != nil { return errors.Trace(err) } // notice worker that we push a new job and wait the job done. asyncNotify(d.jobCh) log.Warnf("start DDL job %v", job) jobID := job.ID var historyJob *model.Job // for a job from start to end, the state of it will be none -> delete only -> write only -> reorganization -> public // for every state change, we will wait as lease 2 * lease time, so here the ticker check is 10 * lease. ticker := time.NewTicker(chooseLeaseTime(10*d.lease, 10*time.Second)) defer ticker.Stop() for { select { case <-d.jobDoneCh: case <-ticker.C: } historyJob, err = d.getHistoryJob(jobID) if err != nil { log.Errorf("get history job err %v, check again", err) continue } else if historyJob == nil { log.Warnf("job %d is not in history, maybe not run", jobID) continue } // if a job is a history table, the state must be JobDone or JobCancel. if historyJob.State == model.JobDone { return nil } return errors.Errorf(historyJob.Error) } }
func (d *ddl) startJob(ctx context.Context, job *model.Job) error { // for every DDL, we must commit current transaction. if err := ctx.FinishTxn(false); err != nil { return errors.Trace(err) } // Create a new job and queue it. err := kv.RunInNewTxn(d.store, false, func(txn kv.Transaction) error { t := meta.NewMeta(txn) var err error job.ID, err = t.GenGlobalID() if err != nil { return errors.Trace(err) } err = t.EnQueueDDLJob(job) return errors.Trace(err) }) if err != nil { return errors.Trace(err) } // notice worker that we push a new job and wait the job done. asyncNotify(d.jobCh) jobID := job.ID ticker := time.NewTicker(10 * time.Second) defer ticker.Stop() for { select { case <-d.jobDoneCh: case <-ticker.C: } job, err = d.getHistoryJob(jobID) if err != nil { log.Errorf("get history job err %v, check again", err) continue } else if job == nil { log.Warnf("job %d is not in history, maybe not run", jobID) continue } // if a job is a history table, the state must be JobDone or JobCancel. if job.State == model.JobDone { return nil } return errors.Errorf("job is %s, err :%v", job.State, job.Error) } }
func (s *testIndexSuite) checkIndexKVExist(c *C, ctx context.Context, t table.Table, handle int64, indexCol *column.IndexedCol, columnValues []interface{}, isExist bool) { c.Assert(len(indexCol.Columns), Equals, len(columnValues)) txn, err := ctx.GetTxn(true) c.Assert(err, IsNil) exist, _, err := indexCol.X.Exist(txn, columnValues, handle) c.Assert(err, IsNil) c.Assert(exist, Equals, isExist) err = ctx.FinishTxn(false) c.Assert(err, IsNil) }
func (s *testColumnSuite) checkColumnKVExist(c *C, ctx context.Context, t table.Table, handle int64, col *column.Col, columnValue interface{}, isExist bool) { txn, err := ctx.GetTxn(true) c.Assert(err, IsNil) key := t.RecordKey(handle, col) data, err := txn.Get(key) if isExist { c.Assert(err, IsNil) v, err1 := tables.DecodeValue(data, &col.FieldType) c.Assert(err1, IsNil) value, err1 := v.ConvertTo(&col.FieldType) c.Assert(err1, IsNil) c.Assert(value.GetValue(), Equals, columnValue) } else { c.Assert(err, NotNil) } err = ctx.FinishTxn(false) c.Assert(err, IsNil) }
func runStmt(ctx context.Context, s ast.Statement, args ...interface{}) (ast.RecordSet, error) { var err error var rs ast.RecordSet // before every execution, we must clear affectedrows. variable.GetSessionVars(ctx).SetAffectedRows(0) if s.IsDDL() { err = ctx.FinishTxn(false) if err != nil { return nil, errors.Trace(err) } } rs, err = s.Exec(ctx) // All the history should be added here. se := ctx.(*session) se.history.add(0, s) // MySQL DDL should be auto-commit if s.IsDDL() || autocommit.ShouldAutocommit(ctx) { if err != nil { ctx.FinishTxn(true) } else { err = ctx.FinishTxn(false) } } return rs, errors.Trace(err) }
func runStmt(ctx context.Context, s stmt.Statement, args ...interface{}) (rset.Recordset, error) { var err error var rs rset.Recordset // before every execution, we must clear affectedrows. variable.GetSessionVars(ctx).SetAffectedRows(0) switch ts := s.(type) { case *stmts.PreparedStmt: rs, err = runPreparedStmt(ctx, ts) case *stmts.ExecuteStmt: rs, err = runExecute(ctx, ts, args...) default: if s.IsDDL() { err = ctx.FinishTxn(false) if err != nil { return nil, errors.Trace(err) } } stmt.BindExecArgs(ctx, args) rs, err = s.Exec(ctx) stmt.ClearExecArgs(ctx) } // All the history should be added here. se := ctx.(*session) switch ts := s.(type) { case *stmts.PreparedStmt: se.history.add(ts.ID, s) case *stmts.ExecuteStmt: se.history.add(ts.ID, s, args...) default: se.history.add(0, s) } // MySQL DDL should be auto-commit if s.IsDDL() || autocommit.ShouldAutocommit(ctx) { if err != nil { ctx.FinishTxn(true) } else { err = ctx.FinishTxn(false) } } return rs, errors.Trace(err) }
// Exec implements the stmt.Statement Exec interface. func (s *CommitStmt) Exec(ctx context.Context) (_ rset.Recordset, err error) { err = ctx.FinishTxn(false) variable.GetSessionVars(ctx).SetStatusFlag(mysql.ServerStatusInTrans, false) return }
// Exec implements the stmt.Statement Exec interface. func (s *CommitStmt) Exec(ctx context.Context) (_ rset.Recordset, err error) { err = ctx.FinishTxn(false) variable.GetSessionVars(ctx).DisableAutocommit = false return }
// Exec implements the stmt.Statement Exec interface. func (s *RollbackStmt) Exec(ctx context.Context) (_ rset.Recordset, err error) { err = ctx.FinishTxn(true) variable.GetSessionVars(ctx).SetStatusInTrans(false) return }