jet/tests/postgres/sample_test.go

563 lines
15 KiB
Go
Raw Normal View History

2019-07-30 11:45:10 +02:00
package postgres
2019-04-04 13:07:21 +02:00
import (
"github.com/go-jet/jet/v2/qrm"
2024-10-06 09:04:10 -04:00
"github.com/go-jet/jet/v2/internal/utils/ptr"
2022-05-05 13:01:42 +02:00
"github.com/google/uuid"
"testing"
"github.com/stretchr/testify/require"
2020-06-27 18:48:19 +02:00
"github.com/go-jet/jet/v2/internal/testutils"
. "github.com/go-jet/jet/v2/postgres"
"github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/test_sample/model"
. "github.com/go-jet/jet/v2/tests/.gentestdata/jetdb/test_sample/table"
"github.com/shopspring/decimal"
2019-04-04 13:07:21 +02:00
)
func TestExactDecimals(t *testing.T) {
type floats struct {
model.Floats
Numeric decimal.Decimal
NumericPtr decimal.Decimal
Decimal decimal.Decimal
DecimalPtr decimal.Decimal
}
t.Run("should query decimal", func(t *testing.T) {
query := SELECT(
Floats.AllColumns,
).FROM(
Floats,
).WHERE(Floats.Decimal.EQ(Decimal("1.11111111111111111111")))
var result floats
err := query.Query(db, &result)
require.NoError(t, err)
require.Equal(t, "1.11111111111111111111", result.Decimal.String())
require.Equal(t, "0", result.DecimalPtr.String()) // NULL
require.Equal(t, "2.22222222222222222222", result.Numeric.String())
require.Equal(t, "0", result.NumericPtr.String()) // NULL
require.Equal(t, 1.1111111111111112, result.Floats.Decimal) // precision loss
require.Equal(t, (*float64)(nil), result.Floats.DecimalPtr)
require.Equal(t, 2.2222222222222223, result.Floats.Numeric) // precision loss
require.Equal(t, (*float64)(nil), result.Floats.NumericPtr)
// floating point
require.Equal(t, float32(3.3333333), result.Floats.Real) // precision loss
require.Equal(t, (*float32)(nil), result.Floats.RealPtr)
require.Equal(t, 4.444444444444445, result.Floats.Double) // precision loss
require.Equal(t, (*float64)(nil), result.Floats.DoublePtr)
})
t.Run("should insert decimal", func(t *testing.T) {
insertQuery := Floats.INSERT(
2022-05-05 13:01:42 +02:00
Floats.MutableColumns,
).MODEL(
floats{
Floats: model.Floats{
// overwritten by wrapped(floats) scope
Numeric: 0.1,
2024-10-06 09:04:10 -04:00
NumericPtr: ptr.Of(0.1),
Decimal: 0.1,
2024-10-06 09:04:10 -04:00
DecimalPtr: ptr.Of(0.1),
// not overwritten
Real: 0.4,
2024-10-06 09:04:10 -04:00
RealPtr: ptr.Of(float32(0.44)),
Double: 0.3,
2024-10-06 09:04:10 -04:00
DoublePtr: ptr.Of(0.33),
},
Numeric: decimal.RequireFromString("0.1234567890123456789"),
NumericPtr: decimal.RequireFromString("1.1111111111111111111"),
Decimal: decimal.RequireFromString("2.2222222222222222222"),
DecimalPtr: decimal.RequireFromString("3.3333333333333333333"),
},
).RETURNING(
2022-05-05 13:01:42 +02:00
Floats.MutableColumns,
)
testutils.AssertDebugStatementSql(t, insertQuery, `
INSERT INTO test_sample.floats (decimal_ptr, decimal, numeric_ptr, numeric, real_ptr, real, double_ptr, double)
VALUES ('3.3333333333333333333', '2.2222222222222222222', '1.1111111111111111111', '0.1234567890123456789', 0.4399999976158142, 0.4000000059604645, 0.33, 0.3)
RETURNING floats.decimal_ptr AS "floats.decimal_ptr",
floats.decimal AS "floats.decimal",
floats.numeric_ptr AS "floats.numeric_ptr",
floats.numeric AS "floats.numeric",
floats.real_ptr AS "floats.real_ptr",
floats.real AS "floats.real",
floats.double_ptr AS "floats.double_ptr",
floats.double AS "floats.double";
`)
var result floats
err := insertQuery.Query(db, &result)
require.NoError(t, err)
// exact decimal
require.Equal(t, "0.1234567890123456789", result.Numeric.String())
require.Equal(t, "1.1111111111111111111", result.NumericPtr.String())
require.Equal(t, "2.2222222222222222222", result.Decimal.String())
require.Equal(t, "3.3333333333333333333", result.DecimalPtr.String())
// precision loss
require.Equal(t, 0.12345678901234568, result.Floats.Numeric)
require.Equal(t, 1.1111111111111112, *result.Floats.NumericPtr)
require.Equal(t, 2.2222222222222223, result.Floats.Decimal)
require.Equal(t, 3.3333333333333335, *result.Floats.DecimalPtr)
// floating points numbers
require.Equal(t, float32(0.4), result.Floats.Real)
require.Equal(t, float32(0.44), *result.Floats.RealPtr)
require.Equal(t, 0.3, result.Floats.Double)
require.Equal(t, 0.33, *result.Floats.DoublePtr)
})
}
func TestUUIDComplex(t *testing.T) {
2024-02-01 15:20:49 +01:00
query := SELECT(
Person.AllColumns,
PersonPhone.AllColumns,
).FROM(
Person.INNER_JOIN(PersonPhone, PersonPhone.PersonID.EQ(Person.PersonID)),
).ORDER_BY(
Person.PersonID.ASC(),
PersonPhone.PhoneID.ASC(),
)
t.Run("slice of structs", func(t *testing.T) {
var dest []struct {
model.Person
Phones []struct {
model.PersonPhone
}
}
err := query.Query(db, &dest)
require.NoError(t, err)
require.Equal(t, len(dest), 2)
testutils.AssertJSON(t, dest, `
[
{
"PersonID": "b68dbff4-a87d-11e9-a7f2-98ded00c39c6",
"FirstName": "Sad",
"LastName": "John",
"Mood": "sad",
"Phones": [
{
"PhoneID": "02b61cc4-d500-4847-bd36-111eccbc7a51",
"PhoneNumber": "212-555-1211",
"PersonID": "b68dbff4-a87d-11e9-a7f2-98ded00c39c6"
}
]
},
{
"PersonID": "b68dbff6-a87d-11e9-a7f2-98ded00c39c8",
"FirstName": "Ok",
"LastName": "John",
"Mood": "ok",
"Phones": [
{
"PhoneID": "02b61cc4-d500-4847-bd36-111eccbc7a52",
"PhoneNumber": "212-555-1212",
"PersonID": "b68dbff6-a87d-11e9-a7f2-98ded00c39c8"
},
{
"PhoneID": "02b61cc4-d500-4847-bd36-111eccbc7a53",
"PhoneNumber": "212-555-1213",
"PersonID": "b68dbff6-a87d-11e9-a7f2-98ded00c39c8"
}
]
}
]
`)
})
t.Run("single struct", func(t *testing.T) {
2022-05-05 13:01:42 +02:00
uuid, err := uuid.Parse("b68dbff6-a87d-11e9-a7f2-98ded00c39c8")
require.NoError(t, err)
singleQuery := query.WHERE(Person.PersonID.EQ(UUID(uuid)))
var dest struct {
model.Person
Phones []struct {
model.PersonPhone
}
}
2022-05-05 13:01:42 +02:00
err = singleQuery.Query(db, &dest)
require.NoError(t, err)
testutils.AssertJSON(t, dest, `
{
"PersonID": "b68dbff6-a87d-11e9-a7f2-98ded00c39c8",
"FirstName": "Ok",
"LastName": "John",
"Mood": "ok",
"Phones": [
{
"PhoneID": "02b61cc4-d500-4847-bd36-111eccbc7a52",
"PhoneNumber": "212-555-1212",
"PersonID": "b68dbff6-a87d-11e9-a7f2-98ded00c39c8"
},
{
"PhoneID": "02b61cc4-d500-4847-bd36-111eccbc7a53",
"PhoneNumber": "212-555-1213",
"PersonID": "b68dbff6-a87d-11e9-a7f2-98ded00c39c8"
}
]
}
`)
requireLogged(t, query)
})
t.Run("slice of structs left join", func(t *testing.T) {
leftQuery := Person.LEFT_JOIN(PersonPhone, PersonPhone.PersonID.EQ(Person.PersonID)).
SELECT(Person.AllColumns, PersonPhone.AllColumns).
ORDER_BY(Person.PersonID.ASC(), PersonPhone.PhoneID.ASC())
var dest []struct {
model.Person
Phones []struct {
model.PersonPhone
}
}
err := leftQuery.Query(db, &dest)
require.NoError(t, err)
testutils.AssertJSON(t, dest, `
[
{
"PersonID": "b68dbff4-a87d-11e9-a7f2-98ded00c39c6",
"FirstName": "Sad",
"LastName": "John",
"Mood": "sad",
"Phones": [
{
"PhoneID": "02b61cc4-d500-4847-bd36-111eccbc7a51",
"PhoneNumber": "212-555-1211",
"PersonID": "b68dbff4-a87d-11e9-a7f2-98ded00c39c6"
}
]
},
{
"PersonID": "b68dbff5-a87d-11e9-a7f2-98ded00c39c7",
"FirstName": "Ok",
"LastName": "John",
"Mood": "ok",
"Phones": null
},
{
"PersonID": "b68dbff6-a87d-11e9-a7f2-98ded00c39c8",
"FirstName": "Ok",
"LastName": "John",
"Mood": "ok",
"Phones": [
{
"PhoneID": "02b61cc4-d500-4847-bd36-111eccbc7a52",
"PhoneNumber": "212-555-1212",
"PersonID": "b68dbff6-a87d-11e9-a7f2-98ded00c39c8"
},
{
"PhoneID": "02b61cc4-d500-4847-bd36-111eccbc7a53",
"PhoneNumber": "212-555-1213",
"PersonID": "b68dbff6-a87d-11e9-a7f2-98ded00c39c8"
}
]
}
]
`)
requireLogged(t, leftQuery)
})
}
2019-04-04 13:07:21 +02:00
func TestEnumType(t *testing.T) {
2019-06-26 10:30:31 +02:00
query := Person.
SELECT(Person.AllColumns)
2019-04-04 13:07:21 +02:00
2019-07-30 11:18:12 +02:00
testutils.AssertDebugStatementSql(t, query, `
2019-07-17 13:22:14 +02:00
SELECT person.person_id AS "person.person_id",
person.first_name AS "person.first_name",
person.last_name AS "person.last_name",
person."Mood" AS "person.Mood"
FROM test_sample.person;
`)
2019-04-04 13:07:21 +02:00
2022-05-05 13:01:42 +02:00
var result []model.Person
2019-04-04 13:07:21 +02:00
2019-07-17 13:22:14 +02:00
err := query.Query(db, &result)
2019-04-04 13:07:21 +02:00
require.NoError(t, err)
testutils.AssertJSON(t, result, `
2019-07-17 13:22:14 +02:00
[
{
"PersonID": "b68dbff4-a87d-11e9-a7f2-98ded00c39c6",
"FirstName": "Sad",
"LastName": "John",
"Mood": "sad"
},
{
"PersonID": "b68dbff5-a87d-11e9-a7f2-98ded00c39c7",
"FirstName": "Ok",
"LastName": "John",
"Mood": "ok"
},
{
"PersonID": "b68dbff6-a87d-11e9-a7f2-98ded00c39c8",
"FirstName": "Ok",
"LastName": "John",
"Mood": "ok"
2019-04-04 13:07:21 +02:00
}
2019-07-17 13:22:14 +02:00
]
`)
2019-04-04 13:07:21 +02:00
}
2019-06-26 10:30:31 +02:00
2022-05-05 13:01:42 +02:00
func TestSelectSelfJoin1(t *testing.T) {
2019-06-26 10:30:31 +02:00
// clean up
_, err := Employee.DELETE().WHERE(Employee.EmployeeID.GT(Int(100))).Exec(db)
require.NoError(t, err)
2019-07-18 17:43:11 +02:00
var expectedSQL = `
2019-06-26 10:30:31 +02:00
SELECT employee.employee_id AS "employee.employee_id",
employee.first_name AS "employee.first_name",
employee.last_name AS "employee.last_name",
employee.employment_date AS "employee.employment_date",
employee.manager_id AS "employee.manager_id",
employee.pto_accrual AS "employee.pto_accrual",
2019-06-26 10:30:31 +02:00
manager.employee_id AS "manager.employee_id",
manager.first_name AS "manager.first_name",
manager.last_name AS "manager.last_name",
manager.employment_date AS "manager.employment_date",
manager.manager_id AS "manager.manager_id",
manager.pto_accrual AS "manager.pto_accrual"
2019-06-26 10:30:31 +02:00
FROM test_sample.employee
LEFT JOIN test_sample.employee AS manager ON (manager.employee_id = employee.manager_id)
ORDER BY employee.employee_id;
`
manager := Employee.AS("manager")
query := Employee.
LEFT_JOIN(manager, manager.EmployeeID.EQ(Employee.ManagerID)).
SELECT(
Employee.AllColumns,
manager.AllColumns,
).
ORDER_BY(Employee.EmployeeID)
2019-07-30 11:18:12 +02:00
testutils.AssertDebugStatementSql(t, query, expectedSQL)
2019-06-26 10:30:31 +02:00
type Manager model.Employee
var dest []struct {
model.Employee
Manager *Manager
}
err = query.Query(db, &dest)
2019-06-26 10:30:31 +02:00
require.NoError(t, err)
require.Equal(t, len(dest), 8)
testutils.AssertDeepEqual(t, dest[0].Employee, model.Employee{
2019-06-26 10:30:31 +02:00
EmployeeID: 1,
FirstName: "Windy",
LastName: "Hays",
2019-07-31 18:43:54 +02:00
EmploymentDate: testutils.TimestampWithTimeZone("1999-01-08 04:05:06.1 +0100 CET", 1),
2019-06-26 10:30:31 +02:00
ManagerID: nil,
PtoAccrual: ptr.Of("22:00:00"),
2019-06-26 10:30:31 +02:00
})
require.True(t, dest[0].Manager == nil)
2019-06-26 10:30:31 +02:00
testutils.AssertDeepEqual(t, dest[7].Employee, model.Employee{
2019-06-26 10:30:31 +02:00
EmployeeID: 8,
FirstName: "Salley",
LastName: "Lester",
2019-07-31 18:43:54 +02:00
EmploymentDate: testutils.TimestampWithTimeZone("1999-01-08 04:05:06 +0100 CET", 1),
2024-10-06 09:04:10 -04:00
ManagerID: ptr.Of(int32(3)),
2019-06-26 10:30:31 +02:00
})
}
func TestWierdNamesTable(t *testing.T) {
2022-05-05 13:01:42 +02:00
stmt := WeirdNamesTable.SELECT(WeirdNamesTable.MutableColumns)
2019-07-30 11:18:12 +02:00
testutils.AssertDebugStatementSql(t, stmt, `
2019-07-13 13:17:28 +02:00
SELECT "WEIRD NAMES TABLE".weird_column_name1 AS "WEIRD NAMES TABLE.weird_column_name1",
"WEIRD NAMES TABLE"."Weird_Column_Name2" AS "WEIRD NAMES TABLE.Weird_Column_Name2",
"WEIRD NAMES TABLE"."wEiRd_cOluMn_nAmE3" AS "WEIRD NAMES TABLE.wEiRd_cOluMn_nAmE3",
"WEIRD NAMES TABLE"."WeIrd_CoLuMN_Name4" AS "WEIRD NAMES TABLE.WeIrd_CoLuMN_Name4",
"WEIRD NAMES TABLE"."WEIRD_COLUMN_NAME5" AS "WEIRD NAMES TABLE.WEIRD_COLUMN_NAME5",
"WEIRD NAMES TABLE"."WeirdColumnName6" AS "WEIRD NAMES TABLE.WeirdColumnName6",
"WEIRD NAMES TABLE"."weirdColumnName7" AS "WEIRD NAMES TABLE.weirdColumnName7",
"WEIRD NAMES TABLE".weirdcolumnname8 AS "WEIRD NAMES TABLE.weirdcolumnname8",
"WEIRD NAMES TABLE"."weird col name9" AS "WEIRD NAMES TABLE.weird col name9",
"WEIRD NAMES TABLE"."wEiRd cOlu nAmE10" AS "WEIRD NAMES TABLE.wEiRd cOlu nAmE10",
"WEIRD NAMES TABLE"."WEIRD COLU NAME11" AS "WEIRD NAMES TABLE.WEIRD COLU NAME11",
"WEIRD NAMES TABLE"."Weird Colu Name12" AS "WEIRD NAMES TABLE.Weird Colu Name12",
"WEIRD NAMES TABLE"."weird-col-name13" AS "WEIRD NAMES TABLE.weird-col-name13",
"WEIRD NAMES TABLE"."wEiRd-cOlu-nAmE14" AS "WEIRD NAMES TABLE.wEiRd-cOlu-nAmE14",
"WEIRD NAMES TABLE"."WEIRD-COLU-NAME15" AS "WEIRD NAMES TABLE.WEIRD-COLU-NAME15",
"WEIRD NAMES TABLE"."Weird-Colu-Name16" AS "WEIRD NAMES TABLE.Weird-Colu-Name16"
FROM test_sample."WEIRD NAMES TABLE";
`)
2022-05-05 13:01:42 +02:00
var dest []model.WeirdNamesTable
err := stmt.Query(db, &dest)
require.NoError(t, err)
require.Equal(t, len(dest), 1)
testutils.AssertDeepEqual(t, dest[0], model.WeirdNamesTable{
WeirdColumnName1: "Doe",
WeirdColumnName2: "Doe",
WeirdColumnName3: "Doe",
WeirdColumnName4: "Doe",
WeirdColumnName5: "Doe",
WeirdColumnName6: "Doe",
WeirdColumnName7: "Doe",
2024-10-06 09:04:10 -04:00
Weirdcolumnname8: ptr.Of("Doe"),
WeirdColName9: "Doe",
WeirdColuName10: "Doe",
WeirdColuName11: "Doe",
WeirdColuName12: "Doe",
WeirdColName13: "Doe",
WeirdColuName14: "Doe",
WeirdColuName15: "Doe",
WeirdColuName16: "Doe",
})
}
func TestReserwedWordEscape(t *testing.T) {
2022-05-05 13:01:42 +02:00
stmt := SELECT(User.MutableColumns).
FROM(User)
//fmt.Println(stmt.DebugSql())
testutils.AssertDebugStatementSql(t, stmt, `
SELECT "User"."column" AS "User.column",
"User"."check" AS "User.check",
"User".ceil AS "User.ceil",
"User".commit AS "User.commit",
"User"."create" AS "User.create",
"User"."default" AS "User.default",
"User"."desc" AS "User.desc",
"User".empty AS "User.empty",
"User".float AS "User.float",
"User".join AS "User.join",
"User".like AS "User.like",
"User".max AS "User.max",
"User".rank AS "User.rank"
FROM test_sample."User";
`)
var dest []model.User
err := stmt.Query(db, &dest)
require.NoError(t, err)
//testutils.PrintJson(dest)
testutils.AssertJSON(t, dest, `
[
{
2022-05-05 13:01:42 +02:00
"ID": 0,
"Column": "Column",
"Check": "CHECK",
"Ceil": "CEIL",
"Commit": "COMMIT",
"Create": "CREATE",
"Default": "DEFAULT",
"Desc": "DESC",
"Empty": "EMPTY",
"Float": "FLOAT",
"Join": "JOIN",
"Like": "LIKE",
"Max": "MAX",
"Rank": "RANK"
}
]
`)
}
2023-01-30 14:53:16 -05:00
func TestMutableColumnsExcludeGeneratedColumn(t *testing.T) {
t.Run("should not have the generated column in mutableColumns", func(t *testing.T) {
require.Equal(t, 2, len(People.MutableColumns))
require.Equal(t, People.PeopleName, People.MutableColumns[0])
require.Equal(t, People.PeopleHeightCm, People.MutableColumns[1])
})
t.Run("should query with all columns", func(t *testing.T) {
query := SELECT(
People.AllColumns,
).FROM(
People,
).WHERE(
People.PeopleID.EQ(Int(3)),
)
var result model.People
err := query.Query(db, &result)
require.NoError(t, err)
require.Equal(t, "Carla", result.PeopleName)
require.Equal(t, 155., *result.PeopleHeightCm)
require.InEpsilon(t, 61.02, *result.PeopleHeightIn, 1e-3)
})
t.Run("should insert without generated columns", func(t *testing.T) {
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
2023-04-06 11:26:09 +02:00
insertQuery := People.INSERT(
People.MutableColumns,
).MODEL(
model.People{
PeopleName: "Dario",
2024-10-06 09:04:10 -04:00
PeopleHeightCm: ptr.Of(120.0),
2023-04-06 11:26:09 +02:00
},
).RETURNING(
People.MutableColumns,
)
2023-01-30 14:53:16 -05:00
2023-04-06 11:26:09 +02:00
testutils.AssertDebugStatementSql(t, insertQuery, `
2023-01-30 14:53:16 -05:00
INSERT INTO test_sample.people (people_name, people_height_cm)
VALUES ('Dario', 120)
RETURNING people.people_name AS "people.people_name",
people.people_height_cm AS "people.people_height_cm";
`)
2023-04-06 11:26:09 +02:00
var result model.People
err := insertQuery.Query(tx, &result)
require.NoError(t, err)
require.Equal(t, "Dario", result.PeopleName)
require.Equal(t, 120., *result.PeopleHeightCm)
query := SELECT(
People.AllColumns,
).FROM(
People,
).ORDER_BY(
People.PeopleID.DESC(),
).LIMIT(1)
result = model.People{}
err = query.Query(tx, &result)
require.NoError(t, err)
require.Equal(t, "Dario", result.PeopleName)
require.Equal(t, 120., *result.PeopleHeightCm)
require.InEpsilon(t, 47.24, *result.PeopleHeightIn, 1e-3)
})
2023-01-30 14:53:16 -05:00
})
}