2019-07-30 11:45:10 +02:00
package postgres
2019-05-20 17:37:55 +02:00
import (
2019-08-13 17:20:35 +02:00
"fmt"
2019-07-29 18:08:53 +02:00
"github.com/go-jet/jet/internal/testutils"
2019-08-03 14:10:47 +02:00
. "github.com/go-jet/jet/postgres"
2019-09-27 11:46:31 +02:00
"github.com/go-jet/jet/qrm"
2019-06-24 10:01:34 +02:00
"github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/model"
. "github.com/go-jet/jet/tests/.gentestdata/jetdb/dvds/table"
2019-05-22 11:28:32 +02:00
"github.com/google/uuid"
2019-05-20 17:37:55 +02:00
"gotest.tools/assert"
"testing"
)
var query = Inventory .
SELECT ( Inventory . AllColumns ) .
LIMIT ( 1 ) .
ORDER_BY ( Inventory . InventoryID )
func TestScanToInvalidDestination ( t * testing . T ) {
t . Run ( "nil dest" , func ( t * testing . T ) {
2019-08-13 13:57:26 +02:00
testutils . AssertQueryPanicErr ( t , query , db , nil , "jet: destination is nil" )
2019-05-20 17:37:55 +02:00
} )
t . Run ( "struct dest" , func ( t * testing . T ) {
2019-08-13 13:57:26 +02:00
testutils . AssertQueryPanicErr ( t , query , db , struct { } { } , "jet: destination has to be a pointer to slice or pointer to struct" )
2019-05-20 17:37:55 +02:00
} )
t . Run ( "slice dest" , func ( t * testing . T ) {
2019-08-13 13:57:26 +02:00
testutils . AssertQueryPanicErr ( t , query , db , [ ] struct { } { } , "jet: destination has to be a pointer to slice or pointer to struct" )
2019-05-20 17:37:55 +02:00
} )
t . Run ( "slice of pointers to pointer dest" , func ( t * testing . T ) {
2019-08-13 13:57:26 +02:00
testutils . AssertQueryPanicErr ( t , query , db , [ ] * * struct { } { } , "jet: destination has to be a pointer to slice or pointer to struct" )
2019-05-20 17:37:55 +02:00
} )
2019-08-13 17:20:35 +02:00
t . Run ( "map dest" , func ( t * testing . T ) {
testutils . AssertQueryPanicErr ( t , query , db , & map [ string ] string { } , "jet: destination has to be a pointer to slice or pointer to struct" )
} )
2019-05-20 17:37:55 +02:00
t . Run ( "map dest" , func ( t * testing . T ) {
2019-08-13 13:57:26 +02:00
testutils . AssertQueryPanicErr ( t , query , db , [ ] map [ string ] string { } , "jet: destination has to be a pointer to slice or pointer to struct" )
2019-05-20 17:37:55 +02:00
} )
2019-08-13 17:20:35 +02:00
t . Run ( "map dest" , func ( t * testing . T ) {
testutils . AssertQueryPanicErr ( t , query , db , & [ ] map [ string ] string { } , "jet: unsupported slice element type" )
} )
2019-05-20 17:37:55 +02:00
}
func TestScanToValidDestination ( t * testing . T ) {
t . Run ( "pointer to struct" , func ( t * testing . T ) {
err := query . Query ( db , & struct { } { } )
assert . NilError ( t , err )
} )
2019-08-13 17:20:35 +02:00
t . Run ( "global query function scan" , func ( t * testing . T ) {
queryStr , args := query . Sql ( )
2019-09-27 11:46:31 +02:00
err := qrm . Query ( nil , db , queryStr , args , & struct { } { } )
2019-08-13 17:20:35 +02:00
assert . NilError ( t , err )
} )
2019-05-20 17:37:55 +02:00
t . Run ( "pointer to slice" , func ( t * testing . T ) {
err := query . Query ( db , & [ ] struct { } { } )
assert . NilError ( t , err )
} )
t . Run ( "pointer to slice of pointer to structs" , func ( t * testing . T ) {
err := query . Query ( db , & [ ] * struct { } { } )
assert . NilError ( t , err )
} )
t . Run ( "pointer to slice of strings" , func ( t * testing . T ) {
2019-05-22 11:28:32 +02:00
err := query . Query ( db , & [ ] int32 { } )
assert . NilError ( t , err )
} )
t . Run ( "pointer to slice of strings" , func ( t * testing . T ) {
err := query . Query ( db , & [ ] * int32 { } )
2019-05-20 17:37:55 +02:00
assert . NilError ( t , err )
} )
}
func TestScanToStruct ( t * testing . T ) {
query := Inventory .
SELECT ( Inventory . AllColumns ) .
ORDER_BY ( Inventory . InventoryID )
2019-08-13 17:20:35 +02:00
fmt . Println ( query . DebugSql ( ) )
2019-05-20 17:37:55 +02:00
t . Run ( "one struct" , func ( t * testing . T ) {
dest := model . Inventory { }
err := query . LIMIT ( 1 ) . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , inventory1 , dest )
} )
t . Run ( "multiple structs, just first one used" , func ( t * testing . T ) {
dest := model . Inventory { }
err := query . LIMIT ( 10 ) . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , inventory1 , dest )
} )
t . Run ( "one struct" , func ( t * testing . T ) {
dest := struct {
model . Inventory
} { }
err := query . LIMIT ( 1 ) . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , inventory1 , dest . Inventory )
} )
t . Run ( "one struct" , func ( t * testing . T ) {
dest := struct {
* model . Inventory
} { }
err := query . LIMIT ( 1 ) . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , inventory1 , * dest . Inventory )
} )
t . Run ( "invalid dest" , func ( t * testing . T ) {
dest := struct {
Inventory * * model . Inventory
} { }
2019-08-13 13:57:26 +02:00
testutils . AssertQueryPanicErr ( t , query , db , & dest , "jet: unsupported dest type: Inventory **model.Inventory" )
2019-05-20 17:37:55 +02:00
} )
t . Run ( "invalid dest 2" , func ( t * testing . T ) {
dest := struct {
Inventory * * * model . Inventory
} { }
2019-08-13 13:57:26 +02:00
testutils . AssertQueryPanicErr ( t , query , db , & dest , "jet: unsupported dest type: Inventory ***model.Inventory" )
2019-05-20 17:37:55 +02:00
} )
2019-05-21 17:34:43 +02:00
t . Run ( "custom struct" , func ( t * testing . T ) {
type Inventory struct {
2019-06-26 10:30:31 +02:00
InventoryID * int32 ` sql:"primary_key" `
2019-05-21 17:34:43 +02:00
FilmID int16
StoreID * int16
}
dest := Inventory { }
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . Equal ( t , * dest . InventoryID , int32 ( 1 ) )
assert . Equal ( t , dest . FilmID , int16 ( 1 ) )
assert . Equal ( t , * dest . StoreID , int16 ( 1 ) )
} )
2019-07-29 18:08:53 +02:00
t . Run ( "type convert int32 to int" , func ( t * testing . T ) {
2019-05-22 11:28:32 +02:00
type Inventory struct {
InventoryID int
FilmID string
}
dest := Inventory { }
err := query . Query ( db , & dest )
2019-07-29 18:08:53 +02:00
assert . NilError ( t , err )
2019-05-22 11:28:32 +02:00
} )
t . Run ( "type mismatch scanner type" , func ( t * testing . T ) {
type Inventory struct {
InventoryID uuid . UUID
FilmID string
}
dest := Inventory { }
2019-08-13 17:20:35 +02:00
testutils . AssertQueryPanicErr ( t , query , db , & dest , ` jet: Scan: unable to scan type int32 into UUID, at 'InventoryID uuid.UUID' of type postgres.Inventory ` )
2019-05-22 11:28:32 +02:00
} )
2019-08-13 17:20:35 +02:00
t . Run ( "type mismatch base type" , func ( t * testing . T ) {
type Inventory struct {
InventoryID int32
FilmID bool
}
dest := [ ] Inventory { }
testutils . AssertQueryPanicErr ( t , query . OFFSET ( 10 ) , db , & dest , ` jet: can't set int16 to bool ` )
} )
2019-05-20 17:37:55 +02:00
}
func TestScanToNestedStruct ( t * testing . T ) {
query := Inventory .
2019-05-29 14:03:38 +02:00
INNER_JOIN ( Film , Inventory . FilmID . EQ ( Film . FilmID ) ) .
INNER_JOIN ( Store , Inventory . StoreID . EQ ( Store . StoreID ) ) .
2019-05-20 17:37:55 +02:00
SELECT ( Inventory . AllColumns , Film . AllColumns , Store . AllColumns ) .
2019-05-29 14:03:38 +02:00
WHERE ( Inventory . InventoryID . EQ ( Int ( 1 ) ) )
2019-05-20 17:37:55 +02:00
t . Run ( "embedded structs" , func ( t * testing . T ) {
dest := struct {
model . Inventory
model . Film
model . Store
} { }
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , dest . Inventory , inventory1 )
assert . DeepEqual ( t , dest . Film , film1 )
assert . DeepEqual ( t , dest . Store , store1 )
} )
t . Run ( "embedded pointer structs" , func ( t * testing . T ) {
dest := struct {
* model . Inventory
* model . Film
* model . Store
} { }
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , * dest . Inventory , inventory1 )
assert . DeepEqual ( t , * dest . Film , film1 )
assert . DeepEqual ( t , * dest . Store , store1 )
} )
t . Run ( "embedded unused structs" , func ( t * testing . T ) {
dest := struct {
model . Inventory
model . Actor //unused
} { }
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , dest . Inventory , inventory1 )
assert . DeepEqual ( t , dest . Actor , model . Actor { } )
} )
t . Run ( "embedded unused pointer structs" , func ( t * testing . T ) {
dest := struct {
model . Inventory
* model . Actor //unused
} { }
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , dest . Inventory , inventory1 )
assert . DeepEqual ( t , dest . Actor , ( * model . Actor ) ( nil ) )
} )
t . Run ( "embedded unused pointer structs" , func ( t * testing . T ) {
dest := struct {
model . Inventory
Actor * model . Actor //unused
} { }
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , dest . Inventory , inventory1 )
assert . DeepEqual ( t , dest . Actor , ( * model . Actor ) ( nil ) )
} )
t . Run ( "embedded pointer to selected column" , func ( t * testing . T ) {
query := Inventory .
2019-05-29 14:03:38 +02:00
INNER_JOIN ( Film , Inventory . FilmID . EQ ( Film . FilmID ) ) .
INNER_JOIN ( Store , Inventory . StoreID . EQ ( Store . StoreID ) ) .
2019-06-04 11:52:37 +02:00
SELECT ( Inventory . AllColumns , Film . AllColumns , Store . AllColumns , String ( "" ) . AS ( "actor.first_name" ) ) .
2019-05-29 14:03:38 +02:00
WHERE ( Inventory . InventoryID . EQ ( Int ( 1 ) ) )
2019-05-20 17:37:55 +02:00
dest := struct {
model . Inventory
Actor * model . Actor //unused
} { }
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , dest . Inventory , inventory1 )
assert . Assert ( t , dest . Actor != nil )
} )
t . Run ( "struct embedded unused pointer" , func ( t * testing . T ) {
dest := struct {
model . Inventory
Actor * struct {
model . Actor
} //unused
} { }
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , dest . Inventory , inventory1 )
assert . DeepEqual ( t , dest . Actor , ( * struct { model . Actor } ) ( nil ) )
} )
t . Run ( "multiple embedded unused pointer" , func ( t * testing . T ) {
dest := struct {
model . Inventory
Actor * struct {
model . Actor //unused
model . Language //unesed
}
} { }
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , dest . Inventory , inventory1 )
assert . DeepEqual ( t , dest . Actor , ( * struct {
model . Actor
model . Language
} ) ( nil ) )
} )
t . Run ( "field not nil, embedded selected model" , func ( t * testing . T ) {
dest := struct {
model . Inventory
Actor * struct {
model . Actor //unselected
model . Film //selected
}
} { }
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , dest . Inventory , inventory1 )
assert . Assert ( t , dest . Actor != nil )
assert . DeepEqual ( t , dest . Actor . Actor , model . Actor { } )
assert . DeepEqual ( t , dest . Actor . Film , film1 )
} )
t . Run ( "field not nil, deeply nested selected model" , func ( t * testing . T ) {
dest := struct {
model . Inventory
Actor * struct {
model . Actor //unselected
Film * struct {
* model . Film //selected
}
}
} { }
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , dest . Inventory , inventory1 )
assert . Assert ( t , dest . Actor != nil )
assert . Assert ( t , dest . Actor . Film != nil )
assert . DeepEqual ( t , dest . Actor . Film . Film , & film1 )
} )
t . Run ( "embedded structs" , func ( t * testing . T ) {
query := Inventory .
2019-05-29 14:03:38 +02:00
INNER_JOIN ( Film , Inventory . FilmID . EQ ( Film . FilmID ) ) .
INNER_JOIN ( Store , Inventory . StoreID . EQ ( Store . StoreID ) ) .
INNER_JOIN ( Language , Film . LanguageID . EQ ( Language . LanguageID ) ) .
2019-05-20 17:37:55 +02:00
SELECT ( Inventory . AllColumns , Film . AllColumns , Store . AllColumns , Language . AllColumns ) .
2019-05-29 14:03:38 +02:00
WHERE ( Inventory . InventoryID . EQ ( Int ( 1 ) ) )
2019-05-20 17:37:55 +02:00
2019-06-12 12:47:30 +02:00
type Language3 model . Language
2019-05-20 17:37:55 +02:00
dest := struct {
model . Inventory
Film struct {
model . Film
Language model . Language
2019-06-26 10:30:31 +02:00
Language2 * model . Language ` alias:"Language.*" `
Language3 * Language3 ` alias:"language" `
2019-05-20 17:37:55 +02:00
Lang struct {
model . Language
}
Lang2 * struct {
model . Language
}
}
Store model . Store
} { }
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , dest . Inventory , inventory1 )
assert . DeepEqual ( t , dest . Film . Film , film1 )
assert . DeepEqual ( t , dest . Store , store1 )
assert . DeepEqual ( t , dest . Film . Language , language1 )
assert . DeepEqual ( t , dest . Film . Lang . Language , language1 )
assert . DeepEqual ( t , dest . Film . Lang2 . Language , language1 )
2019-06-26 10:30:31 +02:00
assert . DeepEqual ( t , dest . Film . Language2 , & language1 )
2019-06-12 12:47:30 +02:00
assert . DeepEqual ( t , model . Language ( * dest . Film . Language3 ) , language1 )
2019-05-20 17:37:55 +02:00
} )
}
func TestScanToSlice ( t * testing . T ) {
t . Run ( "slice of structs" , func ( t * testing . T ) {
query := Inventory .
SELECT ( Inventory . AllColumns ) .
ORDER_BY ( Inventory . InventoryID ) .
LIMIT ( 10 )
2019-05-21 13:11:45 +02:00
t . Run ( "slice od inventory" , func ( t * testing . T ) {
dest := [ ] model . Inventory { }
2019-05-20 17:37:55 +02:00
2019-05-21 13:11:45 +02:00
err := query . Query ( db , & dest )
2019-05-20 17:37:55 +02:00
2019-05-21 13:11:45 +02:00
assert . NilError ( t , err )
assert . Equal ( t , len ( dest ) , 10 )
assert . DeepEqual ( t , dest [ 0 ] , inventory1 )
assert . DeepEqual ( t , dest [ 1 ] , inventory2 )
} )
t . Run ( "slice of ints" , func ( t * testing . T ) {
var dest [ ] int32
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , dest , [ ] int32 { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 } )
} )
2019-05-22 11:28:32 +02:00
2019-08-13 17:20:35 +02:00
t . Run ( "slice type convertible" , func ( t * testing . T ) {
2019-05-22 11:28:32 +02:00
var dest [ ] int
err := query . Query ( db , & dest )
2019-08-13 17:20:35 +02:00
assert . NilError ( t , err )
} )
t . Run ( "slice type mismatch" , func ( t * testing . T ) {
var dest [ ] bool
testutils . AssertQueryPanicErr ( t , query , db , & dest , ` jet: can't append int32 to []bool slice ` )
//assert.Error(t, err, `jet: can't append int32 to []bool slice `)
2019-05-22 11:28:32 +02:00
} )
2019-05-20 17:37:55 +02:00
} )
t . Run ( "slice of complex structs" , func ( t * testing . T ) {
query := Inventory .
2019-05-29 14:03:38 +02:00
INNER_JOIN ( Film , Inventory . FilmID . EQ ( Film . FilmID ) ) .
INNER_JOIN ( Store , Inventory . StoreID . EQ ( Store . StoreID ) ) .
2019-06-26 10:30:31 +02:00
SELECT (
Inventory . AllColumns ,
Film . AllColumns ,
Store . AllColumns ,
) .
2019-05-20 17:37:55 +02:00
ORDER_BY ( Inventory . InventoryID ) .
LIMIT ( 10 )
2019-05-21 13:11:45 +02:00
t . Run ( "struct with slice of ints" , func ( t * testing . T ) {
var dest struct {
model . Film
2019-06-26 10:30:31 +02:00
IDs [ ] int32 ` alias:"inventory.inventory_id" `
2019-05-21 13:11:45 +02:00
}
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . DeepEqual ( t , dest . Film , film1 )
assert . DeepEqual ( t , dest . IDs , [ ] int32 { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 } )
} )
t . Run ( "slice of structs with slice of ints" , func ( t * testing . T ) {
var dest [ ] struct {
model . Film
2019-07-03 16:27:14 +02:00
IDs [ ] int32 ` alias:"inventory.inventory_id" `
2019-05-21 13:11:45 +02:00
}
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . Equal ( t , len ( dest ) , 2 )
assert . DeepEqual ( t , dest [ 0 ] . Film , film1 )
assert . DeepEqual ( t , dest [ 0 ] . IDs , [ ] int32 { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 } )
assert . DeepEqual ( t , dest [ 1 ] . Film , film2 )
assert . DeepEqual ( t , dest [ 1 ] . IDs , [ ] int32 { 9 , 10 } )
} )
t . Run ( "slice of structs with slice of pointer to ints" , func ( t * testing . T ) {
var dest [ ] struct {
model . Film
2019-07-03 16:27:14 +02:00
IDs [ ] * int32 ` alias:"inventory.inventory_id" `
2019-05-21 13:11:45 +02:00
}
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . Equal ( t , len ( dest ) , 2 )
assert . DeepEqual ( t , dest [ 0 ] . Film , film1 )
2019-07-29 18:08:53 +02:00
assert . DeepEqual ( t , dest [ 0 ] . IDs , [ ] * int32 { Int32Ptr ( 1 ) , Int32Ptr ( 2 ) , Int32Ptr ( 3 ) , Int32Ptr ( 4 ) ,
Int32Ptr ( 5 ) , Int32Ptr ( 6 ) , Int32Ptr ( 7 ) , Int32Ptr ( 8 ) } )
2019-05-21 13:11:45 +02:00
assert . DeepEqual ( t , dest [ 1 ] . Film , film2 )
2019-07-29 18:08:53 +02:00
assert . DeepEqual ( t , dest [ 1 ] . IDs , [ ] * int32 { Int32Ptr ( 9 ) , Int32Ptr ( 10 ) } )
2019-05-21 13:11:45 +02:00
} )
2019-05-20 17:37:55 +02:00
t . Run ( "complex struct 1" , func ( t * testing . T ) {
dest := [ ] struct {
model . Inventory
model . Film
model . Store
} { }
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . Equal ( t , len ( dest ) , 10 )
assert . DeepEqual ( t , dest [ 0 ] . Inventory , inventory1 )
assert . DeepEqual ( t , dest [ 0 ] . Film , film1 )
assert . DeepEqual ( t , dest [ 0 ] . Store , store1 )
assert . DeepEqual ( t , dest [ 1 ] . Inventory , inventory2 )
} )
t . Run ( "complex struct 2" , func ( t * testing . T ) {
var dest [ ] struct {
* model . Inventory
model . Film
* model . Store
}
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . Equal ( t , len ( dest ) , 10 )
assert . DeepEqual ( t , dest [ 0 ] . Inventory , & inventory1 )
assert . DeepEqual ( t , dest [ 0 ] . Film , film1 )
assert . DeepEqual ( t , dest [ 0 ] . Store , & store1 )
assert . DeepEqual ( t , dest [ 1 ] . Inventory , & inventory2 )
} )
t . Run ( "complex struct 3" , func ( t * testing . T ) {
var dest [ ] struct {
Inventory model . Inventory
Film * model . Film
Store struct {
* model . Store
}
}
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . Equal ( t , len ( dest ) , 10 )
assert . DeepEqual ( t , dest [ 0 ] . Inventory , inventory1 )
assert . DeepEqual ( t , dest [ 0 ] . Film , & film1 )
assert . DeepEqual ( t , dest [ 0 ] . Store . Store , & store1 )
assert . DeepEqual ( t , dest [ 1 ] . Inventory , inventory2 )
} )
t . Run ( "complex struct 4" , func ( t * testing . T ) {
var dest [ ] struct {
model . Film
Inventories [ ] struct {
model . Inventory
model . Store
}
}
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . Equal ( t , len ( dest ) , 2 )
assert . DeepEqual ( t , dest [ 0 ] . Film , film1 )
assert . DeepEqual ( t , len ( dest [ 0 ] . Inventories ) , 8 )
assert . DeepEqual ( t , dest [ 0 ] . Inventories [ 0 ] . Inventory , inventory1 )
assert . DeepEqual ( t , dest [ 0 ] . Inventories [ 0 ] . Store , store1 )
} )
t . Run ( "complex struct 5" , func ( t * testing . T ) {
var dest [ ] struct {
model . Film
Inventories [ ] struct {
model . Inventory
Rentals * [ ] model . Rental
Rentals2 [ ] model . Rental
}
}
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . Equal ( t , len ( dest ) , 2 )
assert . DeepEqual ( t , dest [ 0 ] . Film , film1 )
assert . Equal ( t , len ( dest [ 0 ] . Inventories ) , 8 )
assert . DeepEqual ( t , dest [ 0 ] . Inventories [ 0 ] . Inventory , inventory1 )
assert . Assert ( t , dest [ 0 ] . Inventories [ 0 ] . Rentals == nil )
assert . Assert ( t , dest [ 0 ] . Inventories [ 0 ] . Rentals2 == nil )
} )
} )
t . Run ( "slice of complex structs 2" , func ( t * testing . T ) {
query := Country .
2019-05-29 14:03:38 +02:00
INNER_JOIN ( City , City . CountryID . EQ ( Country . CountryID ) ) .
INNER_JOIN ( Address , Address . CityID . EQ ( City . CityID ) ) .
INNER_JOIN ( Customer , Customer . AddressID . EQ ( Address . AddressID ) ) .
2019-05-20 17:37:55 +02:00
SELECT ( Country . AllColumns , City . AllColumns , Address . AllColumns , Customer . AllColumns ) .
ORDER_BY ( Country . CountryID . ASC ( ) , City . CityID . ASC ( ) , Address . AddressID . ASC ( ) , Customer . CustomerID . ASC ( ) ) .
LIMIT ( 1000 )
t . Run ( "dest1" , func ( t * testing . T ) {
var dest [ ] struct {
model . Country
Cities [ ] struct {
model . City
Adresses [ ] struct {
model . Address
Customer model . Customer
}
}
}
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . Equal ( t , len ( dest ) , 108 )
assert . DeepEqual ( t , dest [ 100 ] . Country , countryUk )
assert . Equal ( t , len ( dest [ 100 ] . Cities ) , 8 )
assert . DeepEqual ( t , dest [ 100 ] . Cities [ 2 ] . City , cityLondon )
assert . Equal ( t , len ( dest [ 100 ] . Cities [ 2 ] . Adresses ) , 2 )
assert . DeepEqual ( t , dest [ 100 ] . Cities [ 2 ] . Adresses [ 0 ] . Address , address256 )
assert . DeepEqual ( t , dest [ 100 ] . Cities [ 2 ] . Adresses [ 0 ] . Customer , customer256 )
assert . DeepEqual ( t , dest [ 100 ] . Cities [ 2 ] . Adresses [ 1 ] . Address , addres517 )
assert . DeepEqual ( t , dest [ 100 ] . Cities [ 2 ] . Adresses [ 1 ] . Customer , customer512 )
} )
t . Run ( "dest1" , func ( t * testing . T ) {
var dest [ ] * struct {
* model . Country
Cities [ ] * struct {
* model . City
Adresses * [ ] * struct {
* model . Address
Customer * model . Customer
}
}
}
err := query . Query ( db , & dest )
assert . NilError ( t , err )
assert . Equal ( t , len ( dest ) , 108 )
assert . DeepEqual ( t , dest [ 100 ] . Country , & countryUk )
assert . Equal ( t , len ( dest [ 100 ] . Cities ) , 8 )
assert . DeepEqual ( t , dest [ 100 ] . Cities [ 2 ] . City , & cityLondon )
assert . Equal ( t , len ( * dest [ 100 ] . Cities [ 2 ] . Adresses ) , 2 )
assert . DeepEqual ( t , ( * dest [ 100 ] . Cities [ 2 ] . Adresses ) [ 0 ] . Address , & address256 )
assert . DeepEqual ( t , ( * dest [ 100 ] . Cities [ 2 ] . Adresses ) [ 0 ] . Customer , & customer256 )
assert . DeepEqual ( t , ( * dest [ 100 ] . Cities [ 2 ] . Adresses ) [ 1 ] . Address , & addres517 )
assert . DeepEqual ( t , ( * dest [ 100 ] . Cities [ 2 ] . Adresses ) [ 1 ] . Customer , & customer512 )
} )
} )
t . Run ( "dest1" , func ( t * testing . T ) {
var dest [ ] * struct {
* model . Country
Cities [ ] * * struct {
* model . City
}
}
2019-08-13 17:20:35 +02:00
testutils . AssertQueryPanicErr ( t , query , db , & dest , "jet: unsupported slice element type at 'Cities []**struct { *model.City }'" )
2019-05-20 17:37:55 +02:00
} )
}
var address256 = model . Address {
AddressID : 256 ,
Address : "1497 Yuzhou Drive" ,
2019-07-29 18:08:53 +02:00
Address2 : StringPtr ( "" ) ,
2019-05-20 17:37:55 +02:00
District : "England" ,
CityID : 312 ,
2019-07-29 18:08:53 +02:00
PostalCode : StringPtr ( "3433" ) ,
2019-05-20 17:37:55 +02:00
Phone : "246810237916" ,
2019-07-29 18:08:53 +02:00
LastUpdate : * testutils . TimestampWithoutTimeZone ( "2006-02-15 09:45:30" , 0 ) ,
2019-05-20 17:37:55 +02:00
}
var addres517 = model . Address {
AddressID : 517 ,
Address : "548 Uruapan Street" ,
2019-07-29 18:08:53 +02:00
Address2 : StringPtr ( "" ) ,
2019-05-20 17:37:55 +02:00
District : "Ontario" ,
CityID : 312 ,
2019-07-29 18:08:53 +02:00
PostalCode : StringPtr ( "35653" ) ,
2019-05-20 17:37:55 +02:00
Phone : "879347453467" ,
2019-07-29 18:08:53 +02:00
LastUpdate : * testutils . TimestampWithoutTimeZone ( "2006-02-15 09:45:30" , 0 ) ,
2019-05-20 17:37:55 +02:00
}
var customer256 = model . Customer {
CustomerID : 252 ,
StoreID : 2 ,
FirstName : "Mattie" ,
LastName : "Hoffman" ,
2019-07-29 18:08:53 +02:00
Email : StringPtr ( "mattie.hoffman@sakilacustomer.org" ) ,
2019-05-20 17:37:55 +02:00
AddressID : 256 ,
Activebool : true ,
2019-07-29 18:08:53 +02:00
CreateDate : * testutils . TimestampWithoutTimeZone ( "2006-02-14 00:00:00" , 0 ) ,
LastUpdate : testutils . TimestampWithoutTimeZone ( "2013-05-26 14:49:45.738" , 0 ) ,
Active : Int32Ptr ( 1 ) ,
2019-05-20 17:37:55 +02:00
}
var customer512 = model . Customer {
CustomerID : 512 ,
StoreID : 1 ,
FirstName : "Cecil" ,
LastName : "Vines" ,
2019-07-29 18:08:53 +02:00
Email : StringPtr ( "cecil.vines@sakilacustomer.org" ) ,
2019-05-20 17:37:55 +02:00
AddressID : 517 ,
Activebool : true ,
2019-07-29 18:08:53 +02:00
CreateDate : * testutils . TimestampWithoutTimeZone ( "2006-02-14 00:00:00" , 0 ) ,
LastUpdate : testutils . TimestampWithoutTimeZone ( "2013-05-26 14:49:45.738" , 0 ) ,
Active : Int32Ptr ( 1 ) ,
2019-05-20 17:37:55 +02:00
}
var countryUk = model . Country {
CountryID : 102 ,
Country : "United Kingdom" ,
2019-07-29 18:08:53 +02:00
LastUpdate : * testutils . TimestampWithoutTimeZone ( "2006-02-15 09:44:00" , 0 ) ,
2019-05-20 17:37:55 +02:00
}
var cityLondon = model . City {
CityID : 312 ,
City : "London" ,
CountryID : 102 ,
2019-07-29 18:08:53 +02:00
LastUpdate : * testutils . TimestampWithoutTimeZone ( "2006-02-15 09:45:25" , 0 ) ,
2019-05-20 17:37:55 +02:00
}
var inventory1 = model . Inventory {
InventoryID : 1 ,
FilmID : 1 ,
StoreID : 1 ,
2019-07-29 18:08:53 +02:00
LastUpdate : * testutils . TimestampWithoutTimeZone ( "2006-02-15 10:09:17" , 0 ) ,
2019-05-20 17:37:55 +02:00
}
var inventory2 = model . Inventory {
InventoryID : 2 ,
FilmID : 1 ,
StoreID : 1 ,
2019-07-29 18:08:53 +02:00
LastUpdate : * testutils . TimestampWithoutTimeZone ( "2006-02-15 10:09:17" , 0 ) ,
2019-05-20 17:37:55 +02:00
}
var film1 = model . Film {
FilmID : 1 ,
Title : "Academy Dinosaur" ,
2019-07-29 18:08:53 +02:00
Description : StringPtr ( "A Epic Drama of a Feminist And a Mad Scientist who must Battle a Teacher in The Canadian Rockies" ) ,
ReleaseYear : Int32Ptr ( 2006 ) ,
2019-05-20 17:37:55 +02:00
LanguageID : 1 ,
RentalDuration : 6 ,
RentalRate : 0.99 ,
2019-07-29 18:08:53 +02:00
Length : Int16Ptr ( 86 ) ,
2019-05-20 17:37:55 +02:00
ReplacementCost : 20.99 ,
Rating : & pgRating ,
2019-07-29 18:08:53 +02:00
LastUpdate : * testutils . TimestampWithoutTimeZone ( "2013-05-26 14:50:58.951" , 3 ) ,
SpecialFeatures : StringPtr ( "{\"Deleted Scenes\",\"Behind the Scenes\"}" ) ,
2019-05-20 17:37:55 +02:00
Fulltext : "'academi':1 'battl':15 'canadian':20 'dinosaur':2 'drama':5 'epic':4 'feminist':8 'mad':11 'must':14 'rocki':21 'scientist':12 'teacher':17" ,
}
2019-05-21 13:11:45 +02:00
var film2 = model . Film {
FilmID : 2 ,
Title : "Ace Goldfinger" ,
2019-07-29 18:08:53 +02:00
Description : StringPtr ( "A Astounding Epistle of a Database Administrator And a Explorer who must Find a Car in Ancient China" ) ,
ReleaseYear : Int32Ptr ( 2006 ) ,
2019-05-21 13:11:45 +02:00
LanguageID : 1 ,
RentalDuration : 3 ,
RentalRate : 4.99 ,
2019-07-29 18:08:53 +02:00
Length : Int16Ptr ( 48 ) ,
2019-05-21 13:11:45 +02:00
ReplacementCost : 12.99 ,
Rating : & gRating ,
2019-07-29 18:08:53 +02:00
LastUpdate : * testutils . TimestampWithoutTimeZone ( "2013-05-26 14:50:58.951" , 3 ) ,
SpecialFeatures : StringPtr ( ` { Trailers,"Deleted Scenes"} ` ) ,
2019-05-21 13:11:45 +02:00
Fulltext : ` 'ace':1 'administr':9 'ancient':19 'astound':4 'car':17 'china':20 'databas':8 'epistl':5 'explor':12 'find':15 'goldfing':2 'must':14 ` ,
}
2019-05-20 17:37:55 +02:00
var store1 = model . Store {
StoreID : 1 ,
ManagerStaffID : 1 ,
AddressID : 1 ,
2019-07-29 18:08:53 +02:00
LastUpdate : * testutils . TimestampWithoutTimeZone ( "2006-02-15 09:57:12" , 0 ) ,
2019-05-20 17:37:55 +02:00
}
2019-07-03 16:27:14 +02:00
var pgRating = model . MpaaRating_Pg
2019-05-21 13:11:45 +02:00
var gRating = model . MpaaRating_G
2019-05-20 17:37:55 +02:00
var language1 = model . Language {
LanguageID : 1 ,
Name : "English " ,
2019-07-29 18:08:53 +02:00
LastUpdate : * testutils . TimestampWithoutTimeZone ( "2006-02-15 10:02:19" , 0 ) ,
2019-05-20 17:37:55 +02:00
}