func newdriverRows(rs rset.Recordset) *driverRows { r := &driverRows{ rs: rs, done: make(chan int), rows: make(chan interface{}, 500), } go func() { err := io.EOF if e := r.rs.Do(func(data []interface{}) (bool, error) { vv, cloneErr := types.Clone(data) if cloneErr != nil { return false, errors.Trace(cloneErr) } select { case r.rows <- vv: return true, nil case <-r.done: return false, nil } }); e != nil { err = e } select { case r.rows <- err: case <-r.done: } }() return r }
func (t *memTemp) Set(k, v []interface{}) (err error) { vv, err := types.Clone(v) if err != nil { return err } t.tree.Set(append([]interface{}(nil), k...), vv.([]interface{})) return }
// execExecSelect implements `insert table select ... from ...`. func (s *InsertValues) execSelect(t table.Table, cols []*column.Col, ctx context.Context) (rset.Recordset, error) { r, err := s.Sel.Plan(ctx) if err != nil { return nil, errors.Trace(err) } defer r.Close() if len(r.GetFields()) != len(cols) { return nil, errors.Errorf("Column count %d doesn't match value count %d", len(cols), len(r.GetFields())) } var bufRecords [][]interface{} var lastInsertIds []uint64 for { var row *plan.Row row, err = r.Next(ctx) if err != nil { return nil, errors.Trace(err) } if row == nil { break } data0 := make([]interface{}, len(t.Cols())) marked := make(map[int]struct{}, len(cols)) for i, d := range row.Data { data0[cols[i].Offset] = d marked[cols[i].Offset] = struct{}{} } if err = s.initDefaultValues(ctx, t, data0, marked); err != nil { return nil, errors.Trace(err) } if err = column.CastValues(ctx, data0, cols); err != nil { return nil, errors.Trace(err) } if err = column.CheckNotNull(t.Cols(), data0); err != nil { return nil, errors.Trace(err) } var v interface{} v, err = types.Clone(data0) if err != nil { return nil, errors.Trace(err) } bufRecords = append(bufRecords, v.([]interface{})) lastInsertIds = append(lastInsertIds, variable.GetSessionVars(ctx).LastInsertID) } for i, r := range bufRecords { variable.GetSessionVars(ctx).SetLastInsertID(lastInsertIds[i]) if _, err = t.AddRecord(ctx, r); err != nil { return nil, errors.Trace(err) } } return nil, nil }
// execExecSelect implements `insert table select ... from ...`. func (s *InsertIntoStmt) execSelect(t table.Table, cols []*column.Col, ctx context.Context) (_ rset.Recordset, err error) { r, err := s.Sel.Plan(ctx) if err != nil { return nil, errors.Trace(err) } else if len(r.GetFields()) != len(cols) { return nil, errors.Errorf("Column count %d doesn't match value count %d", len(cols), len(r.GetFields())) } var bufRecords [][]interface{} var lastInsertIds []uint64 err = r.Do(ctx, func(_ interface{}, data []interface{}) (more bool, err error) { data0 := make([]interface{}, len(t.Cols())) marked := make(map[int]struct{}, len(cols)) for i, d := range data { data0[cols[i].Offset] = d marked[cols[i].Offset] = struct{}{} } if err = s.initDefaultValues(ctx, t, t.Cols(), data0, marked); err != nil { return false, errors.Trace(err) } if err = column.CastValues(ctx, data0, cols); err != nil { return false, errors.Trace(err) } if err = column.CheckNotNull(t.Cols(), data0); err != nil { return false, errors.Trace(err) } v, err := types.Clone(data0) if err != nil { return false, errors.Trace(err) } bufRecords = append(bufRecords, v.([]interface{})) lastInsertIds = append(lastInsertIds, variable.GetSessionVars(ctx).LastInsertID) return true, nil }) if err != nil { return nil, errors.Trace(err) } for i, r := range bufRecords { variable.GetSessionVars(ctx).SetLastInsertID(lastInsertIds[i]) if _, err = t.AddRecord(ctx, r); err != nil { return nil, errors.Trace(err) } } return nil, nil }
func newdriverRows(rs rset.Recordset) *driverRows { r := &driverRows{ rs: rs, done: make(chan int), rows: make(chan interface{}, 500), } r.wg.Add(1) go func() { // TODO: We may change the whole implementation later, so here just using WaitGroup // to solve issue https://github.com/pingcap/tidb/issues/57 // But if we forget close rows and do commit later, we may still meet this panic // with very little probability. defer r.wg.Done() err := io.EOF if e := r.rs.Do(func(data []interface{}) (bool, error) { vv, cloneErr := types.Clone(data) if cloneErr != nil { return false, errors.Trace(cloneErr) } select { case r.rows <- vv: return true, nil case <-r.done: return false, nil } }); e != nil { err = e } select { case r.rows <- err: case <-r.done: } }() return r }