Skip to content

Commit d372abd

Browse files
cmoogkyleconroy
authored andcommitted
adds support for select stm as insert rows (#258)
1 parent 2839632 commit d372abd

File tree

2 files changed

+56
-30
lines changed

2 files changed

+56
-30
lines changed

internal/mysql/parse.go

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -309,38 +309,46 @@ func parseUpdate(node *sqlparser.Update, query string, s *Schema, settings dinos
309309
}
310310

311311
func parseInsert(node *sqlparser.Insert, query string, s *Schema, settings dinosql.GenerateSettings) (*Query, error) {
312+
params := []*Param{}
312313
cols := node.Columns
313314
tableName := node.Table.Name.String()
314-
rows, ok := node.Rows.(sqlparser.Values)
315-
if !ok {
316-
return nil, fmt.Errorf("Unknown insert row type of %T", node.Rows)
317-
}
318315

319-
params := []*Param{}
320-
321-
for _, row := range rows {
322-
for colIx, item := range row {
323-
switch v := item.(type) {
324-
case *sqlparser.SQLVal:
325-
if v.Type == sqlparser.ValArg {
326-
colName := cols[colIx].String()
327-
colDfn, err := s.schemaLookup(tableName, colName)
328-
varName := string(v.Val)
329-
p := &Param{OriginalName: varName}
330-
if err == nil {
331-
p.Name = paramName(colDfn.Name, varName)
332-
p.Typ = goTypeCol(colDfn, settings)
333-
} else {
334-
p.Name = "Unknown"
335-
p.Typ = "interface{}"
316+
switch rows := node.Rows.(type) {
317+
case *sqlparser.Select:
318+
selectQuery, err := parseSelect(rows, query, s, settings)
319+
if err != nil {
320+
return nil, err
321+
}
322+
params = append(params, selectQuery.Params...)
323+
case sqlparser.Values:
324+
for _, row := range rows {
325+
for colIx, item := range row {
326+
switch v := item.(type) {
327+
case *sqlparser.SQLVal:
328+
if v.Type == sqlparser.ValArg {
329+
colName := cols[colIx].String()
330+
colDfn, err := s.schemaLookup(tableName, colName)
331+
varName := string(v.Val)
332+
p := &Param{OriginalName: varName}
333+
if err == nil {
334+
p.Name = paramName(colDfn.Name, varName)
335+
p.Typ = goTypeCol(colDfn, settings)
336+
} else {
337+
p.Name = "Unknown"
338+
p.Typ = "interface{}"
339+
}
340+
params = append(params, p)
336341
}
337-
params = append(params, p)
342+
343+
default:
344+
panic("Error occurred in parsing INSERT statement")
338345
}
339-
default:
340-
panic("Error occurred in parsing INSERT statement")
341346
}
342347
}
348+
default:
349+
return nil, fmt.Errorf("Unknown insert row type of %T", node.Rows)
343350
}
351+
344352
parsedQuery := &Query{
345353
SQL: query,
346354
Params: params,

internal/mysql/parse_test.go

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -355,16 +355,12 @@ func TestParseInsertUpdate(t *testing.T) {
355355
input expected
356356
output *Query
357357
}
358-
query1 := `/* name: InsertNewUser :exec */
359-
INSERT INTO users (first_name, last_name) VALUES (?, ?)`
360-
query2 := `/* name: UpdateUserAt :exec */
361-
UPDATE users SET first_name = ?, last_name = ? WHERE id > ? AND first_name = ? LIMIT 3`
362358

363359
tests := []testCase{
364360
testCase{
365361
name: "insert_users",
366362
input: expected{
367-
query: query1,
363+
query: "/* name: InsertNewUser :exec */\nINSERT INTO users (first_name, last_name) VALUES (?, ?)",
368364
schema: mockSchema,
369365
},
370366
output: &Query{
@@ -407,7 +403,7 @@ UPDATE users SET first_name = ?, last_name = ? WHERE id > ? AND first_name = ? L
407403
testCase{
408404
name: "update_users",
409405
input: expected{
410-
query: query2,
406+
query: "/* name: UpdateUserAt :exec */\nUPDATE users SET first_name = ?, last_name = ? WHERE id > ? AND first_name = ? LIMIT 3",
411407
schema: mockSchema,
412408
},
413409
output: &Query{
@@ -441,6 +437,28 @@ UPDATE users SET first_name = ?, last_name = ? WHERE id > ? AND first_name = ? L
441437
SchemaLookup: mockSchema,
442438
},
443439
},
440+
testCase{
441+
name: "insert_users_from_orders",
442+
input: expected{
443+
query: "/* name: InsertUsersFromOrders :exec */\ninsert into users ( first_name ) select user_id from orders where id = ?;",
444+
schema: mockSchema,
445+
},
446+
output: &Query{
447+
SQL: "insert into users(first_name) select user_id from orders where id = ?",
448+
Columns: nil,
449+
Params: []*Param{
450+
&Param{
451+
OriginalName: ":v1",
452+
Name: "id",
453+
Typ: "int",
454+
},
455+
},
456+
Name: "InsertUsersFromOrders",
457+
Cmd: ":exec",
458+
DefaultTableName: "users",
459+
SchemaLookup: mockSchema,
460+
},
461+
},
444462
}
445463

446464
for _, tt := range tests {

0 commit comments

Comments
 (0)