Skip to content

Commit

Permalink
feat: add support to insert mutiple rows
Browse files Browse the repository at this point in the history
  • Loading branch information
thoas committed Jun 18, 2021
1 parent 893939d commit 372dfd5
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 4 deletions.
4 changes: 2 additions & 2 deletions builder/insert.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (b Insert) Values(values ...interface{}) Insert {
panic("loukoum: insert builder has values clause already defined")
}

b.query.Values = stmt.NewValues(stmt.NewArrayExpression(values...))
b.query.Values = stmt.NewValues(stmt.NewArrayListExpression(values...))

return b
}
Expand Down Expand Up @@ -116,7 +116,7 @@ func (b Insert) Set(args ...interface{}) Insert {
pairs := ToSet(args).Pairs
columns, expressions := pairs.Values()

array := stmt.NewArrayExpression(expressions)
array := stmt.NewArrayListExpression(expressions)
values := stmt.NewValues(array)

b.query.Columns = columns
Expand Down
11 changes: 11 additions & 0 deletions builder/insert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,17 @@ func TestInsert_Values(t *testing.T) {
NamedQuery: "INSERT INTO \"table\" (\"data\") VALUES (:arg_1)",
Args: []interface{}{[]byte{1, 2, 3}},
},
{
Name: "With multiple values",
Builders: []builder.Builder{
loukoum.Insert("table").Values([][]string{{"va", "vb", "vc"}, {"wa", "wb", "wc"}}),
loukoum.Insert("table").Values([][]interface{}{{"va", "vb", "vc"}, {"wa", "wb", "wc"}}),
},
String: "INSERT INTO \"table\" VALUES ('va', 'vb', 'vc'), ('wa', 'wb', 'wc')",
Query: "INSERT INTO \"table\" VALUES ($1, $2, $3), ($4, $5, $6)",
NamedQuery: "INSERT INTO \"table\" VALUES (:arg_1, :arg_2, :arg_3), (:arg_4, :arg_5, :arg_6)",
Args: []interface{}{"va", "vb", "vc", "wa", "wb", "wc"},
},
})
}

Expand Down
91 changes: 91 additions & 0 deletions stmt/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,97 @@ var _ Expression = Value{}
// Array
// ----------------------------------------------------------------------------

// ArrayList contains a list of array expression values.
type ArrayList struct {
Values []Expression
}

// NewArrayListExpression creates a new Expression using a list of values.
func NewArrayListExpression(values ...interface{}) Expression { // nolint: gocyclo
// We pass only one argument and it's a slice or an expression.
arraylist := toArrayList(values[0])
if len(arraylist.Values) == 0 {
arraylist.Values = []Expression{NewArrayExpression(values...)}

}
return arraylist
}

func toArrayList(value interface{}) ArrayList { // nolint: gocyclo
arraylist := ArrayList{}
switch values := value.(type) {
case [][]interface{}:
for i := range values {
arraylist.Values = append(arraylist.Values, NewArrayExpression(values[i]...))
}
case [][]string:
for i := range values {
raws := make([]interface{}, len(values[i]))
for j := range values[i] {
raws[j] = values[i][j]
}

arraylist.Values = append(arraylist.Values, NewArrayExpression(raws...))
}
case [][]int:
for i := range values {
raws := make([]interface{}, len(values[i]))
for j := range values[i] {
raws[j] = values[i][j]
}
arraylist.Values = append(arraylist.Values, NewArrayExpression(raws...))
}
case [][]int64:
for i := range values {
raws := make([]interface{}, len(values[i]))
for j := range values[i] {
raws[j] = values[i][j]
}
arraylist.Values = append(arraylist.Values, NewArrayExpression(raws...))
}
case [][]bool:
for i := range values {
raws := make([]interface{}, len(values[i]))
for j := range values[i] {
raws[j] = values[i][j]
}
arraylist.Values = append(arraylist.Values, NewArrayExpression(raws...))
}
case [][]Expression:
for i := range values {
raws := make([]interface{}, len(values[i]))
for j := range values[i] {
raws[j] = values[i][j]
}
arraylist.Values = append(arraylist.Values, NewArrayExpression(raws...))
}
}

return arraylist
}

func (ArrayList) expression() {}

// Write exposes statement as a SQL query.
func (array ArrayList) Write(ctx types.Context) {
for i, value := range array.Values {
if i > 0 {
ctx.Write(", ")
}
ctx.Write("(")
value.Write(ctx)
ctx.Write(")")
}
}

// IsEmpty returns true if statement is undefined.
func (array ArrayList) IsEmpty() bool {
return len(array.Values) == 0
}

// Ensure that Array is an Expression
var _ Expression = ArrayList{}

// Array contains a list of expression values.
type Array struct {
Values []Expression
Expand Down
3 changes: 1 addition & 2 deletions stmt/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ func (values Values) Write(ctx types.Context) {
}

ctx.Write(token.Values.String())
ctx.Write(" (")
ctx.Write(" ")
values.Values.Write(ctx)
ctx.Write(")")
}

// IsEmpty returns true if statement is undefined.
Expand Down

0 comments on commit 372dfd5

Please sign in to comment.