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

@ -991,6 +991,53 @@ func TestAllTypesInsert(t *testing.T) {
require.NoError(t, err)
}
func TestAllTypesInsertOnDuplicateKeyUpdate(t *testing.T) {
tx, err := db.Begin()
require.NoError(t, err)
toInsert := model.AllTypes{
Boolean: true,
Integer: 124,
Float: 45.67,
Blob: []byte("blob"),
Text: "text",
JSON: "{}",
Time: time.Now(),
Timestamp: time.Now(),
Date: time.Now(),
}
stmt := AllTypes.INSERT(
AllTypes.Boolean,
AllTypes.Integer,
AllTypes.Float,
AllTypes.Blob,
AllTypes.Text,
AllTypes.JSON,
AllTypes.Time,
AllTypes.Timestamp,
AllTypes.Date,
).
MODEL(toInsert).
ON_DUPLICATE_KEY_UPDATE(
AllTypes.Boolean.SET(Bool(false)),
AllTypes.Integer.SET(Int(4)),
AllTypes.Float.SET(Float(0.67)),
AllTypes.Text.SET(String("new text")),
AllTypes.Time.SET(TimeT(time.Now())),
AllTypes.Timestamp.SET(TimestampT(time.Now())),
AllTypes.Date.SET(DateT(time.Now())),
)
fmt.Println(stmt.DebugSql())
_, err = stmt.Exec(tx)
assert.NoError(t, err)
err = tx.Rollback()
require.NoError(t, err)
}
var toInsert = model.AllTypes{
Boolean: false,
BooleanPtr: testutils.BoolPtr(true),

View file

@ -7,6 +7,8 @@ import (
"github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/model"
. "github.com/go-jet/jet/tests/.gentestdata/mysql/test_sample/table"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"math/rand"
"testing"
"time"
)
@ -248,6 +250,46 @@ INSERT INTO test_sample.link (url, name) (
assert.Equal(t, len(youtubeLinks), 2)
}
func TestInsertOnDuplicateKey(t *testing.T) {
randId := rand.Int31()
stmt := Link.INSERT().
VALUES(randId, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT).
VALUES(randId, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT).
ON_DUPLICATE_KEY_UPDATE(
Link.ID.SET(Link.ID.ADD(Int(11))),
Link.Name.SET(String("PostgreSQL Tutorial 2")),
)
testutils.AssertStatementSql(t, stmt, `
INSERT INTO test_sample.link
VALUES (?, ?, ?, DEFAULT),
(?, ?, ?, DEFAULT)
ON DUPLICATE KEY UPDATE id = (id + ?),
name = ?;
`, randId, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial",
randId, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial",
int64(11), "PostgreSQL Tutorial 2")
testutils.AssertExec(t, stmt, db, 3)
newLinks := []model.Link{}
err := SELECT(Link.AllColumns).
FROM(Link).
WHERE(Link.ID.EQ(Int(int64(randId)).ADD(Int(11)))).
Query(db, &newLinks)
require.NoError(t, err)
require.Len(t, newLinks, 1)
require.Equal(t, newLinks[0], model.Link{
ID: randId + 11,
URL: "http://www.postgresqltutorial.com",
Name: "PostgreSQL Tutorial 2",
Description: nil,
})
}
func TestInsertWithQueryContext(t *testing.T) {
cleanUpLinkTable(t)

View file

@ -4,6 +4,8 @@ import (
"database/sql"
"flag"
"github.com/go-jet/jet/tests/dbconfig"
"math/rand"
"time"
_ "github.com/go-sql-driver/mysql"
@ -28,6 +30,7 @@ func sourceIsMariaDB() bool {
}
func TestMain(m *testing.M) {
rand.Seed(time.Now().Unix())
defer profile.Start().Stop()
var err error

View file

@ -2,7 +2,6 @@ package postgres
import (
"context"
"github.com/go-jet/jet/internal/jet"
"github.com/go-jet/jet/internal/testutils"
. "github.com/go-jet/jet/postgres"
"github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/model"
@ -134,8 +133,10 @@ ON CONFLICT ON CONSTRAINT employee_pkey DO NOTHING;
VALUES(100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT).
VALUES(200, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT).
ON_CONFLICT(Link.ID).DO_UPDATE(
SET(Link.ID, Link.EXCLUDED.ID).
SET(Link.URL, "http://www.postgresqltutorial2.com"),
SET(
Link.ID.SET(Link.EXCLUDED.ID),
Link.URL.SET(String("http://www.postgresqltutorial2.com")),
),
).
RETURNING(Link.AllColumns)
@ -161,8 +162,10 @@ RETURNING link.id AS "link.id",
VALUES(100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT).
VALUES(200, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT).
ON_CONFLICT().ON_CONSTRAINT("link_pkey").DO_UPDATE(
SET(Link.ID, Link.EXCLUDED.ID).
SET(Link.URL, "http://www.postgresqltutorial2.com"),
SET(
Link.ID.SET(Link.EXCLUDED.ID),
Link.URL.SET(String("http://www.postgresqltutorial2.com")),
),
).
RETURNING(Link.AllColumns)
@ -188,9 +191,13 @@ RETURNING link.id AS "link.id",
stmt := Link.INSERT(Link.ID, Link.URL, Link.Name, Link.Description).
VALUES(100, "http://www.postgresqltutorial.com", "PostgreSQL Tutorial", DEFAULT).
ON_CONFLICT(Link.ID).WHERE(Link.ID.MUL(Int(2)).GT(Int(10))).DO_UPDATE(
SET(Link.ID, SELECT(MAXi(Link.ID).ADD(Int(1))).FROM(Link)).
SET(ColumnList{Link.Name, Link.Description}, jet.ROW(Link.EXCLUDED.Name, String("new description"))).
WHERE(Link.Description.IS_NOT_NULL()),
SET(
Link.ID.SET(
IntExp(SELECT(MAXi(Link.ID).ADD(Int(1))).
FROM(Link)),
),
ColumnList{Link.Name, Link.Description}.SET(ROW(Link.EXCLUDED.Name, String("new description"))),
).WHERE(Link.Description.IS_NOT_NULL()),
)
testutils.AssertDebugStatementSql(t, stmt, `