@@ -50,9 +50,13 @@ type InsertValues struct {
50
50
GenColumns []* ast.ColumnName
51
51
GenExprs []expression.Expression
52
52
53
+ insertColumns []* table.Column
54
+
53
55
// colDefaultVals is used to store casted default value.
54
56
// Because not every insert statement needs colDefaultVals, so we will init the buffer lazily.
55
- colDefaultVals []defaultVal
57
+ colDefaultVals []defaultVal
58
+ evalBuffer chunk.MutRow
59
+ evalBufferTypes []* types.FieldType
56
60
}
57
61
58
62
type defaultVal struct {
@@ -61,16 +65,18 @@ type defaultVal struct {
61
65
valid bool
62
66
}
63
67
64
- // getColumns gets the explicitly specified columns of an insert statement. There are three cases:
68
+ // initInsertColumns sets the explicitly specified columns of an insert statement. There are three cases:
65
69
// There are three types of insert statements:
66
70
// 1 insert ... values(...) --> name type column
67
71
// 2 insert ... set x=y... --> set type column
68
72
// 3 insert ... (select ..) --> name type column
69
73
// See https://dev.mysql.com/doc/refman/5.7/en/insert.html
70
- func (e * InsertValues ) getColumns ( tableCols [] * table. Column ) ([] * table. Column , error ) {
74
+ func (e * InsertValues ) initInsertColumns () error {
71
75
var cols []* table.Column
72
76
var err error
73
77
78
+ tableCols := e .Table .Cols ()
79
+
74
80
if len (e .SetList ) > 0 {
75
81
// Process `set` type column.
76
82
columns := make ([]string , 0 , len (e .SetList ))
@@ -82,10 +88,10 @@ func (e *InsertValues) getColumns(tableCols []*table.Column) ([]*table.Column, e
82
88
}
83
89
cols , err = table .FindCols (tableCols , columns , e .Table .Meta ().PKIsHandle )
84
90
if err != nil {
85
- return nil , errors .Errorf ("INSERT INTO %s: %s" , e .Table .Meta ().Name .O , err )
91
+ return errors .Errorf ("INSERT INTO %s: %s" , e .Table .Meta ().Name .O , err )
86
92
}
87
93
if len (cols ) == 0 {
88
- return nil , errors .Errorf ("INSERT INTO %s: empty column" , e .Table .Meta ().Name .O )
94
+ return errors .Errorf ("INSERT INTO %s: empty column" , e .Table .Meta ().Name .O )
89
95
}
90
96
} else if len (e .Columns ) > 0 {
91
97
// Process `name` type column.
@@ -98,7 +104,7 @@ func (e *InsertValues) getColumns(tableCols []*table.Column) ([]*table.Column, e
98
104
}
99
105
cols , err = table .FindCols (tableCols , columns , e .Table .Meta ().PKIsHandle )
100
106
if err != nil {
101
- return nil , errors .Errorf ("INSERT INTO %s: %s" , e .Table .Meta ().Name .O , err )
107
+ return errors .Errorf ("INSERT INTO %s: %s" , e .Table .Meta ().Name .O , err )
102
108
}
103
109
} else {
104
110
// If e.Columns are empty, use all columns instead.
@@ -114,10 +120,25 @@ func (e *InsertValues) getColumns(tableCols []*table.Column) ([]*table.Column, e
114
120
// Check column whether is specified only once.
115
121
err = table .CheckOnce (cols )
116
122
if err != nil {
117
- return nil , errors . Trace ( err )
123
+ return err
118
124
}
125
+ e .insertColumns = cols
126
+ return nil
127
+ }
119
128
120
- return cols , nil
129
+ func (e * InsertValues ) initEvalBuffer () {
130
+ numCols := len (e .Table .Cols ())
131
+ if e .hasExtraHandle {
132
+ numCols ++
133
+ }
134
+ e .evalBufferTypes = make ([]* types.FieldType , numCols )
135
+ for i , col := range e .Table .Cols () {
136
+ e .evalBufferTypes [i ] = & col .FieldType
137
+ }
138
+ if e .hasExtraHandle {
139
+ e .evalBufferTypes [len (e .evalBufferTypes )- 1 ] = types .NewFieldType (mysql .TypeLonglong )
140
+ }
141
+ e .evalBuffer = chunk .MutRowFromTypes (e .evalBufferTypes )
121
142
}
122
143
123
144
func (e * InsertValues ) lazilyInitColDefaultValBuf () (ok bool ) {
@@ -150,7 +171,7 @@ func (e *InsertValues) processSetList() error {
150
171
}
151
172
152
173
// insertRows processes `insert|replace into values ()` or `insert|replace into set x=y`
153
- func (e * InsertValues ) insertRows (cols [] * table. Column , exec func (rows [][]types.Datum ) error ) (err error ) {
174
+ func (e * InsertValues ) insertRows (exec func (rows [][]types.Datum ) error ) (err error ) {
154
175
// For `insert|replace into set x=y`, process the set list here.
155
176
if err = e .processSetList (); err != nil {
156
177
return errors .Trace (err )
@@ -159,7 +180,7 @@ func (e *InsertValues) insertRows(cols []*table.Column, exec func(rows [][]types
159
180
rows := make ([][]types.Datum , 0 , len (e .Lists ))
160
181
for i , list := range e .Lists {
161
182
e .rowCount ++
162
- row , err := e .evalRow (cols , list , i )
183
+ row , err := e .evalRow (list , i )
163
184
if err != nil {
164
185
return errors .Trace (err )
165
186
}
@@ -189,7 +210,7 @@ func (e *InsertValues) handleErr(col *table.Column, val *types.Datum, rowIdx int
189
210
190
211
// evalRow evaluates a to-be-inserted row. The value of the column may base on another column,
191
212
// so we use setValueForRefColumn to fill the empty row some default values when needFillDefaultValues is true.
192
- func (e * InsertValues ) evalRow (cols [] * table. Column , list []expression.Expression , rowIdx int ) ([]types.Datum , error ) {
213
+ func (e * InsertValues ) evalRow (list []expression.Expression , rowIdx int ) ([]types.Datum , error ) {
193
214
rowLen := len (e .Table .Cols ())
194
215
if e .hasExtraHandle {
195
216
rowLen ++
@@ -204,18 +225,20 @@ func (e *InsertValues) evalRow(cols []*table.Column, list []expression.Expressio
204
225
}
205
226
}
206
227
228
+ e .evalBuffer .SetDatums (row ... )
207
229
for i , expr := range list {
208
- val , err := expr .Eval (chunk . MutRowFromDatums ( row ) .ToRow ())
209
- if err = e .handleErr (cols [i ], & val , rowIdx , err ); err != nil {
230
+ val , err := expr .Eval (e . evalBuffer .ToRow ())
231
+ if err = e .handleErr (e . insertColumns [i ], & val , rowIdx , err ); err != nil {
210
232
return nil , errors .Trace (err )
211
233
}
212
- val1 , err := table .CastValue (e .ctx , val , cols [i ].ToInfo ())
213
- if err = e .handleErr (cols [i ], & val , rowIdx , err ); err != nil {
234
+ val1 , err := table .CastValue (e .ctx , val , e . insertColumns [i ].ToInfo ())
235
+ if err = e .handleErr (e . insertColumns [i ], & val , rowIdx , err ); err != nil {
214
236
return nil , errors .Trace (err )
215
237
}
216
238
217
- offset := cols [i ].Offset
218
- row [offset ], hasValue [offset ] = val1 , true
239
+ offset := e .insertColumns [i ].Offset
240
+ row [offset ], hasValue [offset ] = * val1 .Copy (), true
241
+ e .evalBuffer .SetDatum (offset , val1 )
219
242
}
220
243
221
244
return e .fillRow (row , hasValue )
@@ -251,7 +274,7 @@ func (e *InsertValues) setValueForRefColumn(row []types.Datum, hasValue []bool)
251
274
return nil
252
275
}
253
276
254
- func (e * InsertValues ) insertRowsFromSelect (ctx context.Context , cols [] * table. Column , exec func (rows [][]types.Datum ) error ) error {
277
+ func (e * InsertValues ) insertRowsFromSelect (ctx context.Context , exec func (rows [][]types.Datum ) error ) error {
255
278
// process `insert|replace into ... select ... from ...`
256
279
selectExec := e .children [0 ]
257
280
fields := selectExec .retTypes ()
@@ -275,7 +298,7 @@ func (e *InsertValues) insertRowsFromSelect(ctx context.Context, cols []*table.C
275
298
for innerChunkRow := iter .Begin (); innerChunkRow != iter .End (); innerChunkRow = iter .Next () {
276
299
innerRow := types .CopyRow (innerChunkRow .GetDatumRow (fields ))
277
300
e .rowCount ++
278
- row , err := e .getRow (cols , innerRow )
301
+ row , err := e .getRow (innerRow )
279
302
if err != nil {
280
303
return errors .Trace (err )
281
304
}
@@ -305,16 +328,16 @@ func (e *InsertValues) insertRowsFromSelect(ctx context.Context, cols []*table.C
305
328
// getRow gets the row which from `insert into select from` or `load data`.
306
329
// The input values from these two statements are datums instead of
307
330
// expressions which are used in `insert into set x=y`.
308
- func (e * InsertValues ) getRow (cols [] * table. Column , vals []types.Datum ) ([]types.Datum , error ) {
331
+ func (e * InsertValues ) getRow (vals []types.Datum ) ([]types.Datum , error ) {
309
332
row := make ([]types.Datum , len (e .Table .Cols ()))
310
333
hasValue := make ([]bool , len (e .Table .Cols ()))
311
334
for i , v := range vals {
312
- casted , err := table .CastValue (e .ctx , v , cols [i ].ToInfo ())
335
+ casted , err := table .CastValue (e .ctx , v , e . insertColumns [i ].ToInfo ())
313
336
if e .filterErr (err ) != nil {
314
337
return nil , errors .Trace (err )
315
338
}
316
339
317
- offset := cols [i ].Offset
340
+ offset := e . insertColumns [i ].Offset
318
341
row [offset ] = casted
319
342
hasValue [offset ] = true
320
343
}
0 commit comments