Add ON DUPLICATE KEY UPDATE support (MySQL).
This commit is contained in:
parent
30284af33e
commit
980b9b6aac
18 changed files with 388 additions and 109 deletions
|
|
@ -13,13 +13,15 @@ type InsertStatement interface {
|
|||
MODEL(data interface{}) InsertStatement
|
||||
MODELS(data interface{}) InsertStatement
|
||||
|
||||
ON_DUPLICATE_KEY_UPDATE(assigments ...ColumnAssigment) InsertStatement
|
||||
|
||||
QUERY(selectStatement SelectStatement) InsertStatement
|
||||
}
|
||||
|
||||
func newInsertStatement(table Table, columns []jet.Column) InsertStatement {
|
||||
newInsert := &insertStatementImpl{}
|
||||
newInsert.SerializerStatement = jet.NewStatementImpl(Dialect, jet.InsertStatementType, newInsert,
|
||||
&newInsert.Insert, &newInsert.ValuesQuery)
|
||||
&newInsert.Insert, &newInsert.ValuesQuery, &newInsert.OnDuplicateKey)
|
||||
|
||||
newInsert.Insert.Table = table
|
||||
newInsert.Insert.Columns = columns
|
||||
|
|
@ -30,26 +32,55 @@ func newInsertStatement(table Table, columns []jet.Column) InsertStatement {
|
|||
type insertStatementImpl struct {
|
||||
jet.SerializerStatement
|
||||
|
||||
Insert jet.ClauseInsert
|
||||
ValuesQuery jet.ClauseValuesQuery
|
||||
Insert jet.ClauseInsert
|
||||
ValuesQuery jet.ClauseValuesQuery
|
||||
OnDuplicateKey onDuplicateKeyUpdateClause
|
||||
}
|
||||
|
||||
func (i *insertStatementImpl) VALUES(value interface{}, values ...interface{}) InsertStatement {
|
||||
i.ValuesQuery.Rows = append(i.ValuesQuery.Rows, jet.UnwindRowFromValues(value, values))
|
||||
return i
|
||||
func (is *insertStatementImpl) VALUES(value interface{}, values ...interface{}) InsertStatement {
|
||||
is.ValuesQuery.Rows = append(is.ValuesQuery.Rows, jet.UnwindRowFromValues(value, values))
|
||||
return is
|
||||
}
|
||||
|
||||
func (i *insertStatementImpl) MODEL(data interface{}) InsertStatement {
|
||||
i.ValuesQuery.Rows = append(i.ValuesQuery.Rows, jet.UnwindRowFromModel(i.Insert.GetColumns(), data))
|
||||
return i
|
||||
func (is *insertStatementImpl) MODEL(data interface{}) InsertStatement {
|
||||
is.ValuesQuery.Rows = append(is.ValuesQuery.Rows, jet.UnwindRowFromModel(is.Insert.GetColumns(), data))
|
||||
return is
|
||||
}
|
||||
|
||||
func (i *insertStatementImpl) MODELS(data interface{}) InsertStatement {
|
||||
i.ValuesQuery.Rows = append(i.ValuesQuery.Rows, jet.UnwindRowsFromModels(i.Insert.GetColumns(), data)...)
|
||||
return i
|
||||
func (is *insertStatementImpl) MODELS(data interface{}) InsertStatement {
|
||||
is.ValuesQuery.Rows = append(is.ValuesQuery.Rows, jet.UnwindRowsFromModels(is.Insert.GetColumns(), data)...)
|
||||
return is
|
||||
}
|
||||
|
||||
func (i *insertStatementImpl) QUERY(selectStatement SelectStatement) InsertStatement {
|
||||
i.ValuesQuery.Query = selectStatement
|
||||
return i
|
||||
func (is *insertStatementImpl) ON_DUPLICATE_KEY_UPDATE(assigments ...ColumnAssigment) InsertStatement {
|
||||
is.OnDuplicateKey = assigments
|
||||
return is
|
||||
}
|
||||
|
||||
func (is *insertStatementImpl) QUERY(selectStatement SelectStatement) InsertStatement {
|
||||
is.ValuesQuery.Query = selectStatement
|
||||
return is
|
||||
}
|
||||
|
||||
type onDuplicateKeyUpdateClause []jet.ColumnAssigment
|
||||
|
||||
// Serialize for SetClause
|
||||
func (s onDuplicateKeyUpdateClause) Serialize(statementType jet.StatementType, out *jet.SQLBuilder, options ...jet.SerializeOption) {
|
||||
if len(s) == 0 {
|
||||
return
|
||||
}
|
||||
out.NewLine()
|
||||
out.WriteString("ON DUPLICATE KEY UPDATE")
|
||||
out.IncreaseIdent(24)
|
||||
|
||||
for i, assigment := range s {
|
||||
if i > 0 {
|
||||
out.WriteString(",")
|
||||
out.NewLine()
|
||||
}
|
||||
|
||||
jet.Serialize(assigment, statementType, out, jet.ShortName.WithFallTrough(options)...)
|
||||
}
|
||||
|
||||
out.DecreaseIdent(24)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,3 +133,50 @@ VALUES (DEFAULT, ?);
|
|||
|
||||
assertStatementSql(t, stmt, expectedSQL, "two")
|
||||
}
|
||||
|
||||
func TestInsertOnDuplicateKeyUpdate(t *testing.T) {
|
||||
stmt := func() InsertStatement {
|
||||
return table1.INSERT(table1Col1, table1ColFloat).
|
||||
VALUES(DEFAULT, "two")
|
||||
}
|
||||
|
||||
t.Run("empty list", func(t *testing.T) {
|
||||
stmt := stmt().ON_DUPLICATE_KEY_UPDATE()
|
||||
assertStatementSql(t, stmt, `
|
||||
INSERT INTO db.table1 (col1, col_float)
|
||||
VALUES (DEFAULT, ?);
|
||||
`, "two")
|
||||
})
|
||||
|
||||
t.Run("one set", func(t *testing.T) {
|
||||
stmt := stmt().ON_DUPLICATE_KEY_UPDATE(table1ColFloat.SET(Float(11.1)))
|
||||
assertStatementSql(t, stmt, `
|
||||
INSERT INTO db.table1 (col1, col_float)
|
||||
VALUES (DEFAULT, ?)
|
||||
ON DUPLICATE KEY UPDATE col_float = ?;
|
||||
`, "two", 11.1)
|
||||
})
|
||||
|
||||
t.Run("all types set", func(t *testing.T) {
|
||||
stmt := stmt().ON_DUPLICATE_KEY_UPDATE(
|
||||
table1ColBool.SET(Bool(true)),
|
||||
table1ColInt.SET(Int(11)),
|
||||
table1ColFloat.SET(Float(11.1)),
|
||||
table1ColString.SET(String("str")),
|
||||
table1ColTime.SET(Time(11, 23, 11)),
|
||||
table1ColTimestamp.SET(Timestamp(2020, 1, 22, 3, 4, 5)),
|
||||
table1ColDate.SET(Date(2020, 12, 1)),
|
||||
)
|
||||
assertStatementSql(t, stmt, `
|
||||
INSERT INTO db.table1 (col1, col_float)
|
||||
VALUES (DEFAULT, ?)
|
||||
ON DUPLICATE KEY UPDATE col_bool = ?,
|
||||
col_int = ?,
|
||||
col_float = ?,
|
||||
col_string = ?,
|
||||
col_time = CAST(? AS TIME),
|
||||
col_timestamp = TIMESTAMP(?),
|
||||
col_date = CAST(? AS DATE);
|
||||
`, "two", true, int64(11), 11.1, "str", "11:23:11", "2020-01-22 03:04:05", "2020-12-01")
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -7,12 +7,14 @@ import (
|
|||
)
|
||||
|
||||
var table1Col1 = IntegerColumn("col1")
|
||||
var table1ColBool = BoolColumn("col_bool")
|
||||
var table1ColInt = IntegerColumn("col_int")
|
||||
var table1ColFloat = FloatColumn("col_float")
|
||||
var table1ColString = StringColumn("col_string")
|
||||
var table1Col3 = IntegerColumn("col3")
|
||||
var table1ColTimestamp = TimestampColumn("col_timestamp")
|
||||
var table1ColBool = BoolColumn("col_bool")
|
||||
var table1ColDate = DateColumn("col_date")
|
||||
var table1ColTime = TimeColumn("col_time")
|
||||
|
||||
var table1 = NewTable(
|
||||
"db",
|
||||
|
|
@ -20,10 +22,12 @@ var table1 = NewTable(
|
|||
table1Col1,
|
||||
table1ColInt,
|
||||
table1ColFloat,
|
||||
table1ColString,
|
||||
table1Col3,
|
||||
table1ColBool,
|
||||
table1ColDate,
|
||||
table1ColTimestamp,
|
||||
table1ColTime,
|
||||
)
|
||||
|
||||
var table2Col3 = IntegerColumn("col3")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue