Skip to content

Commit

Permalink
Add mysql "upsert" with column aliases
Browse files Browse the repository at this point in the history
  • Loading branch information
XIELongDragon committed Oct 9, 2021
1 parent 90a0aeb commit f34e0bf
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 1 deletion.
20 changes: 20 additions & 0 deletions exp/insert_clauses.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ type (
HasRows() bool
SetRows(rows []interface{}) InsertClauses

HasAlias() bool
Alias() IdentifierExpression
SetAlias(ie IdentifierExpression) InsertClauses

Vals() [][]interface{}
HasVals() bool
SetVals(vals [][]interface{}) InsertClauses
Expand All @@ -41,6 +45,7 @@ type (
cols ColumnListExpression
into Expression
returning ColumnListExpression
alias IdentifierExpression
rows []interface{}
values [][]interface{}
from AppendableExpression
Expand All @@ -62,6 +67,7 @@ func (ic *insertClauses) clone() *insertClauses {
cols: ic.cols,
into: ic.into,
returning: ic.returning,
alias: ic.alias,
rows: ic.rows,
values: ic.values,
from: ic.from,
Expand Down Expand Up @@ -117,6 +123,20 @@ func (ic *insertClauses) HasReturning() bool {
return ic.returning != nil && !ic.returning.IsEmpty()
}

func (ic *insertClauses) HasAlias() bool {
return ic.alias != nil
}

func (ic *insertClauses) Alias() IdentifierExpression {
return ic.alias
}

func (ic *insertClauses) SetAlias(ie IdentifierExpression) InsertClauses {
ret := ic.clone()
ret.alias = ie
return ret
}

func (ic *insertClauses) SetReturning(cl ColumnListExpression) InsertClauses {
ret := ic.clone()
ret.returning = cl
Expand Down
7 changes: 6 additions & 1 deletion insert_dataset.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,12 @@ func (id *InsertDataset) AppendSQL(b sb.SQLBuilder) {
}

func (id *InsertDataset) GetAs() exp.IdentifierExpression {
return nil
return id.clauses.Alias()
}

// Sets the alias for this dataset. This is typically used when using a Dataset as MySQL upsert
func (id *InsertDataset) As(alias string) *InsertDataset {
return id.copy(id.clauses.SetAlias(T(alias)))
}

func (id *InsertDataset) ReturnsColumns() bool {
Expand Down
31 changes: 31 additions & 0 deletions insert_dataset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,37 @@ func (ids *insertDatasetSuite) TestOnConflict() {
)
}

func (ids *insertDatasetSuite) TestAs() {
du := goqu.DoUpdate("other_items", goqu.Record{"new.a": 1})

bd := goqu.Insert("items").As("new")
ids.assertCases(
insertTestCase{
ds: bd.OnConflict(nil),
clauses: exp.NewInsertClauses().SetInto(goqu.C("items")).
SetAlias(exp.NewIdentifierExpression("", "new", "")),
},
insertTestCase{
ds: bd.OnConflict(goqu.DoNothing()),
clauses: exp.NewInsertClauses().SetInto(goqu.C("items")).
SetAlias(exp.NewIdentifierExpression("", "new", "")).
SetOnConflict(goqu.DoNothing()),
},
insertTestCase{
ds: bd.OnConflict(du),
clauses: exp.NewInsertClauses().
SetAlias(exp.NewIdentifierExpression("", "new", "")).
SetInto(goqu.C("items")).SetOnConflict(du),
},
insertTestCase{
ds: bd,
clauses: exp.NewInsertClauses().
SetAlias(exp.NewIdentifierExpression("", "new", "")).
SetInto(goqu.C("items")),
},
)
}

func (ids *insertDatasetSuite) TestClearOnConflict() {
du := goqu.DoUpdate("other_items", goqu.Record{"a": 1})

Expand Down
4 changes: 4 additions & 0 deletions sqlgen/insert_sql_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ func (isg *insertSQLGenerator) InsertSQL(b sb.SQLBuilder, ic exp.InsertClauses)
default:
isg.defaultValuesSQL(b)
}
if ic.HasAlias() {
b.Write(isg.DialectOptions().AsFragment)
isg.ExpressionSQLGenerator().Generate(b, ic.Alias())
}
isg.onConflictSQL(b, ic.OnConflict())
}

Expand Down
11 changes: 11 additions & 0 deletions sqlgen/insert_sql_generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@ func (igs *insertSQLGeneratorSuite) TestGenerate_onConflict() {
})
icDn := ic.SetOnConflict(exp.NewDoNothingConflictExpression())
icDu := ic.SetOnConflict(exp.NewDoUpdateConflictExpression("test", exp.Record{"a": "b"}))
icAsDu := ic.SetAlias(exp.NewIdentifierExpression("", "new", "")).SetOnConflict(
exp.NewDoUpdateConflictExpression("test", exp.Record{"a": exp.NewIdentifierExpression("", "new", "a")}),
)
icDoc := ic.SetOnConflict(exp.NewDoUpdateConflictExpression("on constraint test", exp.Record{"a": "b"}))
icDuw := ic.SetOnConflict(
exp.NewDoUpdateConflictExpression("test", exp.Record{"a": "b"}).Where(exp.Ex{"foo": true}),
Expand All @@ -283,6 +286,14 @@ func (igs *insertSQLGeneratorSuite) TestGenerate_onConflict() {
args: []interface{}{"a1", "b"},
},

insertTestCase{clause: icAsDu, sql: `INSERT INTO "test" ("a") VALUES ('a1') AS "new" on conflict (test) do update set "a"="new"."a"`},
insertTestCase{
clause: icAsDu,
sql: `INSERT INTO "test" ("a") VALUES (?) AS "new" on conflict (test) do update set "a"="new"."a"`,
isPrepared: true,
args: []interface{}{"a1"},
},

insertTestCase{clause: icDoc, sql: `INSERT INTO "test" ("a") VALUES ('a1') on conflict on constraint test do update set "a"='b'`},
insertTestCase{
clause: icDoc,
Expand Down

0 comments on commit f34e0bf

Please sign in to comment.