[postgres] Add support for ON CONFLICT clause

This commit is contained in:
go-jet 2020-04-12 18:53:57 +02:00
parent eea776a1ac
commit 14e1863456
42 changed files with 827 additions and 277 deletions

View file

@ -76,7 +76,7 @@ func assertGeneratedFiles(t *testing.T) {
testutils.AssertFileNamesEqual(t, viewSQLBuilderFiles, "actor_info.go", "film_list.go", "nicer_but_slower_film_list.go",
"sales_by_film_category.go", "customer_list.go", "sales_by_store.go", "staff_list.go")
testutils.AssertFileContent(t, genTestDir3+"/dvds/view/actor_info.go", "\npackage view", actorInfoSQLBuilerFile)
testutils.AssertFileContent(t, genTestDir3+"/dvds/view/actor_info.go", "\npackage view", actorInfoSQLBuilderFile)
// Enums SQL Builder files
enumFiles, err := ioutil.ReadDir(genTestDir3 + "/dvds/enum")
@ -128,7 +128,7 @@ import (
var Actor = newActorTable()
type ActorTable struct {
type actorTable struct {
mysql.Table
//Columns
@ -141,25 +141,38 @@ type ActorTable struct {
MutableColumns mysql.ColumnList
}
type ActorTable struct {
actorTable
EXCLUDED actorTable
}
// creates new ActorTable with assigned alias
func (a *ActorTable) AS(alias string) *ActorTable {
aliasTable := newActorTable()
aliasTable.Table.AS(alias)
return aliasTable
}
func newActorTable() *ActorTable {
return &ActorTable{
actorTable: newActorTableImpl("dvds", "actor"),
EXCLUDED: newActorTableImpl("", "excluded"),
}
}
func newActorTableImpl(schemaName, tableName string) actorTable {
var (
ActorIDColumn = mysql.IntegerColumn("actor_id")
FirstNameColumn = mysql.StringColumn("first_name")
LastNameColumn = mysql.StringColumn("last_name")
LastUpdateColumn = mysql.TimestampColumn("last_update")
allColumns = mysql.ColumnList{ActorIDColumn, FirstNameColumn, LastNameColumn, LastUpdateColumn}
mutableColumns = mysql.ColumnList{FirstNameColumn, LastNameColumn, LastUpdateColumn}
)
return &ActorTable{
Table: mysql.NewTable("dvds", "actor", ActorIDColumn, FirstNameColumn, LastNameColumn, LastUpdateColumn),
return actorTable{
Table: mysql.NewTable(schemaName, tableName, allColumns...),
//Columns
ActorID: ActorIDColumn,
@ -167,8 +180,8 @@ func newActorTable() *ActorTable {
LastName: LastNameColumn,
LastUpdate: LastUpdateColumn,
AllColumns: mysql.ColumnList{ActorIDColumn, FirstNameColumn, LastNameColumn, LastUpdateColumn},
MutableColumns: mysql.ColumnList{FirstNameColumn, LastNameColumn, LastUpdateColumn},
AllColumns: allColumns,
MutableColumns: mutableColumns,
}
}
`
@ -188,7 +201,7 @@ type Actor struct {
}
`
var actorInfoSQLBuilerFile = `
var actorInfoSQLBuilderFile = `
package view
import (
@ -197,7 +210,7 @@ import (
var ActorInfo = newActorInfoTable()
type ActorInfoTable struct {
type actorInfoTable struct {
mysql.Table
//Columns
@ -210,25 +223,38 @@ type ActorInfoTable struct {
MutableColumns mysql.ColumnList
}
type ActorInfoTable struct {
actorInfoTable
EXCLUDED actorInfoTable
}
// creates new ActorInfoTable with assigned alias
func (a *ActorInfoTable) AS(alias string) *ActorInfoTable {
aliasTable := newActorInfoTable()
aliasTable.Table.AS(alias)
return aliasTable
}
func newActorInfoTable() *ActorInfoTable {
return &ActorInfoTable{
actorInfoTable: newActorInfoTableImpl("dvds", "actor_info"),
EXCLUDED: newActorInfoTableImpl("", "excluded"),
}
}
func newActorInfoTableImpl(schemaName, tableName string) actorInfoTable {
var (
ActorIDColumn = mysql.IntegerColumn("actor_id")
FirstNameColumn = mysql.StringColumn("first_name")
LastNameColumn = mysql.StringColumn("last_name")
FilmInfoColumn = mysql.StringColumn("film_info")
allColumns = mysql.ColumnList{ActorIDColumn, FirstNameColumn, LastNameColumn, FilmInfoColumn}
mutableColumns = mysql.ColumnList{ActorIDColumn, FirstNameColumn, LastNameColumn, FilmInfoColumn}
)
return &ActorInfoTable{
Table: mysql.NewTable("dvds", "actor_info", ActorIDColumn, FirstNameColumn, LastNameColumn, FilmInfoColumn),
return actorInfoTable{
Table: mysql.NewTable(schemaName, tableName, allColumns...),
//Columns
ActorID: ActorIDColumn,
@ -236,8 +262,8 @@ func newActorInfoTable() *ActorInfoTable {
LastName: LastNameColumn,
FilmInfo: FilmInfoColumn,
AllColumns: mysql.ColumnList{ActorIDColumn, FirstNameColumn, LastNameColumn, FilmInfoColumn},
MutableColumns: mysql.ColumnList{ActorIDColumn, FirstNameColumn, LastNameColumn, FilmInfoColumn},
AllColumns: allColumns,
MutableColumns: mutableColumns,
}
}
`

View file

@ -15,10 +15,10 @@ func TestInsertValues(t *testing.T) {
cleanUpLinkTable(t)
var expectedSQL = `
INSERT INTO test_sample.link (id, url, name, description) VALUES
(100, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT),
(101, 'http://www.google.com', 'Google', DEFAULT),
(102, 'http://www.yahoo.com', 'Yahoo', NULL);
INSERT INTO test_sample.link (id, url, name, description)
VALUES (100, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT),
(101, 'http://www.google.com', 'Google', DEFAULT),
(102, 'http://www.yahoo.com', 'Yahoo', NULL);
`
insertQuery := Link.INSERT(Link.ID, Link.URL, Link.Name, Link.Description).
@ -69,8 +69,8 @@ func TestInsertEmptyColumnList(t *testing.T) {
cleanUpLinkTable(t)
expectedSQL := `
INSERT INTO test_sample.link VALUES
(100, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT);
INSERT INTO test_sample.link
VALUES (100, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT);
`
stmt := Link.INSERT().
@ -97,8 +97,8 @@ INSERT INTO test_sample.link VALUES
func TestInsertModelObject(t *testing.T) {
cleanUpLinkTable(t)
var expectedSQL = `
INSERT INTO test_sample.link (url, name) VALUES
('http://www.duckduckgo.com', 'Duck Duck go');
INSERT INTO test_sample.link (url, name)
VALUES ('http://www.duckduckgo.com', 'Duck Duck go');
`
linkData := model.Link{
@ -119,8 +119,8 @@ INSERT INTO test_sample.link (url, name) VALUES
func TestInsertModelObjectEmptyColumnList(t *testing.T) {
cleanUpLinkTable(t)
var expectedSQL = `
INSERT INTO test_sample.link VALUES
(1000, 'http://www.duckduckgo.com', 'Duck Duck go', NULL);
INSERT INTO test_sample.link
VALUES (1000, 'http://www.duckduckgo.com', 'Duck Duck go', NULL);
`
linkData := model.Link{
@ -141,10 +141,10 @@ INSERT INTO test_sample.link VALUES
func TestInsertModelsObject(t *testing.T) {
expectedSQL := `
INSERT INTO test_sample.link (url, name) VALUES
('http://www.postgresqltutorial.com', 'PostgreSQL Tutorial'),
('http://www.google.com', 'Google'),
('http://www.yahoo.com', 'Yahoo');
INSERT INTO test_sample.link (url, name)
VALUES ('http://www.postgresqltutorial.com', 'PostgreSQL Tutorial'),
('http://www.google.com', 'Google'),
('http://www.yahoo.com', 'Yahoo');
`
tutorial := model.Link{
@ -177,11 +177,11 @@ INSERT INTO test_sample.link (url, name) VALUES
func TestInsertUsingMutableColumns(t *testing.T) {
var expectedSQL = `
INSERT INTO test_sample.link (url, name, description) VALUES
('http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT),
('http://www.google.com', 'Google', NULL),
('http://www.google.com', 'Google', NULL),
('http://www.yahoo.com', 'Yahoo', NULL);
INSERT INTO test_sample.link (url, name, description)
VALUES ('http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT),
('http://www.google.com', 'Google', NULL),
('http://www.google.com', 'Google', NULL),
('http://www.yahoo.com', 'Yahoo', NULL);
`
google := model.Link{

View file

@ -161,7 +161,7 @@ import (
var Actor = newActorTable()
type ActorTable struct {
type actorTable struct {
postgres.Table
//Columns
@ -174,25 +174,38 @@ type ActorTable struct {
MutableColumns postgres.ColumnList
}
type ActorTable struct {
actorTable
EXCLUDED actorTable
}
// creates new ActorTable with assigned alias
func (a *ActorTable) AS(alias string) *ActorTable {
aliasTable := newActorTable()
aliasTable.Table.AS(alias)
return aliasTable
}
func newActorTable() *ActorTable {
return &ActorTable{
actorTable: newActorTableImpl("dvds", "actor"),
EXCLUDED: newActorTableImpl("", "excluded"),
}
}
func newActorTableImpl(schemaName, tableName string) actorTable {
var (
ActorIDColumn = postgres.IntegerColumn("actor_id")
FirstNameColumn = postgres.StringColumn("first_name")
LastNameColumn = postgres.StringColumn("last_name")
LastUpdateColumn = postgres.TimestampColumn("last_update")
allColumns = postgres.ColumnList{ActorIDColumn, FirstNameColumn, LastNameColumn, LastUpdateColumn}
mutableColumns = postgres.ColumnList{FirstNameColumn, LastNameColumn, LastUpdateColumn}
)
return &ActorTable{
Table: postgres.NewTable("dvds", "actor", ActorIDColumn, FirstNameColumn, LastNameColumn, LastUpdateColumn),
return actorTable{
Table: postgres.NewTable(schemaName, tableName, allColumns...),
//Columns
ActorID: ActorIDColumn,
@ -200,8 +213,8 @@ func newActorTable() *ActorTable {
LastName: LastNameColumn,
LastUpdate: LastUpdateColumn,
AllColumns: postgres.ColumnList{ActorIDColumn, FirstNameColumn, LastNameColumn, LastUpdateColumn},
MutableColumns: postgres.ColumnList{FirstNameColumn, LastNameColumn, LastUpdateColumn},
AllColumns: allColumns,
MutableColumns: mutableColumns,
}
}
`
@ -230,7 +243,7 @@ import (
var ActorInfo = newActorInfoTable()
type ActorInfoTable struct {
type actorInfoTable struct {
postgres.Table
//Columns
@ -243,25 +256,38 @@ type ActorInfoTable struct {
MutableColumns postgres.ColumnList
}
type ActorInfoTable struct {
actorInfoTable
EXCLUDED actorInfoTable
}
// creates new ActorInfoTable with assigned alias
func (a *ActorInfoTable) AS(alias string) *ActorInfoTable {
aliasTable := newActorInfoTable()
aliasTable.Table.AS(alias)
return aliasTable
}
func newActorInfoTable() *ActorInfoTable {
return &ActorInfoTable{
actorInfoTable: newActorInfoTableImpl("dvds", "actor_info"),
EXCLUDED: newActorInfoTableImpl("", "excluded"),
}
}
func newActorInfoTableImpl(schemaName, tableName string) actorInfoTable {
var (
ActorIDColumn = postgres.IntegerColumn("actor_id")
FirstNameColumn = postgres.StringColumn("first_name")
LastNameColumn = postgres.StringColumn("last_name")
FilmInfoColumn = postgres.StringColumn("film_info")
allColumns = postgres.ColumnList{ActorIDColumn, FirstNameColumn, LastNameColumn, FilmInfoColumn}
mutableColumns = postgres.ColumnList{ActorIDColumn, FirstNameColumn, LastNameColumn, FilmInfoColumn}
)
return &ActorInfoTable{
Table: postgres.NewTable("dvds", "actor_info", ActorIDColumn, FirstNameColumn, LastNameColumn, FilmInfoColumn),
return actorInfoTable{
Table: postgres.NewTable(schemaName, tableName, allColumns...),
//Columns
ActorID: ActorIDColumn,
@ -269,8 +295,8 @@ func newActorInfoTable() *ActorInfoTable {
LastName: LastNameColumn,
FilmInfo: FilmInfoColumn,
AllColumns: postgres.ColumnList{ActorIDColumn, FirstNameColumn, LastNameColumn, FilmInfoColumn},
MutableColumns: postgres.ColumnList{ActorIDColumn, FirstNameColumn, LastNameColumn, FilmInfoColumn},
AllColumns: allColumns,
MutableColumns: mutableColumns,
}
}
`
@ -422,7 +448,7 @@ import (
var AllTypes = newAllTypesTable()
type AllTypesTable struct {
type allTypesTable struct {
postgres.Table
//Columns
@ -492,16 +518,27 @@ type AllTypesTable struct {
MutableColumns postgres.ColumnList
}
type AllTypesTable struct {
allTypesTable
EXCLUDED allTypesTable
}
// creates new AllTypesTable with assigned alias
func (a *AllTypesTable) AS(alias string) *AllTypesTable {
aliasTable := newAllTypesTable()
aliasTable.Table.AS(alias)
return aliasTable
}
func newAllTypesTable() *AllTypesTable {
return &AllTypesTable{
allTypesTable: newAllTypesTableImpl("test_sample", "all_types"),
EXCLUDED: newAllTypesTableImpl("", "excluded"),
}
}
func newAllTypesTableImpl(schemaName, tableName string) allTypesTable {
var (
SmallIntPtrColumn = postgres.IntegerColumn("small_int_ptr")
SmallIntColumn = postgres.IntegerColumn("small_int")
@ -564,10 +601,12 @@ func newAllTypesTable() *AllTypesTable {
JsonbArrayColumn = postgres.StringColumn("jsonb_array")
TextMultiDimArrayPtrColumn = postgres.StringColumn("text_multi_dim_array_ptr")
TextMultiDimArrayColumn = postgres.StringColumn("text_multi_dim_array")
allColumns = postgres.ColumnList{SmallIntPtrColumn, SmallIntColumn, IntegerPtrColumn, IntegerColumn, BigIntPtrColumn, BigIntColumn, DecimalPtrColumn, DecimalColumn, NumericPtrColumn, NumericColumn, RealPtrColumn, RealColumn, DoublePrecisionPtrColumn, DoublePrecisionColumn, SmallserialColumn, SerialColumn, BigserialColumn, VarCharPtrColumn, VarCharColumn, CharPtrColumn, CharColumn, TextPtrColumn, TextColumn, ByteaPtrColumn, ByteaColumn, TimestampzPtrColumn, TimestampzColumn, TimestampPtrColumn, TimestampColumn, DatePtrColumn, DateColumn, TimezPtrColumn, TimezColumn, TimePtrColumn, TimeColumn, IntervalPtrColumn, IntervalColumn, BooleanPtrColumn, BooleanColumn, PointPtrColumn, BitPtrColumn, BitColumn, BitVaryingPtrColumn, BitVaryingColumn, TsvectorPtrColumn, TsvectorColumn, UUIDPtrColumn, UUIDColumn, XMLPtrColumn, XMLColumn, JSONPtrColumn, JSONColumn, JsonbPtrColumn, JsonbColumn, IntegerArrayPtrColumn, IntegerArrayColumn, TextArrayPtrColumn, TextArrayColumn, JsonbArrayColumn, TextMultiDimArrayPtrColumn, TextMultiDimArrayColumn}
mutableColumns = postgres.ColumnList{SmallIntPtrColumn, SmallIntColumn, IntegerPtrColumn, IntegerColumn, BigIntPtrColumn, BigIntColumn, DecimalPtrColumn, DecimalColumn, NumericPtrColumn, NumericColumn, RealPtrColumn, RealColumn, DoublePrecisionPtrColumn, DoublePrecisionColumn, SmallserialColumn, SerialColumn, BigserialColumn, VarCharPtrColumn, VarCharColumn, CharPtrColumn, CharColumn, TextPtrColumn, TextColumn, ByteaPtrColumn, ByteaColumn, TimestampzPtrColumn, TimestampzColumn, TimestampPtrColumn, TimestampColumn, DatePtrColumn, DateColumn, TimezPtrColumn, TimezColumn, TimePtrColumn, TimeColumn, IntervalPtrColumn, IntervalColumn, BooleanPtrColumn, BooleanColumn, PointPtrColumn, BitPtrColumn, BitColumn, BitVaryingPtrColumn, BitVaryingColumn, TsvectorPtrColumn, TsvectorColumn, UUIDPtrColumn, UUIDColumn, XMLPtrColumn, XMLColumn, JSONPtrColumn, JSONColumn, JsonbPtrColumn, JsonbColumn, IntegerArrayPtrColumn, IntegerArrayColumn, TextArrayPtrColumn, TextArrayColumn, JsonbArrayColumn, TextMultiDimArrayPtrColumn, TextMultiDimArrayColumn}
)
return &AllTypesTable{
Table: postgres.NewTable("test_sample", "all_types", SmallIntPtrColumn, SmallIntColumn, IntegerPtrColumn, IntegerColumn, BigIntPtrColumn, BigIntColumn, DecimalPtrColumn, DecimalColumn, NumericPtrColumn, NumericColumn, RealPtrColumn, RealColumn, DoublePrecisionPtrColumn, DoublePrecisionColumn, SmallserialColumn, SerialColumn, BigserialColumn, VarCharPtrColumn, VarCharColumn, CharPtrColumn, CharColumn, TextPtrColumn, TextColumn, ByteaPtrColumn, ByteaColumn, TimestampzPtrColumn, TimestampzColumn, TimestampPtrColumn, TimestampColumn, DatePtrColumn, DateColumn, TimezPtrColumn, TimezColumn, TimePtrColumn, TimeColumn, IntervalPtrColumn, IntervalColumn, BooleanPtrColumn, BooleanColumn, PointPtrColumn, BitPtrColumn, BitColumn, BitVaryingPtrColumn, BitVaryingColumn, TsvectorPtrColumn, TsvectorColumn, UUIDPtrColumn, UUIDColumn, XMLPtrColumn, XMLColumn, JSONPtrColumn, JSONColumn, JsonbPtrColumn, JsonbColumn, IntegerArrayPtrColumn, IntegerArrayColumn, TextArrayPtrColumn, TextArrayColumn, JsonbArrayColumn, TextMultiDimArrayPtrColumn, TextMultiDimArrayColumn),
return allTypesTable{
Table: postgres.NewTable(schemaName, tableName, allColumns...),
//Columns
SmallIntPtr: SmallIntPtrColumn,
@ -632,8 +671,8 @@ func newAllTypesTable() *AllTypesTable {
TextMultiDimArrayPtr: TextMultiDimArrayPtrColumn,
TextMultiDimArray: TextMultiDimArrayColumn,
AllColumns: postgres.ColumnList{SmallIntPtrColumn, SmallIntColumn, IntegerPtrColumn, IntegerColumn, BigIntPtrColumn, BigIntColumn, DecimalPtrColumn, DecimalColumn, NumericPtrColumn, NumericColumn, RealPtrColumn, RealColumn, DoublePrecisionPtrColumn, DoublePrecisionColumn, SmallserialColumn, SerialColumn, BigserialColumn, VarCharPtrColumn, VarCharColumn, CharPtrColumn, CharColumn, TextPtrColumn, TextColumn, ByteaPtrColumn, ByteaColumn, TimestampzPtrColumn, TimestampzColumn, TimestampPtrColumn, TimestampColumn, DatePtrColumn, DateColumn, TimezPtrColumn, TimezColumn, TimePtrColumn, TimeColumn, IntervalPtrColumn, IntervalColumn, BooleanPtrColumn, BooleanColumn, PointPtrColumn, BitPtrColumn, BitColumn, BitVaryingPtrColumn, BitVaryingColumn, TsvectorPtrColumn, TsvectorColumn, UUIDPtrColumn, UUIDColumn, XMLPtrColumn, XMLColumn, JSONPtrColumn, JSONColumn, JsonbPtrColumn, JsonbColumn, IntegerArrayPtrColumn, IntegerArrayColumn, TextArrayPtrColumn, TextArrayColumn, JsonbArrayColumn, TextMultiDimArrayPtrColumn, TextMultiDimArrayColumn},
MutableColumns: postgres.ColumnList{SmallIntPtrColumn, SmallIntColumn, IntegerPtrColumn, IntegerColumn, BigIntPtrColumn, BigIntColumn, DecimalPtrColumn, DecimalColumn, NumericPtrColumn, NumericColumn, RealPtrColumn, RealColumn, DoublePrecisionPtrColumn, DoublePrecisionColumn, SmallserialColumn, SerialColumn, BigserialColumn, VarCharPtrColumn, VarCharColumn, CharPtrColumn, CharColumn, TextPtrColumn, TextColumn, ByteaPtrColumn, ByteaColumn, TimestampzPtrColumn, TimestampzColumn, TimestampPtrColumn, TimestampColumn, DatePtrColumn, DateColumn, TimezPtrColumn, TimezColumn, TimePtrColumn, TimeColumn, IntervalPtrColumn, IntervalColumn, BooleanPtrColumn, BooleanColumn, PointPtrColumn, BitPtrColumn, BitColumn, BitVaryingPtrColumn, BitVaryingColumn, TsvectorPtrColumn, TsvectorColumn, UUIDPtrColumn, UUIDColumn, XMLPtrColumn, XMLColumn, JSONPtrColumn, JSONColumn, JsonbPtrColumn, JsonbColumn, IntegerArrayPtrColumn, IntegerArrayColumn, TextArrayPtrColumn, TextArrayColumn, JsonbArrayColumn, TextMultiDimArrayPtrColumn, TextMultiDimArrayColumn},
AllColumns: allColumns,
MutableColumns: mutableColumns,
}
}
`

View file

@ -2,11 +2,13 @@ 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"
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table"
"github.com/stretchr/testify/assert"
"math/rand"
"testing"
"time"
)
@ -15,10 +17,10 @@ func TestInsertValues(t *testing.T) {
cleanUpLinkTable(t)
var expectedSQL = `
INSERT INTO test_sample.link (id, url, name, description) VALUES
(100, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT),
(101, 'http://www.google.com', 'Google', DEFAULT),
(102, 'http://www.yahoo.com', 'Yahoo', NULL)
INSERT INTO test_sample.link (id, url, name, description)
VALUES (100, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT),
(101, 'http://www.google.com', 'Google', DEFAULT),
(102, 'http://www.yahoo.com', 'Yahoo', NULL)
RETURNING link.id AS "link.id",
link.url AS "link.url",
link.name AS "link.name",
@ -77,8 +79,8 @@ func TestInsertEmptyColumnList(t *testing.T) {
cleanUpLinkTable(t)
expectedSQL := `
INSERT INTO test_sample.link VALUES
(100, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT);
INSERT INTO test_sample.link
VALUES (100, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT);
`
stmt := Link.INSERT().
@ -90,11 +92,128 @@ INSERT INTO test_sample.link VALUES
AssertExec(t, stmt, 1)
}
func TestInsertOnConflict(t *testing.T) {
t.Run("do nothing", func(t *testing.T) {
employee := model.Employee{EmployeeID: rand.Int31()}
stmt := Employee.INSERT(Employee.AllColumns).
MODEL(employee).
MODEL(employee).
ON_CONFLICT(Employee.EmployeeID).DO_NOTHING()
testutils.AssertStatementSql(t, stmt, `
INSERT INTO test_sample.employee (employee_id, first_name, last_name, employment_date, manager_id)
VALUES ($1, $2, $3, $4, $5),
($6, $7, $8, $9, $10)
ON CONFLICT (employee_id) DO NOTHING;
`)
AssertExec(t, stmt, 1)
})
t.Run("on constraint do nothing", func(t *testing.T) {
employee := model.Employee{EmployeeID: rand.Int31()}
stmt := Employee.INSERT(Employee.AllColumns).
MODEL(employee).
MODEL(employee).
ON_CONFLICT().ON_CONSTRAINT("employee_pkey").DO_NOTHING()
testutils.AssertStatementSql(t, stmt, `
INSERT INTO test_sample.employee (employee_id, first_name, last_name, employment_date, manager_id)
VALUES ($1, $2, $3, $4, $5),
($6, $7, $8, $9, $10)
ON CONFLICT ON CONSTRAINT employee_pkey DO NOTHING;
`)
AssertExec(t, stmt, 1)
})
t.Run("do update", func(t *testing.T) {
cleanUpLinkTable(t)
stmt := Link.INSERT(Link.ID, Link.URL, Link.Name, Link.Description).
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"),
).
RETURNING(Link.AllColumns)
testutils.AssertStatementSql(t, stmt, `
INSERT INTO test_sample.link (id, url, name, description)
VALUES ($1, $2, $3, DEFAULT),
($4, $5, $6, DEFAULT)
ON CONFLICT (id) DO UPDATE
SET id = excluded.id,
url = $7
RETURNING link.id AS "link.id",
link.url AS "link.url",
link.name AS "link.name",
link.description AS "link.description";
`)
AssertExec(t, stmt, 2)
})
t.Run("on constraint do update", func(t *testing.T) {
cleanUpLinkTable(t)
stmt := Link.INSERT(Link.ID, Link.URL, Link.Name, Link.Description).
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"),
).
RETURNING(Link.AllColumns)
testutils.AssertStatementSql(t, stmt, `
INSERT INTO test_sample.link (id, url, name, description)
VALUES ($1, $2, $3, DEFAULT),
($4, $5, $6, DEFAULT)
ON CONFLICT ON CONSTRAINT link_pkey DO UPDATE
SET id = excluded.id,
url = $7
RETURNING link.id AS "link.id",
link.url AS "link.url",
link.name AS "link.name",
link.description AS "link.description";
`)
AssertExec(t, stmt, 2)
})
t.Run("do update complex", func(t *testing.T) {
cleanUpLinkTable(t)
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()),
)
testutils.AssertDebugStatementSql(t, stmt, `
INSERT INTO test_sample.link (id, url, name, description)
VALUES (100, 'http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT)
ON CONFLICT (id) WHERE (id * 2) > 10 DO UPDATE
SET id = (
SELECT MAX(link.id) + 1
FROM test_sample.link
),
(name, description) = ROW(excluded.name, 'new description')
WHERE link.description IS NOT NULL;
`)
AssertExec(t, stmt, 1)
})
}
func TestInsertModelObject(t *testing.T) {
cleanUpLinkTable(t)
var expectedSQL = `
INSERT INTO test_sample.link (url, name) VALUES
('http://www.duckduckgo.com', 'Duck Duck go');
INSERT INTO test_sample.link (url, name)
VALUES ('http://www.duckduckgo.com', 'Duck Duck go');
`
linkData := model.Link{
@ -114,8 +233,8 @@ INSERT INTO test_sample.link (url, name) VALUES
func TestInsertModelObjectEmptyColumnList(t *testing.T) {
cleanUpLinkTable(t)
var expectedSQL = `
INSERT INTO test_sample.link VALUES
(1000, 'http://www.duckduckgo.com', 'Duck Duck go', NULL);
INSERT INTO test_sample.link
VALUES (1000, 'http://www.duckduckgo.com', 'Duck Duck go', NULL);
`
linkData := model.Link{
@ -135,10 +254,10 @@ INSERT INTO test_sample.link VALUES
func TestInsertModelsObject(t *testing.T) {
expectedSQL := `
INSERT INTO test_sample.link (url, name) VALUES
('http://www.postgresqltutorial.com', 'PostgreSQL Tutorial'),
('http://www.google.com', 'Google'),
('http://www.yahoo.com', 'Yahoo');
INSERT INTO test_sample.link (url, name)
VALUES ('http://www.postgresqltutorial.com', 'PostgreSQL Tutorial'),
('http://www.google.com', 'Google'),
('http://www.yahoo.com', 'Yahoo');
`
tutorial := model.Link{
@ -170,11 +289,11 @@ INSERT INTO test_sample.link (url, name) VALUES
func TestInsertUsingMutableColumns(t *testing.T) {
var expectedSQL = `
INSERT INTO test_sample.link (url, name, description) VALUES
('http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT),
('http://www.google.com', 'Google', NULL),
('http://www.google.com', 'Google', NULL),
('http://www.yahoo.com', 'Yahoo', NULL);
INSERT INTO test_sample.link (url, name, description)
VALUES ('http://www.postgresqltutorial.com', 'PostgreSQL Tutorial', DEFAULT),
('http://www.google.com', 'Google', NULL),
('http://www.google.com', 'Google', NULL),
('http://www.yahoo.com', 'Yahoo', NULL);
`
google := model.Link{

View file

@ -5,16 +5,19 @@ import (
"github.com/go-jet/jet/tests/dbconfig"
_ "github.com/lib/pq"
"github.com/pkg/profile"
"math/rand"
"os"
"os/exec"
"strings"
"testing"
"time"
)
var db *sql.DB
var testRoot string
func TestMain(m *testing.M) {
rand.Seed(time.Now().Unix())
defer profile.Start().Stop()
setTestRoot()

View file

@ -7,6 +7,7 @@ import (
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/test_sample/table"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
)
@ -221,6 +222,10 @@ FROM test_sample.person;
func TestSelecSelfJoin1(t *testing.T) {
// clean up
_, err := Employee.DELETE().WHERE(Employee.EmployeeID.GT(Int(100))).Exec(db)
require.NoError(t, err)
var expectedSQL = `
SELECT employee.employee_id AS "employee.employee_id",
employee.first_name AS "employee.first_name",
@ -256,7 +261,7 @@ ORDER BY employee.employee_id;
Manager *Manager
}
err := query.Query(db, &dest)
err = query.Query(db, &dest)
assert.NoError(t, err)
assert.Equal(t, len(dest), 8)

View file

@ -6,13 +6,14 @@ import (
"github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/model"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
)
func AssertExec(t *testing.T, stmt jet.Statement, rowsAffected int64) {
res, err := stmt.Exec(db)
assert.NoError(t, err)
require.NoError(t, err)
rows, err := res.RowsAffected()
assert.NoError(t, err)
assert.Equal(t, rows, rowsAffected)