Merge pull request #197 from emarj/custom-types-indexes-pk
Allow custom types as indexes when joining tables
This commit is contained in:
commit
b80fb5df94
4 changed files with 225 additions and 15 deletions
1
go.mod
1
go.mod
|
|
@ -18,4 +18,5 @@ require (
|
|||
github.com/shopspring/decimal v1.3.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/volatiletech/null/v8 v8.1.2
|
||||
gopkg.in/guregu/null.v4 v4.0.0
|
||||
)
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -199,6 +199,8 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
|||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg=
|
||||
gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
|
|
|
|||
|
|
@ -187,17 +187,6 @@ func (s *ScanContext) getGroupKeyInfo(
|
|||
field := structType.Field(i)
|
||||
fieldType := indirectType(field.Type)
|
||||
|
||||
if !isSimpleModelType(fieldType) {
|
||||
if fieldType.Kind() != reflect.Struct {
|
||||
continue
|
||||
}
|
||||
|
||||
subType := s.getGroupKeyInfo(fieldType, &field, typeVisited)
|
||||
|
||||
if len(subType.indexes) != 0 || len(subType.subTypes) != 0 {
|
||||
ret.subTypes = append(ret.subTypes, subType)
|
||||
}
|
||||
} else {
|
||||
if isPrimaryKey(field, primaryKeyOverwrites) {
|
||||
newTypeName, fieldName := getTypeAndFieldName(typeName, field)
|
||||
|
||||
|
|
@ -208,6 +197,13 @@ func (s *ScanContext) getGroupKeyInfo(
|
|||
}
|
||||
|
||||
ret.indexes = append(ret.indexes, index)
|
||||
|
||||
} else if fieldType.Kind() == reflect.Struct {
|
||||
|
||||
subType := s.getGroupKeyInfo(fieldType, &field, typeVisited)
|
||||
|
||||
if len(subType.indexes) != 0 || len(subType.subTypes) != 0 {
|
||||
ret.subTypes = append(ret.subTypes, subType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,13 @@ package postgres
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/go-jet/jet/v2/qrm"
|
||||
"database/sql"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-jet/jet/v2/qrm"
|
||||
"gopkg.in/guregu/null.v4"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/go-jet/jet/v2/internal/testutils"
|
||||
|
|
@ -658,6 +661,214 @@ ORDER BY city.city_id, address.address_id, customer.customer_id;
|
|||
`)
|
||||
}
|
||||
|
||||
// Test join with custom primary keys (sql.NullInt64)
|
||||
func TestExecutionCustomPKTypes1(t *testing.T) {
|
||||
|
||||
var dest []struct {
|
||||
CityID sql.NullInt64 `sql:"primary_key" alias:"city.city_id"`
|
||||
CityName string `alias:"city.city"`
|
||||
|
||||
Customers []struct {
|
||||
CustomerID sql.NullInt64 `sql:"primary_key" alias:"customer_id"`
|
||||
LastName *string `alias:"last_name"`
|
||||
|
||||
Address struct {
|
||||
AddressID sql.NullInt64 `sql:"primary_key" alias:"AddressId"`
|
||||
AddressLine string `alias:"address.address"`
|
||||
} `alias:"address.*"`
|
||||
} `alias:"customer"`
|
||||
}
|
||||
|
||||
stmt := City.
|
||||
INNER_JOIN(Address, Address.CityID.EQ(City.CityID)).
|
||||
INNER_JOIN(Customer, Customer.AddressID.EQ(Address.AddressID)).
|
||||
SELECT(
|
||||
City.CityID,
|
||||
City.City,
|
||||
Customer.CustomerID,
|
||||
Customer.LastName,
|
||||
Address.AddressID,
|
||||
Address.Address,
|
||||
).
|
||||
WHERE(City.City.EQ(String("London")).OR(City.City.EQ(String("York")))).
|
||||
ORDER_BY(City.CityID, Address.AddressID, Customer.CustomerID)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
SELECT city.city_id AS "city.city_id",
|
||||
city.city AS "city.city",
|
||||
customer.customer_id AS "customer.customer_id",
|
||||
customer.last_name AS "customer.last_name",
|
||||
address.address_id AS "address.address_id",
|
||||
address.address AS "address.address"
|
||||
FROM dvds.city
|
||||
INNER JOIN dvds.address ON (address.city_id = city.city_id)
|
||||
INNER JOIN dvds.customer ON (customer.address_id = address.address_id)
|
||||
WHERE (city.city = 'London'::text) OR (city.city = 'York'::text)
|
||||
ORDER BY city.city_id, address.address_id, customer.customer_id;
|
||||
`, "London", "York")
|
||||
|
||||
err := stmt.Query(db, &dest)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(dest), 2)
|
||||
testutils.AssertJSON(t, dest, `
|
||||
[
|
||||
{
|
||||
"CityID": {
|
||||
"Int64": 312,
|
||||
"Valid": true
|
||||
},
|
||||
"CityName": "London",
|
||||
"Customers": [
|
||||
{
|
||||
"CustomerID": {
|
||||
"Int64": 252,
|
||||
"Valid": true
|
||||
},
|
||||
"LastName": "Hoffman",
|
||||
"Address": {
|
||||
"AddressID": {
|
||||
"Int64": 256,
|
||||
"Valid": true
|
||||
},
|
||||
"AddressLine": "1497 Yuzhou Drive"
|
||||
}
|
||||
},
|
||||
{
|
||||
"CustomerID": {
|
||||
"Int64": 512,
|
||||
"Valid": true
|
||||
},
|
||||
"LastName": "Vines",
|
||||
"Address": {
|
||||
"AddressID": {
|
||||
"Int64": 517,
|
||||
"Valid": true
|
||||
},
|
||||
"AddressLine": "548 Uruapan Street"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"CityID": {
|
||||
"Int64": 589,
|
||||
"Valid": true
|
||||
},
|
||||
"CityName": "York",
|
||||
"Customers": [
|
||||
{
|
||||
"CustomerID": {
|
||||
"Int64": 497,
|
||||
"Valid": true
|
||||
},
|
||||
"LastName": "Sledge",
|
||||
"Address": {
|
||||
"AddressID": {
|
||||
"Int64": 502,
|
||||
"Valid": true
|
||||
},
|
||||
"AddressLine": "1515 Korla Way"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
`)
|
||||
}
|
||||
|
||||
// Test join with custom primary keys (null.Int)
|
||||
func TestExecutionCustomPKTypes2(t *testing.T) {
|
||||
|
||||
var dest []struct {
|
||||
CityID null.Int `sql:"primary_key" alias:"city.city_id"`
|
||||
CityName string `alias:"city.city"`
|
||||
|
||||
Customers []struct {
|
||||
CustomerID null.Int `sql:"primary_key" alias:"customer_id"`
|
||||
LastName *string `alias:"last_name"`
|
||||
|
||||
Address struct {
|
||||
AddressID null.Int `sql:"primary_key" alias:"AddressId"`
|
||||
AddressLine string `alias:"address.address"`
|
||||
} `alias:"address.*"`
|
||||
} `alias:"customer"`
|
||||
}
|
||||
|
||||
stmt := City.
|
||||
INNER_JOIN(Address, Address.CityID.EQ(City.CityID)).
|
||||
INNER_JOIN(Customer, Customer.AddressID.EQ(Address.AddressID)).
|
||||
SELECT(
|
||||
City.CityID,
|
||||
City.City,
|
||||
Customer.CustomerID,
|
||||
Customer.LastName,
|
||||
Address.AddressID,
|
||||
Address.Address,
|
||||
).
|
||||
WHERE(City.City.EQ(String("London")).OR(City.City.EQ(String("York")))).
|
||||
ORDER_BY(City.CityID, Address.AddressID, Customer.CustomerID)
|
||||
|
||||
testutils.AssertDebugStatementSql(t, stmt, `
|
||||
SELECT city.city_id AS "city.city_id",
|
||||
city.city AS "city.city",
|
||||
customer.customer_id AS "customer.customer_id",
|
||||
customer.last_name AS "customer.last_name",
|
||||
address.address_id AS "address.address_id",
|
||||
address.address AS "address.address"
|
||||
FROM dvds.city
|
||||
INNER JOIN dvds.address ON (address.city_id = city.city_id)
|
||||
INNER JOIN dvds.customer ON (customer.address_id = address.address_id)
|
||||
WHERE (city.city = 'London'::text) OR (city.city = 'York'::text)
|
||||
ORDER BY city.city_id, address.address_id, customer.customer_id;
|
||||
`, "London", "York")
|
||||
|
||||
err := stmt.Query(db, &dest)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(dest), 2)
|
||||
testutils.AssertJSON(t, dest, `
|
||||
[
|
||||
{
|
||||
"CityID": 312,
|
||||
"CityName": "London",
|
||||
"Customers": [
|
||||
{
|
||||
"CustomerID": 252,
|
||||
"LastName": "Hoffman",
|
||||
"Address": {
|
||||
"AddressID": 256,
|
||||
"AddressLine": "1497 Yuzhou Drive"
|
||||
}
|
||||
},
|
||||
{
|
||||
"CustomerID": 512,
|
||||
"LastName": "Vines",
|
||||
"Address": {
|
||||
"AddressID": 517,
|
||||
"AddressLine": "548 Uruapan Street"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"CityID": 589,
|
||||
"CityName": "York",
|
||||
"Customers": [
|
||||
{
|
||||
"CustomerID": 497,
|
||||
"LastName": "Sledge",
|
||||
"Address": {
|
||||
"AddressID": 502,
|
||||
"AddressLine": "1515 Korla Way"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
`)
|
||||
}
|
||||
|
||||
func TestJoinQuerySliceWithPtrs(t *testing.T) {
|
||||
type FilmsPerLanguage struct {
|
||||
Language model.Language
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue