Add ON DUPLICATE KEY UPDATE support (MySQL).

This commit is contained in:
go-jet 2020-05-03 20:46:21 +02:00
parent 30284af33e
commit 980b9b6aac
18 changed files with 388 additions and 109 deletions

View file

@ -21,11 +21,12 @@ ON CONFLICT (col_bool) DO NOTHING`)
ON CONFLICT (col_bool) ON CONSTRAINT table_pkey DO NOTHING`)
onConflict = &onConflictClause{indexExpressions: ColumnList{table1ColBool, table2ColFloat}}
onConflict.WHERE(table2ColFloat.ADD(table1ColInt).GT(table1ColFloat)).DO_UPDATE(
SET(table1ColBool, Bool(true)).
SET(table1ColInt, Int(1)).
WHERE(table2ColFloat.GT(Float(11.1))),
)
onConflict.WHERE(table2ColFloat.ADD(table1ColInt).GT(table1ColFloat)).
DO_UPDATE(
SET(table1ColBool.SET(Bool(true)),
table1ColInt.SET(Int(11))).
WHERE(table2ColFloat.GT(Float(11.1))),
)
assertClauseSerialize(t, onConflict, `
ON CONFLICT (col_bool, col_float) WHERE (col_float + col_int) > col_float DO UPDATE
SET col_bool = $1,

View file

@ -4,16 +4,15 @@ import "github.com/go-jet/jet/internal/jet"
type conflictAction interface {
jet.Serializer
SET(column jet.ColumnSerializer, expression interface{}) conflictAction
WHERE(condition BoolExpression) conflictAction
}
// SET creates conflict action for ON_CONFLICT clause
func SET(column jet.ColumnSerializer, expression interface{}) conflictAction {
func SET(assigments ...ColumnAssigment) conflictAction {
conflictAction := updateConflictActionImpl{}
conflictAction.doUpdate = jet.KeywordClause{Keyword: "DO UPDATE"}
conflictAction.Serializer = jet.NewSerializerClauseImpl(&conflictAction.doUpdate, &conflictAction.set, &conflictAction.where)
conflictAction.SET(column, expression)
conflictAction.set = assigments
return &conflictAction
}
@ -25,11 +24,6 @@ type updateConflictActionImpl struct {
where jet.ClauseWhere
}
func (u *updateConflictActionImpl) SET(column jet.ColumnSerializer, expression interface{}) conflictAction {
u.set = append(u.set, jet.SetPair{Column: column, Value: jet.ToSerializerValue(expression)})
return u
}
func (u *updateConflictActionImpl) WHERE(condition BoolExpression) conflictAction {
u.where.Condition = condition
return u

View file

@ -153,10 +153,10 @@ func TestInsert_ON_CONFLICT(t *testing.T) {
VALUES("1", "2").
VALUES("theta", "beta").
ON_CONFLICT(table1ColBool).WHERE(table1ColBool.IS_NOT_FALSE()).DO_UPDATE(
SET(table1ColBool, "12").
SET(table2ColInt, 1).
SET(ColumnList{table1Col1, table1ColBool}, jet.ROW(Int(2), String("two"))).
WHERE(table1Col1.GT(Int(2))),
SET(table1ColBool.SET(Bool(true)),
table2ColInt.SET(Int(1)),
ColumnList{table1Col1, table1ColBool}.SET(jet.ROW(Int(2), String("two"))),
).WHERE(table1Col1.GT(Int(2))),
).
RETURNING(table1Col1, table1ColBool)
@ -166,7 +166,7 @@ VALUES ('one', 'two'),
('1', '2'),
('theta', 'beta')
ON CONFLICT (col_bool) WHERE col_bool IS NOT FALSE DO UPDATE
SET col_bool = '12',
SET col_bool = TRUE,
col_int = 1,
(col1, col_bool) = ROW(2, 'two')
WHERE table1.col1 > 2
@ -180,10 +180,10 @@ func TestInsert_ON_CONFLICT_ON_CONSTRAINT(t *testing.T) {
VALUES("one", "two").
VALUES("1", "2").
ON_CONFLICT().ON_CONSTRAINT("idk_primary_key").DO_UPDATE(
SET(table1ColBool, "12").
SET(table2ColInt, 1).
SET(ColumnList{table1Col1, table1ColBool}, jet.ROW(Int(2), String("two"))).
WHERE(table1Col1.GT(Int(2))),
SET(table1ColBool.SET(Bool(false)),
table2ColInt.SET(Int(1)),
ColumnList{table1Col1, table1ColBool}.SET(jet.ROW(Int(2), String("two"))),
).WHERE(table1Col1.GT(Int(2))),
).
RETURNING(table1Col1, table1ColBool)
@ -192,7 +192,7 @@ INSERT INTO db.table1 (col1, col_bool)
VALUES ('one', 'two'),
('1', '2')
ON CONFLICT ON CONSTRAINT idk_primary_key DO UPDATE
SET col_bool = '12',
SET col_bool = FALSE,
col_int = 1,
(col1, col_bool) = ROW(2, 'two')
WHERE table1.col1 > 2

View file

@ -10,3 +10,6 @@ type Projection = jet.Projection
// ProjectionList can be used to create conditional constructed projection list.
type ProjectionList = jet.ProjectionList
// ColumnAssigment is interface wrapper around column assigment
type ColumnAssigment = jet.ColumnAssigment