Merge branch 'byteslicepkeys' into dev
This commit is contained in:
commit
c1dab978a5
50 changed files with 1859 additions and 958 deletions
|
@ -179,6 +179,10 @@ fmt.Println(len(users.R.FavoriteMovies))
|
|||
a *composite primary key* that encompasses both foreign table foreign keys. For example, on a
|
||||
join table named `user_videos` you should have: `primary key(user_id, video_id)`, with both `user_id`
|
||||
and `video_id` being foreign key columns to the users and videos tables respectively.
|
||||
* For MySQL if using the `github.com/go-sql-driver/mysql` driver, please activate
|
||||
[time.Time parsing](https://github.com/go-sql-driver/mysql#timetime-support) when making your
|
||||
MySQL database connection. SQLBoiler uses `time.Time` and `null.Time` to represent time in
|
||||
it's models and without this enabled any models with `DATE`/`DATETIME` columns will not work.
|
||||
|
||||
### Pro Tips
|
||||
* Foreign key column names should end with `_id`.
|
||||
|
@ -1060,6 +1064,10 @@ with all Postgres drivers. Example:
|
|||
|
||||
Please note that multi-dimensional Postgres ARRAY types are not supported at this time.
|
||||
|
||||
#### Why aren't my time.Time or null.Time fields working in MySQL?
|
||||
|
||||
You *must* use a DSN flag in MySQL connections, see: [Requirements](#requirements)
|
||||
|
||||
#### Where is the homepage?
|
||||
|
||||
The homepage for the [SQLBoiler](https://github.com/vattle/sqlboiler) [Golang ORM](https://github.com/vattle/sqlboiler) generator is located at: https://github.com/vattle/sqlboiler
|
||||
|
|
|
@ -5,11 +5,6 @@ import "github.com/vattle/sqlboiler/strmangle"
|
|||
// Column holds information about a database column.
|
||||
// Types are Go types, converted by TranslateColumnType.
|
||||
type Column struct {
|
||||
// ArrType is the underlying data type of the Postgres
|
||||
// ARRAY type. See here:
|
||||
// https://www.postgresql.org/docs/9.1/static/infoschema-element-types.html
|
||||
ArrType *string
|
||||
UDTName string
|
||||
Name string
|
||||
Type string
|
||||
DBType string
|
||||
|
@ -17,6 +12,13 @@ type Column struct {
|
|||
Nullable bool
|
||||
Unique bool
|
||||
Validated bool
|
||||
|
||||
// Postgres only extension bits
|
||||
// ArrType is the underlying data type of the Postgres
|
||||
// ARRAY type. See here:
|
||||
// https://www.postgresql.org/docs/9.1/static/infoschema-element-types.html
|
||||
ArrType *string
|
||||
UDTName string
|
||||
}
|
||||
|
||||
// ColumnNames of the columns.
|
||||
|
|
|
@ -47,6 +47,10 @@ func MySQLBuildQueryString(user, pass, dbname, host string, port int, sslmode st
|
|||
config.Addr += ":" + strconv.Itoa(port)
|
||||
config.TLSConfig = sslmode
|
||||
|
||||
// MySQL is a bad, and by default reads date/datetime into a []byte
|
||||
// instead of a time.Time. Tell it to stop being a bad.
|
||||
config.ParseTime = true
|
||||
|
||||
return config.FormatDSN()
|
||||
}
|
||||
|
||||
|
@ -256,7 +260,9 @@ func (m *MySQLDriver) TranslateColumnType(c bdb.Column) bdb.Column {
|
|||
c.Type = "null.Int8"
|
||||
case "smallint":
|
||||
c.Type = "null.Int16"
|
||||
case "mediumint", "int", "integer":
|
||||
case "mediumint":
|
||||
c.Type = "null.Int32"
|
||||
case "int", "integer":
|
||||
c.Type = "null.Int"
|
||||
case "bigint":
|
||||
c.Type = "null.Int64"
|
||||
|
@ -281,10 +287,12 @@ func (m *MySQLDriver) TranslateColumnType(c bdb.Column) bdb.Column {
|
|||
c.Type = "int8"
|
||||
case "smallint":
|
||||
c.Type = "int16"
|
||||
case "mediumint", "int", "integer":
|
||||
case "mediumint":
|
||||
c.Type = "int32"
|
||||
case "int", "integer":
|
||||
c.Type = "int"
|
||||
case "bigint":
|
||||
c.Type = "null.Int64"
|
||||
c.Type = "int64"
|
||||
case "float":
|
||||
c.Type = "float32"
|
||||
case "double", "double precision", "real":
|
||||
|
|
|
@ -119,5 +119,6 @@ func setForeignKeyConstraints(t *Table, tables []Table) {
|
|||
}
|
||||
|
||||
func setRelationships(t *Table, tables []Table) {
|
||||
t.ToOneRelationships = toOneRelationships(*t, tables)
|
||||
t.ToManyRelationships = toManyRelationships(*t, tables)
|
||||
}
|
||||
|
|
|
@ -127,13 +127,13 @@ func TestTables(t *testing.T) {
|
|||
if len(pilots.Columns) != 2 {
|
||||
t.Error()
|
||||
}
|
||||
if pilots.ToManyRelationships[0].ForeignTable != "jets" {
|
||||
if pilots.ToOneRelationships[0].ForeignTable != "jets" {
|
||||
t.Error("want a to many to jets")
|
||||
}
|
||||
if pilots.ToManyRelationships[1].ForeignTable != "licenses" {
|
||||
if pilots.ToManyRelationships[0].ForeignTable != "licenses" {
|
||||
t.Error("want a to many to languages")
|
||||
}
|
||||
if pilots.ToManyRelationships[2].ForeignTable != "languages" {
|
||||
if pilots.ToManyRelationships[1].ForeignTable != "languages" {
|
||||
t.Error("want a to many to languages")
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,21 @@
|
|||
package bdb
|
||||
|
||||
// ToOneRelationship describes a relationship between two tables where the local
|
||||
// table has no id, and the foregin table has an id that matches a column in the
|
||||
// local table, that column is also unique which changes the dynamic into a
|
||||
// one-to-one style, not a to-many.
|
||||
type ToOneRelationship struct {
|
||||
Table string
|
||||
Column string
|
||||
Nullable bool
|
||||
Unique bool
|
||||
|
||||
ForeignTable string
|
||||
ForeignColumn string
|
||||
ForeignColumnNullable bool
|
||||
ForeignColumnUnique bool
|
||||
}
|
||||
|
||||
// ToManyRelationship describes a relationship between two tables where the
|
||||
// local table has no id, and the foreign table has an id that matches a column
|
||||
// in the local table.
|
||||
|
@ -26,31 +42,64 @@ type ToManyRelationship struct {
|
|||
JoinForeignColumnUnique bool
|
||||
}
|
||||
|
||||
// ToOneRelationships relationship lookups
|
||||
// Input should be the sql name of a table like: videos
|
||||
func ToOneRelationships(table string, tables []Table) []ToOneRelationship {
|
||||
localTable := GetTable(tables, table)
|
||||
return toOneRelationships(localTable, tables)
|
||||
}
|
||||
|
||||
// ToManyRelationships relationship lookups
|
||||
// Input should be the sql name of a table like: videos
|
||||
func ToManyRelationships(table string, tables []Table) []ToManyRelationship {
|
||||
localTable := GetTable(tables, table)
|
||||
|
||||
return toManyRelationships(localTable, tables)
|
||||
}
|
||||
|
||||
func toOneRelationships(table Table, tables []Table) []ToOneRelationship {
|
||||
var relationships []ToOneRelationship
|
||||
|
||||
for _, t := range tables {
|
||||
for _, f := range t.FKeys {
|
||||
if f.ForeignTable == table.Name && !t.IsJoinTable && f.Unique {
|
||||
relationships = append(relationships, buildToOneRelationship(table, f, t, tables))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return relationships
|
||||
}
|
||||
|
||||
func toManyRelationships(table Table, tables []Table) []ToManyRelationship {
|
||||
var relationships []ToManyRelationship
|
||||
|
||||
for _, t := range tables {
|
||||
for _, f := range t.FKeys {
|
||||
if f.ForeignTable != table.Name {
|
||||
continue
|
||||
if f.ForeignTable == table.Name && !f.Unique {
|
||||
relationships = append(relationships, buildToManyRelationship(table, f, t, tables))
|
||||
}
|
||||
|
||||
relationships = append(relationships, buildRelationship(table, f, t, tables))
|
||||
}
|
||||
}
|
||||
|
||||
return relationships
|
||||
}
|
||||
|
||||
func buildRelationship(localTable Table, foreignKey ForeignKey, foreignTable Table, tables []Table) ToManyRelationship {
|
||||
func buildToOneRelationship(localTable Table, foreignKey ForeignKey, foreignTable Table, tables []Table) ToOneRelationship {
|
||||
return ToOneRelationship{
|
||||
Table: localTable.Name,
|
||||
Column: foreignKey.ForeignColumn,
|
||||
Nullable: foreignKey.ForeignColumnNullable,
|
||||
Unique: foreignKey.ForeignColumnUnique,
|
||||
|
||||
ForeignTable: foreignTable.Name,
|
||||
ForeignColumn: foreignKey.Column,
|
||||
ForeignColumnNullable: foreignKey.Nullable,
|
||||
ForeignColumnUnique: foreignKey.Unique,
|
||||
}
|
||||
}
|
||||
|
||||
func buildToManyRelationship(localTable Table, foreignKey ForeignKey, foreignTable Table, tables []Table) ToManyRelationship {
|
||||
if !foreignTable.IsJoinTable {
|
||||
col := localTable.GetColumn(foreignKey.ForeignColumn)
|
||||
return ToManyRelationship{
|
||||
|
|
|
@ -5,67 +5,128 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func TestToOneRelationships(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tables := []Table{
|
||||
{
|
||||
Name: "pilots",
|
||||
Columns: []Column{{Name: "id", Unique: true}, {Name: "name", Unique: true}}},
|
||||
{
|
||||
Name: "airports",
|
||||
Columns: []Column{{Name: "id", Unique: true}, {Name: "size", Unique: true}},
|
||||
},
|
||||
{
|
||||
Name: "jets",
|
||||
Columns: []Column{{Name: "id", Unique: true}, {Name: "pilot_id", Unique: true}, {Name: "airport_id", Unique: true}},
|
||||
FKeys: []ForeignKey{
|
||||
{Name: "jets_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Unique: true},
|
||||
{Name: "jets_airport_id_fk", Column: "airport_id", ForeignTable: "airports", ForeignColumn: "id", Unique: true},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "licenses",
|
||||
Columns: []Column{{Name: "id", Unique: true}, {Name: "pilot_id", Unique: true}},
|
||||
FKeys: []ForeignKey{
|
||||
{Name: "licenses_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Unique: true},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "hangars",
|
||||
Columns: []Column{{Name: "id", Unique: true}, {Name: "name", Unique: true}},
|
||||
},
|
||||
{
|
||||
Name: "languages",
|
||||
Columns: []Column{{Name: "id", Unique: true}, {Name: "language", Unique: true}},
|
||||
},
|
||||
{
|
||||
Name: "pilot_languages",
|
||||
IsJoinTable: true,
|
||||
Columns: []Column{{Name: "pilot_id", Unique: true}, {Name: "language_id", Unique: true}},
|
||||
FKeys: []ForeignKey{
|
||||
{Name: "pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Unique: true},
|
||||
{Name: "language_id_fk", Column: "language_id", ForeignTable: "languages", ForeignColumn: "id", Unique: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
relationships := ToOneRelationships("pilots", tables)
|
||||
|
||||
expected := []ToOneRelationship{
|
||||
{
|
||||
Table: "pilots",
|
||||
Column: "id",
|
||||
Nullable: false,
|
||||
Unique: false,
|
||||
|
||||
ForeignTable: "jets",
|
||||
ForeignColumn: "pilot_id",
|
||||
ForeignColumnNullable: false,
|
||||
ForeignColumnUnique: true,
|
||||
},
|
||||
{
|
||||
Table: "pilots",
|
||||
Column: "id",
|
||||
Nullable: false,
|
||||
Unique: false,
|
||||
|
||||
ForeignTable: "licenses",
|
||||
ForeignColumn: "pilot_id",
|
||||
ForeignColumnNullable: false,
|
||||
ForeignColumnUnique: true,
|
||||
},
|
||||
}
|
||||
|
||||
if len(relationships) != 2 {
|
||||
t.Error("wrong # of relationships", len(relationships))
|
||||
}
|
||||
|
||||
for i, v := range relationships {
|
||||
if !reflect.DeepEqual(v, expected[i]) {
|
||||
t.Errorf("[%d] Mismatch between relationships:\n\nwant:%#v\n\ngot:%#v\n\n", i, expected[i], v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestToManyRelationships(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tables := []Table{
|
||||
{
|
||||
Name: "pilots",
|
||||
Columns: []Column{
|
||||
{Name: "id"},
|
||||
{Name: "name"},
|
||||
},
|
||||
Name: "pilots",
|
||||
Columns: []Column{{Name: "id"}, {Name: "name"}},
|
||||
},
|
||||
{
|
||||
Name: "airports",
|
||||
Columns: []Column{
|
||||
{Name: "id"},
|
||||
{Name: "size"},
|
||||
},
|
||||
Name: "airports",
|
||||
Columns: []Column{{Name: "id"}, {Name: "size"}},
|
||||
},
|
||||
{
|
||||
Name: "jets",
|
||||
Columns: []Column{
|
||||
{Name: "id"},
|
||||
{Name: "pilot_id"},
|
||||
{Name: "airport_id"},
|
||||
},
|
||||
Name: "jets",
|
||||
Columns: []Column{{Name: "id"}, {Name: "pilot_id"}, {Name: "airport_id"}},
|
||||
FKeys: []ForeignKey{
|
||||
{Name: "jets_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id"},
|
||||
{Name: "jets_airport_id_fk", Column: "airport_id", ForeignTable: "airports", ForeignColumn: "id"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "licenses",
|
||||
Columns: []Column{
|
||||
{Name: "id"},
|
||||
{Name: "pilot_id"},
|
||||
},
|
||||
Name: "licenses",
|
||||
Columns: []Column{{Name: "id"}, {Name: "pilot_id"}},
|
||||
FKeys: []ForeignKey{
|
||||
{Name: "licenses_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "hangars",
|
||||
Columns: []Column{
|
||||
{Name: "id"},
|
||||
{Name: "name"},
|
||||
},
|
||||
Name: "hangars",
|
||||
Columns: []Column{{Name: "id"}, {Name: "name"}},
|
||||
},
|
||||
{
|
||||
Name: "languages",
|
||||
Columns: []Column{
|
||||
{Name: "id"},
|
||||
{Name: "language"},
|
||||
},
|
||||
Name: "languages",
|
||||
Columns: []Column{{Name: "id"}, {Name: "language"}},
|
||||
},
|
||||
{
|
||||
Name: "pilot_languages",
|
||||
IsJoinTable: true,
|
||||
Columns: []Column{
|
||||
{Name: "pilot_id"},
|
||||
{Name: "language_id"},
|
||||
},
|
||||
Columns: []Column{{Name: "pilot_id"}, {Name: "language_id"}},
|
||||
FKeys: []ForeignKey{
|
||||
{Name: "pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id"},
|
||||
{Name: "language_id_fk", Column: "language_id", ForeignTable: "languages", ForeignColumn: "id"},
|
||||
|
@ -132,7 +193,7 @@ func TestToManyRelationships(t *testing.T) {
|
|||
|
||||
for i, v := range relationships {
|
||||
if !reflect.DeepEqual(v, expected[i]) {
|
||||
t.Errorf("[%d] Mismatch between relationships:\n\n%#v\n\n%#v\n\n", i, v, expected[i])
|
||||
t.Errorf("[%d] Mismatch between relationships:\n\nwant:%#v\n\ngot:%#v\n\n", i, expected[i], v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,65 +203,42 @@ func TestToManyRelationshipsNull(t *testing.T) {
|
|||
|
||||
tables := []Table{
|
||||
{
|
||||
Name: "pilots",
|
||||
Columns: []Column{
|
||||
{Name: "id", Nullable: true, Unique: true},
|
||||
{Name: "name", Nullable: true, Unique: true},
|
||||
},
|
||||
Name: "pilots",
|
||||
Columns: []Column{{Name: "id", Nullable: true}, {Name: "name", Nullable: true}}},
|
||||
{
|
||||
Name: "airports",
|
||||
Columns: []Column{{Name: "id", Nullable: true}, {Name: "size", Nullable: true}},
|
||||
},
|
||||
{
|
||||
Name: "airports",
|
||||
Columns: []Column{
|
||||
{Name: "id", Nullable: true, Unique: true},
|
||||
{Name: "size", Nullable: true, Unique: true},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "jets",
|
||||
Columns: []Column{
|
||||
{Name: "id", Nullable: true, Unique: true},
|
||||
{Name: "pilot_id", Nullable: true, Unique: true},
|
||||
{Name: "airport_id", Nullable: true, Unique: true},
|
||||
},
|
||||
Name: "jets",
|
||||
Columns: []Column{{Name: "id", Nullable: true}, {Name: "pilot_id", Nullable: true}, {Name: "airport_id", Nullable: true}},
|
||||
FKeys: []ForeignKey{
|
||||
{Name: "jets_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true, Unique: true},
|
||||
{Name: "jets_airport_id_fk", Column: "airport_id", ForeignTable: "airports", ForeignColumn: "id", Nullable: true, Unique: true},
|
||||
{Name: "jets_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true},
|
||||
{Name: "jets_airport_id_fk", Column: "airport_id", ForeignTable: "airports", ForeignColumn: "id", Nullable: true},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "licenses",
|
||||
Columns: []Column{
|
||||
{Name: "id", Nullable: true, Unique: true},
|
||||
{Name: "pilot_id", Nullable: true, Unique: true},
|
||||
},
|
||||
Name: "licenses",
|
||||
Columns: []Column{{Name: "id", Nullable: true}, {Name: "pilot_id", Nullable: true}},
|
||||
FKeys: []ForeignKey{
|
||||
{Name: "licenses_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true, Unique: true},
|
||||
{Name: "licenses_pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "hangars",
|
||||
Columns: []Column{
|
||||
{Name: "id", Nullable: true, Unique: true},
|
||||
{Name: "name", Nullable: true, Unique: true},
|
||||
},
|
||||
Name: "hangars",
|
||||
Columns: []Column{{Name: "id", Nullable: true}, {Name: "name", Nullable: true}},
|
||||
},
|
||||
{
|
||||
Name: "languages",
|
||||
Columns: []Column{
|
||||
{Name: "id", Nullable: true, Unique: true},
|
||||
{Name: "language", Nullable: true, Unique: true},
|
||||
},
|
||||
Name: "languages",
|
||||
Columns: []Column{{Name: "id", Nullable: true}, {Name: "language", Nullable: true}},
|
||||
},
|
||||
{
|
||||
Name: "pilot_languages",
|
||||
IsJoinTable: true,
|
||||
Columns: []Column{
|
||||
{Name: "pilot_id", Nullable: true, Unique: true},
|
||||
{Name: "language_id", Nullable: true, Unique: true},
|
||||
},
|
||||
Columns: []Column{{Name: "pilot_id", Nullable: true}, {Name: "language_id", Nullable: true}},
|
||||
FKeys: []ForeignKey{
|
||||
{Name: "pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true, Unique: true},
|
||||
{Name: "language_id_fk", Column: "language_id", ForeignTable: "languages", ForeignColumn: "id", Nullable: true, Unique: true},
|
||||
{Name: "pilot_id_fk", Column: "pilot_id", ForeignTable: "pilots", ForeignColumn: "id", Nullable: true},
|
||||
{Name: "language_id_fk", Column: "language_id", ForeignTable: "languages", ForeignColumn: "id", Nullable: true},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -215,12 +253,12 @@ func TestToManyRelationshipsNull(t *testing.T) {
|
|||
Table: "pilots",
|
||||
Column: "id",
|
||||
Nullable: true,
|
||||
Unique: true,
|
||||
Unique: false,
|
||||
|
||||
ForeignTable: "jets",
|
||||
ForeignColumn: "pilot_id",
|
||||
ForeignColumnNullable: true,
|
||||
ForeignColumnUnique: true,
|
||||
ForeignColumnUnique: false,
|
||||
|
||||
ToJoinTable: false,
|
||||
},
|
||||
|
@ -228,12 +266,12 @@ func TestToManyRelationshipsNull(t *testing.T) {
|
|||
Table: "pilots",
|
||||
Column: "id",
|
||||
Nullable: true,
|
||||
Unique: true,
|
||||
Unique: false,
|
||||
|
||||
ForeignTable: "licenses",
|
||||
ForeignColumn: "pilot_id",
|
||||
ForeignColumnNullable: true,
|
||||
ForeignColumnUnique: true,
|
||||
ForeignColumnUnique: false,
|
||||
|
||||
ToJoinTable: false,
|
||||
},
|
||||
|
@ -241,29 +279,29 @@ func TestToManyRelationshipsNull(t *testing.T) {
|
|||
Table: "pilots",
|
||||
Column: "id",
|
||||
Nullable: true,
|
||||
Unique: true,
|
||||
Unique: false,
|
||||
|
||||
ForeignTable: "languages",
|
||||
ForeignColumn: "id",
|
||||
ForeignColumnNullable: true,
|
||||
ForeignColumnUnique: true,
|
||||
ForeignColumnUnique: false,
|
||||
|
||||
ToJoinTable: true,
|
||||
JoinTable: "pilot_languages",
|
||||
|
||||
JoinLocalColumn: "pilot_id",
|
||||
JoinLocalColumnNullable: true,
|
||||
JoinLocalColumnUnique: true,
|
||||
JoinLocalColumnUnique: false,
|
||||
|
||||
JoinForeignColumn: "language_id",
|
||||
JoinForeignColumnNullable: true,
|
||||
JoinForeignColumnUnique: true,
|
||||
JoinForeignColumnUnique: false,
|
||||
},
|
||||
}
|
||||
|
||||
for i, v := range relationships {
|
||||
if !reflect.DeepEqual(v, expected[i]) {
|
||||
t.Errorf("[%d] Mismatch between relationships null:\n\n%#v\n\n%#v\n\n", i, v, expected[i])
|
||||
t.Errorf("[%d] Mismatch between relationships:\n\nwant:%#v\n\ngot:%#v\n\n", i, expected[i], v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ type Table struct {
|
|||
|
||||
IsJoinTable bool
|
||||
|
||||
ToOneRelationships []ToOneRelationship
|
||||
ToManyRelationships []ToManyRelationship
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ test:
|
|||
- go install github.com/jstemmer/go-junit-report
|
||||
- echo -e "[postgres]\nhost=\"localhost\"\nport=5432\nuser=\"ubuntu\"\ndbname=\"sqlboiler\"" > sqlboiler.toml
|
||||
- createdb -U ubuntu sqlboiler
|
||||
- psql -U ubuntu sqlboiler < ./testdata/test_schema.sql
|
||||
- psql -U ubuntu sqlboiler < ./testdata/postgres_test_schema.sql
|
||||
- ./sqlboiler postgres
|
||||
override:
|
||||
- go test -v -race ./... > $CIRCLE_ARTIFACTS/gotest.txt
|
||||
|
|
|
@ -143,10 +143,11 @@ func removeDuplicates(dedup []string) []string {
|
|||
|
||||
var defaultTemplateImports = imports{
|
||||
standard: importList{
|
||||
`"fmt"`,
|
||||
`"strings"`,
|
||||
`"bytes"`,
|
||||
`"database/sql"`,
|
||||
`"fmt"`,
|
||||
`"reflect"`,
|
||||
`"strings"`,
|
||||
`"sync"`,
|
||||
`"time"`,
|
||||
},
|
||||
|
@ -177,8 +178,9 @@ var defaultSingletonTemplateImports = map[string]imports{
|
|||
|
||||
var defaultTestTemplateImports = imports{
|
||||
standard: importList{
|
||||
`"testing"`,
|
||||
`"bytes"`,
|
||||
`"reflect"`,
|
||||
`"testing"`,
|
||||
},
|
||||
thirdParty: importList{
|
||||
`"github.com/vattle/sqlboiler/boil"`,
|
||||
|
|
|
@ -190,6 +190,17 @@ func BuildUpsertQueryMySQL(dia Dialect, tableName string, update, whitelist []st
|
|||
buf := strmangle.GetBuffer()
|
||||
defer strmangle.PutBuffer(buf)
|
||||
|
||||
if len(update) == 0 {
|
||||
fmt.Fprintf(
|
||||
buf,
|
||||
"INSERT IGNORE INTO %s (%s) VALUES (%s)",
|
||||
tableName,
|
||||
strings.Join(whitelist, ", "),
|
||||
strmangle.Placeholders(dia.IndexPlaceholders, len(whitelist), 1, 1),
|
||||
)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
fmt.Fprintf(
|
||||
buf,
|
||||
"INSERT INTO %s (%s) VALUES (%s) ON DUPLICATE KEY UPDATE ",
|
||||
|
|
|
@ -49,7 +49,7 @@ var (
|
|||
rgxValidTime = regexp.MustCompile(`[2-9]+`)
|
||||
|
||||
validatedTypes = []string{
|
||||
"inet", "line", "uuid", "interval",
|
||||
"inet", "line", "uuid", "interval", "mediumint",
|
||||
"json", "jsonb", "box", "cidr", "circle",
|
||||
"lseg", "macaddr", "path", "pg_lsn", "point",
|
||||
"polygon", "txid_snapshot", "money", "hstore",
|
||||
|
@ -135,7 +135,7 @@ func Struct(s *Seed, str interface{}, colTypes map[string]string, canBeNull bool
|
|||
// not cause mismatches in the test data comparisons.
|
||||
func randDate(s *Seed) time.Time {
|
||||
t := time.Date(
|
||||
1850+s.nextInt()%160,
|
||||
1972+s.nextInt()%60,
|
||||
time.Month(1+(s.nextInt()%12)),
|
||||
1+(s.nextInt()%25),
|
||||
0,
|
||||
|
@ -221,6 +221,13 @@ func randomizeField(s *Seed, field reflect.Value, fieldType string, canBeNull bo
|
|||
field.Set(reflect.ValueOf(value))
|
||||
return nil
|
||||
}
|
||||
case typeNullInt32:
|
||||
if fieldType == "mediumint" {
|
||||
// 8388607 is the max for 3 byte int
|
||||
value = null.NewInt32(int32(s.nextInt())%8388607, true)
|
||||
field.Set(reflect.ValueOf(value))
|
||||
return nil
|
||||
}
|
||||
case typeNullJSON:
|
||||
value = null.NewJSON([]byte(fmt.Sprintf(`"%s"`, randStr(s, 1))), true)
|
||||
field.Set(reflect.ValueOf(value))
|
||||
|
@ -287,6 +294,13 @@ func randomizeField(s *Seed, field reflect.Value, fieldType string, canBeNull bo
|
|||
field.Set(reflect.ValueOf(value))
|
||||
return nil
|
||||
}
|
||||
case reflect.Int32:
|
||||
if fieldType == "mediumint" {
|
||||
// 8388607 is the max for 3 byte int
|
||||
value = int32(s.nextInt()) % 8388607
|
||||
field.Set(reflect.ValueOf(value))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
switch typ {
|
||||
case typeJSON:
|
||||
|
@ -319,13 +333,15 @@ func randomizeField(s *Seed, field reflect.Value, fieldType string, canBeNull bo
|
|||
// Retrieve the value to be returned
|
||||
} else if kind == reflect.Struct {
|
||||
if isNull {
|
||||
value = getStructNullValue(typ)
|
||||
value = getStructNullValue(s, typ)
|
||||
} else {
|
||||
value = getStructRandValue(s, typ)
|
||||
}
|
||||
} else {
|
||||
if isNull {
|
||||
value = getVariableZeroValue(kind)
|
||||
// only get zero values for non byte slices
|
||||
// to stop mysql from being a jerk
|
||||
if isNull && kind != reflect.Slice {
|
||||
value = getVariableZeroValue(s, kind)
|
||||
} else {
|
||||
value = getVariableRandValue(s, kind, typ)
|
||||
}
|
||||
|
@ -404,10 +420,11 @@ func getArrayRandValue(s *Seed, typ reflect.Type, fieldType string) interface{}
|
|||
}
|
||||
|
||||
// getStructNullValue for the matching type.
|
||||
func getStructNullValue(typ reflect.Type) interface{} {
|
||||
func getStructNullValue(s *Seed, typ reflect.Type) interface{} {
|
||||
switch typ {
|
||||
case typeTime:
|
||||
return time.Time{}
|
||||
// MySQL does not support 0 value time.Time, so use rand
|
||||
return randDate(s)
|
||||
case typeNullBool:
|
||||
return null.NewBool(false, false)
|
||||
case typeNullString:
|
||||
|
@ -463,7 +480,7 @@ func getStructRandValue(s *Seed, typ reflect.Type) interface{} {
|
|||
case typeNullFloat64:
|
||||
return null.NewFloat64(float64(s.nextInt()%10)/10.0+float64(s.nextInt()%10), true)
|
||||
case typeNullInt:
|
||||
return null.NewInt(s.nextInt(), true)
|
||||
return null.NewInt(int(int32(s.nextInt())), true)
|
||||
case typeNullInt8:
|
||||
return null.NewInt8(int8(s.nextInt()), true)
|
||||
case typeNullInt16:
|
||||
|
@ -483,14 +500,14 @@ func getStructRandValue(s *Seed, typ reflect.Type) interface{} {
|
|||
case typeNullUint64:
|
||||
return null.NewUint64(uint64(s.nextInt()), true)
|
||||
case typeNullBytes:
|
||||
return null.NewBytes(randByteSlice(s, 16), true)
|
||||
return null.NewBytes(randByteSlice(s, 1), true)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getVariableZeroValue for the matching type.
|
||||
func getVariableZeroValue(kind reflect.Kind) interface{} {
|
||||
func getVariableZeroValue(s *Seed, kind reflect.Kind) interface{} {
|
||||
switch kind {
|
||||
case reflect.Float32:
|
||||
return float32(0)
|
||||
|
@ -521,7 +538,7 @@ func getVariableZeroValue(kind reflect.Kind) interface{} {
|
|||
case reflect.String:
|
||||
return ""
|
||||
case reflect.Slice:
|
||||
return []byte(nil)
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -565,7 +582,7 @@ func getVariableRandValue(s *Seed, kind reflect.Kind, typ reflect.Type) interfac
|
|||
if sliceVal.Kind() != reflect.Uint8 {
|
||||
return errors.Errorf("unsupported slice type: %T, was expecting byte slice.", typ.String())
|
||||
}
|
||||
return randByteSlice(s, 5+s.nextInt()%20)
|
||||
return randByteSlice(s, 1)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -166,11 +166,10 @@ var templateFunctions = template.FuncMap{
|
|||
// Database related mangling
|
||||
"whereClause": strmangle.WhereClause,
|
||||
|
||||
// Text helpers
|
||||
"textsFromForeignKey": textsFromForeignKey,
|
||||
"textsFromOneToOneRelationship": textsFromOneToOneRelationship,
|
||||
"textsFromRelationship": textsFromRelationship,
|
||||
"preserveDot": preserveDot,
|
||||
// Relationship text helpers
|
||||
"txtsFromFKey": txtsFromFKey,
|
||||
"txtsFromOneToOne": txtsFromOneToOne,
|
||||
"txtsFromToMany": txtsFromToMany,
|
||||
|
||||
// dbdrivers ops
|
||||
"filterColumnsByDefault": bdb.FilterColumnsByDefault,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
{{- define "relationship_to_one_struct_helper" -}}
|
||||
{{.Function.Name}} *{{.ForeignTable.NameGo}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $dot := . -}}
|
||||
|
@ -23,17 +22,19 @@ type {{$modelName}} struct {
|
|||
// {{$modelNameCamel}}R is where relationships are stored.
|
||||
type {{$modelNameCamel}}R struct {
|
||||
{{range .Table.FKeys -}}
|
||||
{{- $rel := textsFromForeignKey $dot.PkgName $dot.Tables $dot.Table . -}}
|
||||
{{- template "relationship_to_one_struct_helper" $rel}}
|
||||
{{- $txt := txtsFromFKey $dot.Tables $dot.Table . -}}
|
||||
{{$txt.Function.Name}} *{{$txt.ForeignTable.NameGo}}
|
||||
{{end -}}
|
||||
{{- range .Table.ToManyRelationships -}}
|
||||
{{- if (and .ForeignColumnUnique (not .ToJoinTable)) -}}
|
||||
{{- template "relationship_to_one_struct_helper" (textsFromOneToOneRelationship $dot.PkgName $dot.Tables $dot.Table .)}}
|
||||
{{else -}}
|
||||
{{- $rel := textsFromRelationship $dot.Tables $dot.Table . -}}
|
||||
{{$rel.Function.Name}} {{$rel.ForeignTable.Slice}}
|
||||
{{end -}}{{/* if ForeignColumnUnique */}}
|
||||
{{- end -}}{{/* range tomany */}}
|
||||
|
||||
{{range .Table.ToOneRelationships -}}
|
||||
{{- $txt := txtsFromOneToOne $dot.Tables $dot.Table . -}}
|
||||
{{$txt.Function.Name}} *{{$txt.ForeignTable.NameGo}}
|
||||
{{end -}}
|
||||
|
||||
{{range .Table.ToManyRelationships -}}
|
||||
{{- $txt := txtsFromToMany $dot.Tables $dot.Table . -}}
|
||||
{{$txt.Function.Name}} {{$txt.ForeignTable.Slice}}
|
||||
{{end -}}{{/* range tomany */}}
|
||||
}
|
||||
|
||||
// {{$modelNameCamel}}L is where Load methods for each relationship are stored.
|
||||
|
|
|
@ -36,6 +36,10 @@ var (
|
|||
{{$varNameSingular}}UpsertCache = make(map[string]insertCache)
|
||||
)
|
||||
|
||||
// Force time package dependency for automated UpdatedAt/CreatedAt.
|
||||
var _ = time.Second
|
||||
var (
|
||||
// Force time package dependency for automated UpdatedAt/CreatedAt.
|
||||
_ = time.Second
|
||||
// Force bytes in case of primary key column that uses []byte (for relationship compares)
|
||||
_ = bytes.MinRead
|
||||
)
|
||||
{{end -}}
|
||||
|
|
|
@ -1,34 +1,26 @@
|
|||
{{- define "relationship_to_one_helper" -}}
|
||||
{{- $dot := .Dot -}}{{/* .Dot holds the root templateData struct, passed in through preserveDot */}}
|
||||
{{- with .Rel -}}{{/* Rel holds the text helper data, passed in through preserveDot */}}
|
||||
{{- $varNameSingular := .ForeignKey.ForeignTable | singular | camelCase -}}
|
||||
// {{.Function.Name}}G pointed to by the foreign key.
|
||||
func ({{.Function.Receiver}} *{{.LocalTable.NameGo}}) {{.Function.Name}}G(mods ...qm.QueryMod) {{$varNameSingular}}Query {
|
||||
return {{.Function.Receiver}}.{{.Function.Name}}(boil.GetDB(), mods...)
|
||||
}
|
||||
|
||||
// {{.Function.Name}} pointed to by the foreign key.
|
||||
func ({{.Function.Receiver}} *{{.LocalTable.NameGo}}) {{.Function.Name}}(exec boil.Executor, mods ...qm.QueryMod) ({{$varNameSingular}}Query) {
|
||||
queryMods := []qm.QueryMod{
|
||||
qm.Where("{{.ForeignTable.ColumnName}}={{if $dot.Dialect.IndexPlaceholders}}$1{{else}}?{{end}}", {{.Function.Receiver}}.{{.LocalTable.ColumnNameGo}}),
|
||||
}
|
||||
|
||||
queryMods = append(queryMods, mods...)
|
||||
|
||||
query := {{.ForeignTable.NamePluralGo}}(exec, queryMods...)
|
||||
queries.SetFrom(query.Query, "{{.ForeignTable.Name | $dot.SchemaTable}}")
|
||||
|
||||
return query
|
||||
}
|
||||
{{- end -}}{{/* end with */}}
|
||||
{{end -}}{{/* end define */}}
|
||||
|
||||
{{- /* Begin execution of template for one-to-one relationship */ -}}
|
||||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.FKeys -}}
|
||||
{{- $txt := textsFromForeignKey $dot.PkgName $dot.Tables $dot.Table . -}}
|
||||
{{- template "relationship_to_one_helper" (preserveDot $dot $txt) -}}
|
||||
{{- $txt := txtsFromFKey $dot.Tables $dot.Table . -}}
|
||||
{{- $varNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
// {{$txt.Function.Name}}G pointed to by the foreign key.
|
||||
func ({{$txt.Function.Receiver}} *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}G(mods ...qm.QueryMod) {{$varNameSingular}}Query {
|
||||
return {{$txt.Function.Receiver}}.{{$txt.Function.Name}}(boil.GetDB(), mods...)
|
||||
}
|
||||
|
||||
// {{$txt.Function.Name}} pointed to by the foreign key.
|
||||
func ({{$txt.Function.Receiver}} *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}(exec boil.Executor, mods ...qm.QueryMod) ({{$varNameSingular}}Query) {
|
||||
queryMods := []qm.QueryMod{
|
||||
qm.Where("{{$txt.ForeignTable.ColumnName}}={{if $dot.Dialect.IndexPlaceholders}}$1{{else}}?{{end}}", {{$txt.Function.Receiver}}.{{$txt.LocalTable.ColumnNameGo}}),
|
||||
}
|
||||
|
||||
queryMods = append(queryMods, mods...)
|
||||
|
||||
query := {{$txt.ForeignTable.NamePluralGo}}(exec, queryMods...)
|
||||
queries.SetFrom(query.Query, "{{$txt.ForeignTable.Name | $dot.SchemaTable}}")
|
||||
|
||||
return query
|
||||
}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
|
26
templates/05_relationship_one_to_one.tpl
Normal file
26
templates/05_relationship_one_to_one.tpl
Normal file
|
@ -0,0 +1,26 @@
|
|||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.ToOneRelationships -}}
|
||||
{{- $txt := txtsFromOneToOne $dot.Tables $dot.Table . -}}
|
||||
{{- $varNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
// {{$txt.Function.Name}}G pointed to by the foreign key.
|
||||
func ({{$txt.Function.Receiver}} *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}G(mods ...qm.QueryMod) {{$varNameSingular}}Query {
|
||||
return {{$txt.Function.Receiver}}.{{$txt.Function.Name}}(boil.GetDB(), mods...)
|
||||
}
|
||||
|
||||
// {{$txt.Function.Name}} pointed to by the foreign key.
|
||||
func ({{$txt.Function.Receiver}} *{{$txt.LocalTable.NameGo}}) {{$txt.Function.Name}}(exec boil.Executor, mods ...qm.QueryMod) ({{$varNameSingular}}Query) {
|
||||
queryMods := []qm.QueryMod{
|
||||
qm.Where("{{$txt.ForeignTable.ColumnName}}={{if $dot.Dialect.IndexPlaceholders}}$1{{else}}?{{end}}", {{$txt.Function.Receiver}}.{{$txt.LocalTable.ColumnNameGo}}),
|
||||
}
|
||||
|
||||
queryMods = append(queryMods, mods...)
|
||||
|
||||
query := {{$txt.ForeignTable.NamePluralGo}}(exec, queryMods...)
|
||||
queries.SetFrom(query.Query, "{{$txt.ForeignTable.Name | $dot.SchemaTable}}")
|
||||
|
||||
return query
|
||||
}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
|
@ -1,18 +1,11 @@
|
|||
{{- /* Begin execution of template for many-to-one or many-to-many relationship helper */ -}}
|
||||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- $table := .Table -}}
|
||||
{{- range .Table.ToManyRelationships -}}
|
||||
{{- $varNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- if (and .ForeignColumnUnique (not .ToJoinTable)) -}}
|
||||
{{- /* Begin execution of template for many-to-one relationship. */ -}}
|
||||
{{- $txt := textsFromOneToOneRelationship $dot.PkgName $dot.Tables $table . -}}
|
||||
{{- template "relationship_to_one_helper" (preserveDot $dot $txt) -}}
|
||||
{{- else -}}
|
||||
{{- /* Begin execution of template for many-to-many relationship. */ -}}
|
||||
{{- $rel := textsFromRelationship $dot.Tables $table . -}}
|
||||
{{- $schemaForeignTable := .ForeignTable | $dot.SchemaTable -}}
|
||||
{{- $rel := txtsFromToMany $dot.Tables $table . -}}
|
||||
{{- $schemaForeignTable := .ForeignTable | $dot.SchemaTable -}}
|
||||
// {{$rel.Function.Name}}G retrieves all the {{$rel.LocalTable.NameSingular}}'s {{$rel.ForeignTable.NameHumanReadable}}
|
||||
{{- if not (eq $rel.Function.Name $rel.ForeignTable.NamePluralGo)}} via {{.ForeignColumn}} column{{- end}}.
|
||||
func ({{$rel.Function.Receiver}} *{{$rel.LocalTable.NameGo}}) {{$rel.Function.Name}}G(mods ...qm.QueryMod) {{$varNameSingular}}Query {
|
||||
|
@ -46,6 +39,5 @@ func ({{$rel.Function.Receiver}} *{{$rel.LocalTable.NameGo}}) {{$rel.Function.Na
|
|||
return query
|
||||
}
|
||||
|
||||
{{end -}}{{- /* if unique foreign key */ -}}
|
||||
{{- end -}}{{- /* range relationships */ -}}
|
||||
{{end -}}{{- /* range relationships */ -}}
|
||||
{{- end -}}{{- /* if isJoinTable */ -}}
|
|
@ -1,93 +0,0 @@
|
|||
{{- define "relationship_to_one_eager_helper" -}}
|
||||
{{- $dot := .Dot -}}{{/* .Dot holds the root templateData struct, passed in through preserveDot */}}
|
||||
{{- $varNameSingular := $dot.Table.Name | singular | camelCase -}}
|
||||
{{- with .Rel -}}
|
||||
{{- $arg := printf "maybe%s" .LocalTable.NameGo -}}
|
||||
{{- $slice := printf "%sSlice" .LocalTable.NameGo -}}
|
||||
// Load{{.Function.Name}} allows an eager lookup of values, cached into the
|
||||
// loaded structs of the objects.
|
||||
func ({{$varNameSingular}}L) Load{{.Function.Name}}(e boil.Executor, singular bool, {{$arg}} interface{}) error {
|
||||
var slice []*{{.LocalTable.NameGo}}
|
||||
var object *{{.LocalTable.NameGo}}
|
||||
|
||||
count := 1
|
||||
if singular {
|
||||
object = {{$arg}}.(*{{.LocalTable.NameGo}})
|
||||
} else {
|
||||
slice = *{{$arg}}.(*{{$slice}})
|
||||
count = len(slice)
|
||||
}
|
||||
|
||||
args := make([]interface{}, count)
|
||||
if singular {
|
||||
args[0] = object.{{.LocalTable.ColumnNameGo}}
|
||||
} else {
|
||||
for i, obj := range slice {
|
||||
args[i] = obj.{{.LocalTable.ColumnNameGo}}
|
||||
}
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(
|
||||
"select * from {{.ForeignKey.ForeignTable | $dot.SchemaTable}} where {{.ForeignKey.ForeignColumn | $dot.Quotes}} in (%s)",
|
||||
strmangle.Placeholders(dialect.IndexPlaceholders, count, 1, 1),
|
||||
)
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintf(boil.DebugWriter, "%s\n%v\n", query, args)
|
||||
}
|
||||
|
||||
results, err := e.Query(query, args...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to eager load {{.ForeignTable.NameGo}}")
|
||||
}
|
||||
defer results.Close()
|
||||
|
||||
var resultSlice []*{{.ForeignTable.NameGo}}
|
||||
if err = queries.Bind(results, &resultSlice); err != nil {
|
||||
return errors.Wrap(err, "failed to bind eager loaded slice {{.ForeignTable.NameGo}}")
|
||||
}
|
||||
|
||||
{{if not $dot.NoHooks -}}
|
||||
if len({{.ForeignTable.Name | singular | camelCase}}AfterSelectHooks) != 0 {
|
||||
for _, obj := range resultSlice {
|
||||
if err := obj.doAfterSelectHooks(e); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
if singular && len(resultSlice) != 0 {
|
||||
if object.R == nil {
|
||||
object.R = &{{$varNameSingular}}R{}
|
||||
}
|
||||
object.R.{{.Function.Name}} = resultSlice[0]
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, foreign := range resultSlice {
|
||||
for _, local := range slice {
|
||||
if local.{{.Function.LocalAssignment}} == foreign.{{.Function.ForeignAssignment}} {
|
||||
if local.R == nil {
|
||||
local.R = &{{$varNameSingular}}R{}
|
||||
}
|
||||
local.R.{{.Function.Name}} = foreign
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
{{- end -}}{{- /* end with */ -}}
|
||||
{{end -}}{{- /* end define */ -}}
|
||||
|
||||
{{- /* Begin execution of template for one-to-one eager load */ -}}
|
||||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.FKeys -}}
|
||||
{{- $txt := textsFromForeignKey $dot.PkgName $dot.Tables $dot.Table . -}}
|
||||
{{- template "relationship_to_one_eager_helper" (preserveDot $dot $txt) -}}
|
||||
{{- end -}}
|
||||
{{end}}
|
89
templates/07_relationship_to_one_eager.tpl
Normal file
89
templates/07_relationship_to_one_eager.tpl
Normal file
|
@ -0,0 +1,89 @@
|
|||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.FKeys -}}
|
||||
{{- $txt := txtsFromFKey $dot.Tables $dot.Table . -}}
|
||||
{{- $varNameSingular := $dot.Table.Name | singular | camelCase -}}
|
||||
{{- $arg := printf "maybe%s" $txt.LocalTable.NameGo -}}
|
||||
{{- $slice := printf "%sSlice" $txt.LocalTable.NameGo}}
|
||||
// Load{{$txt.Function.Name}} allows an eager lookup of values, cached into the
|
||||
// loaded structs of the objects.
|
||||
func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singular bool, {{$arg}} interface{}) error {
|
||||
var slice []*{{$txt.LocalTable.NameGo}}
|
||||
var object *{{$txt.LocalTable.NameGo}}
|
||||
|
||||
count := 1
|
||||
if singular {
|
||||
object = {{$arg}}.(*{{$txt.LocalTable.NameGo}})
|
||||
} else {
|
||||
slice = *{{$arg}}.(*{{$slice}})
|
||||
count = len(slice)
|
||||
}
|
||||
|
||||
args := make([]interface{}, count)
|
||||
if singular {
|
||||
args[0] = object.{{$txt.LocalTable.ColumnNameGo}}
|
||||
} else {
|
||||
for i, obj := range slice {
|
||||
args[i] = obj.{{$txt.LocalTable.ColumnNameGo}}
|
||||
}
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(
|
||||
"select * from {{.ForeignTable | $dot.SchemaTable}} where {{.ForeignColumn | $dot.Quotes}} in (%s)",
|
||||
strmangle.Placeholders(dialect.IndexPlaceholders, count, 1, 1),
|
||||
)
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintf(boil.DebugWriter, "%s\n%v\n", query, args)
|
||||
}
|
||||
|
||||
results, err := e.Query(query, args...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to eager load {{$txt.ForeignTable.NameGo}}")
|
||||
}
|
||||
defer results.Close()
|
||||
|
||||
var resultSlice []*{{$txt.ForeignTable.NameGo}}
|
||||
if err = queries.Bind(results, &resultSlice); err != nil {
|
||||
return errors.Wrap(err, "failed to bind eager loaded slice {{$txt.ForeignTable.NameGo}}")
|
||||
}
|
||||
|
||||
{{if not $dot.NoHooks -}}
|
||||
if len({{$txt.ForeignTable.Name | singular | camelCase}}AfterSelectHooks) != 0 {
|
||||
for _, obj := range resultSlice {
|
||||
if err := obj.doAfterSelectHooks(e); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
if singular && len(resultSlice) != 0 {
|
||||
if object.R == nil {
|
||||
object.R = &{{$varNameSingular}}R{}
|
||||
}
|
||||
object.R.{{$txt.Function.Name}} = resultSlice[0]
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, foreign := range resultSlice {
|
||||
for _, local := range slice {
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 == bytes.Compare(local.{{$txt.Function.LocalAssignment}}, foreign.{{$txt.Function.ForeignAssignment}}) {
|
||||
{{else -}}
|
||||
if local.{{$txt.Function.LocalAssignment}} == foreign.{{$txt.Function.ForeignAssignment}} {
|
||||
{{end -}}
|
||||
if local.R == nil {
|
||||
local.R = &{{$varNameSingular}}R{}
|
||||
}
|
||||
local.R.{{$txt.Function.Name}} = foreign
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
{{end -}}{{/* range */}}
|
||||
{{end}}{{/* join table */}}
|
89
templates/08_relationship_one_to_one_eager.tpl
Normal file
89
templates/08_relationship_one_to_one_eager.tpl
Normal file
|
@ -0,0 +1,89 @@
|
|||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.ToOneRelationships -}}
|
||||
{{- $txt := txtsFromOneToOne $dot.Tables $dot.Table . -}}
|
||||
{{- $varNameSingular := $dot.Table.Name | singular | camelCase -}}
|
||||
{{- $arg := printf "maybe%s" $txt.LocalTable.NameGo -}}
|
||||
{{- $slice := printf "%sSlice" $txt.LocalTable.NameGo}}
|
||||
// Load{{$txt.Function.Name}} allows an eager lookup of values, cached into the
|
||||
// loaded structs of the objects.
|
||||
func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singular bool, {{$arg}} interface{}) error {
|
||||
var slice []*{{$txt.LocalTable.NameGo}}
|
||||
var object *{{$txt.LocalTable.NameGo}}
|
||||
|
||||
count := 1
|
||||
if singular {
|
||||
object = {{$arg}}.(*{{$txt.LocalTable.NameGo}})
|
||||
} else {
|
||||
slice = *{{$arg}}.(*{{$slice}})
|
||||
count = len(slice)
|
||||
}
|
||||
|
||||
args := make([]interface{}, count)
|
||||
if singular {
|
||||
args[0] = object.{{$txt.LocalTable.ColumnNameGo}}
|
||||
} else {
|
||||
for i, obj := range slice {
|
||||
args[i] = obj.{{$txt.LocalTable.ColumnNameGo}}
|
||||
}
|
||||
}
|
||||
|
||||
query := fmt.Sprintf(
|
||||
"select * from {{.ForeignTable | $dot.SchemaTable}} where {{.ForeignColumn | $dot.Quotes}} in (%s)",
|
||||
strmangle.Placeholders(dialect.IndexPlaceholders, count, 1, 1),
|
||||
)
|
||||
|
||||
if boil.DebugMode {
|
||||
fmt.Fprintf(boil.DebugWriter, "%s\n%v\n", query, args)
|
||||
}
|
||||
|
||||
results, err := e.Query(query, args...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to eager load {{$txt.ForeignTable.NameGo}}")
|
||||
}
|
||||
defer results.Close()
|
||||
|
||||
var resultSlice []*{{$txt.ForeignTable.NameGo}}
|
||||
if err = queries.Bind(results, &resultSlice); err != nil {
|
||||
return errors.Wrap(err, "failed to bind eager loaded slice {{$txt.ForeignTable.NameGo}}")
|
||||
}
|
||||
|
||||
{{if not $dot.NoHooks -}}
|
||||
if len({{$txt.ForeignTable.Name | singular | camelCase}}AfterSelectHooks) != 0 {
|
||||
for _, obj := range resultSlice {
|
||||
if err := obj.doAfterSelectHooks(e); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
if singular && len(resultSlice) != 0 {
|
||||
if object.R == nil {
|
||||
object.R = &{{$varNameSingular}}R{}
|
||||
}
|
||||
object.R.{{$txt.Function.Name}} = resultSlice[0]
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, foreign := range resultSlice {
|
||||
for _, local := range slice {
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 == bytes.Compare(local.{{$txt.Function.LocalAssignment}}, foreign.{{$txt.Function.ForeignAssignment}}) {
|
||||
{{else -}}
|
||||
if local.{{$txt.Function.LocalAssignment}} == foreign.{{$txt.Function.ForeignAssignment}} {
|
||||
{{end -}}
|
||||
if local.R == nil {
|
||||
local.R = &{{$varNameSingular}}R{}
|
||||
}
|
||||
local.R.{{$txt.Function.Name}} = foreign
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
{{end -}}{{/* range */}}
|
||||
{{end}}{{/* join table */}}
|
|
@ -1,105 +0,0 @@
|
|||
{{- define "relationship_to_one_setops_helper" -}}
|
||||
{{- $tmplData := .Dot -}}{{/* .Dot holds the root templateData struct, passed in through preserveDot */}}
|
||||
{{- with .Rel -}}
|
||||
{{- $varNameSingular := .ForeignKey.ForeignTable | singular | camelCase -}}
|
||||
{{- $localNameSingular := .ForeignKey.Table | singular | camelCase}}
|
||||
// Set{{.Function.Name}} of the {{.ForeignKey.Table | singular}} to the related item.
|
||||
// Sets {{.Function.Receiver}}.R.{{.Function.Name}} to related.
|
||||
// Adds {{.Function.Receiver}} to related.R.{{.Function.ForeignName}}.
|
||||
func ({{.Function.Receiver}} *{{.LocalTable.NameGo}}) Set{{.Function.Name}}(exec boil.Executor, insert bool, related *{{.ForeignTable.NameGo}}) error {
|
||||
var err error
|
||||
if insert {
|
||||
if err = related.Insert(exec); err != nil {
|
||||
return errors.Wrap(err, "failed to insert into foreign table")
|
||||
}
|
||||
}
|
||||
|
||||
oldVal := {{.Function.Receiver}}.{{.LocalTable.ColumnNameGo}}
|
||||
{{.Function.Receiver}}.{{.Function.LocalAssignment}} = related.{{.Function.ForeignAssignment}}
|
||||
if err = {{.Function.Receiver}}.Update(exec, "{{.ForeignKey.Column}}"); err != nil {
|
||||
{{.Function.Receiver}}.{{.LocalTable.ColumnNameGo}} = oldVal
|
||||
return errors.Wrap(err, "failed to update local table")
|
||||
}
|
||||
|
||||
if {{.Function.Receiver}}.R == nil {
|
||||
{{.Function.Receiver}}.R = &{{$localNameSingular}}R{
|
||||
{{.Function.Name}}: related,
|
||||
}
|
||||
} else {
|
||||
{{.Function.Receiver}}.R.{{.Function.Name}} = related
|
||||
}
|
||||
|
||||
{{if (or .ForeignKey.Unique .Function.OneToOne) -}}
|
||||
if related.R == nil {
|
||||
related.R = &{{$varNameSingular}}R{
|
||||
{{.Function.ForeignName}}: {{.Function.Receiver}},
|
||||
}
|
||||
} else {
|
||||
related.R.{{.Function.ForeignName}} = {{.Function.Receiver}}
|
||||
}
|
||||
{{else -}}
|
||||
if related.R == nil {
|
||||
related.R = &{{$varNameSingular}}R{
|
||||
{{.Function.ForeignName}}: {{.LocalTable.NameGo}}Slice{{"{"}}{{.Function.Receiver}}{{"}"}},
|
||||
}
|
||||
} else {
|
||||
related.R.{{.Function.ForeignName}} = append(related.R.{{.Function.ForeignName}}, {{.Function.Receiver}})
|
||||
}
|
||||
{{end -}}
|
||||
|
||||
{{if .ForeignKey.Nullable}}
|
||||
{{.Function.Receiver}}.{{.LocalTable.ColumnNameGo}}.Valid = true
|
||||
{{end -}}
|
||||
return nil
|
||||
}
|
||||
|
||||
{{- if .ForeignKey.Nullable}}
|
||||
// Remove{{.Function.Name}} relationship.
|
||||
// Sets {{.Function.Receiver}}.R.{{.Function.Name}} to nil.
|
||||
// Removes {{.Function.Receiver}} from all passed in related items' relationships struct (Optional).
|
||||
func ({{.Function.Receiver}} *{{.LocalTable.NameGo}}) Remove{{.Function.Name}}(exec boil.Executor, related *{{.ForeignTable.NameGo}}) error {
|
||||
var err error
|
||||
|
||||
{{.Function.Receiver}}.{{.LocalTable.ColumnNameGo}}.Valid = false
|
||||
if err = {{.Function.Receiver}}.Update(exec, "{{.ForeignKey.Column}}"); err != nil {
|
||||
{{.Function.Receiver}}.{{.LocalTable.ColumnNameGo}}.Valid = true
|
||||
return errors.Wrap(err, "failed to update local table")
|
||||
}
|
||||
|
||||
{{.Function.Receiver}}.R.{{.Function.Name}} = nil
|
||||
if related == nil || related.R == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
{{if .ForeignKey.Unique -}}
|
||||
related.R.{{.Function.ForeignName}} = nil
|
||||
{{else -}}
|
||||
for i, ri := range related.R.{{.Function.ForeignName}} {
|
||||
if {{.Function.Receiver}}.{{.Function.LocalAssignment}} != ri.{{.Function.LocalAssignment}} {
|
||||
continue
|
||||
}
|
||||
|
||||
ln := len(related.R.{{.Function.ForeignName}})
|
||||
if ln > 1 && i < ln-1 {
|
||||
related.R.{{.Function.ForeignName}}[i] = related.R.{{.Function.ForeignName}}[ln-1]
|
||||
}
|
||||
related.R.{{.Function.ForeignName}} = related.R.{{.Function.ForeignName}}[:ln-1]
|
||||
break
|
||||
}
|
||||
{{end -}}
|
||||
|
||||
return nil
|
||||
}
|
||||
{{- end -}}{{/* if foreignkey nullable */}}
|
||||
{{end -}}{{/* end with */}}
|
||||
{{- end -}}{{/* end define */}}
|
||||
|
||||
{{- /* Begin execution of template for one-to-one setops */ -}}
|
||||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.FKeys -}}
|
||||
{{- $txt := textsFromForeignKey $dot.PkgName $dot.Tables $dot.Table . -}}
|
||||
{{- template "relationship_to_one_setops_helper" (preserveDot $dot $txt) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
|
@ -3,17 +3,11 @@
|
|||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.ToManyRelationships -}}
|
||||
{{- if (and .ForeignColumnUnique (not .ToJoinTable)) -}}
|
||||
{{- /* Begin execution of template for many-to-one eager load */ -}}
|
||||
{{- $txt := textsFromOneToOneRelationship $dot.PkgName $dot.Tables $dot.Table . -}}
|
||||
{{- template "relationship_to_one_eager_helper" (preserveDot $dot $txt) -}}
|
||||
{{- else -}}
|
||||
{{- /* Begin execution of template for many-to-many eager load */ -}}
|
||||
{{- $varNameSingular := $dot.Table.Name | singular | camelCase -}}
|
||||
{{- $txt := textsFromRelationship $dot.Tables $dot.Table . -}}
|
||||
{{- $arg := printf "maybe%s" $txt.LocalTable.NameGo -}}
|
||||
{{- $slice := printf "%sSlice" $txt.LocalTable.NameGo -}}
|
||||
{{- $schemaForeignTable := .ForeignTable | $dot.SchemaTable -}}
|
||||
{{- $varNameSingular := $dot.Table.Name | singular | camelCase -}}
|
||||
{{- $txt := txtsFromToMany $dot.Tables $dot.Table . -}}
|
||||
{{- $arg := printf "maybe%s" $txt.LocalTable.NameGo -}}
|
||||
{{- $slice := printf "%sSlice" $txt.LocalTable.NameGo -}}
|
||||
{{- $schemaForeignTable := .ForeignTable | $dot.SchemaTable}}
|
||||
// Load{{$txt.Function.Name}} allows an eager lookup of values, cached into the
|
||||
// loaded structs of the objects.
|
||||
func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singular bool, {{$arg}} interface{}) error {
|
||||
|
@ -110,7 +104,11 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula
|
|||
for i, foreign := range resultSlice {
|
||||
localJoinCol := localJoinCols[i]
|
||||
for _, local := range slice {
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 == bytes.Compare(local.{{$txt.Function.LocalAssignment}}, localJoinCol) {
|
||||
{{else -}}
|
||||
if local.{{$txt.Function.LocalAssignment}} == localJoinCol {
|
||||
{{end -}}
|
||||
if local.R == nil {
|
||||
local.R = &{{$varNameSingular}}R{}
|
||||
}
|
||||
|
@ -122,7 +120,11 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula
|
|||
{{else -}}
|
||||
for _, foreign := range resultSlice {
|
||||
for _, local := range slice {
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 == bytes.Compare(local.{{$txt.Function.LocalAssignment}}, foreign.{{$txt.Function.ForeignAssignment}}) {
|
||||
{{else -}}
|
||||
if local.{{$txt.Function.LocalAssignment}} == foreign.{{$txt.Function.ForeignAssignment}} {
|
||||
{{end -}}
|
||||
if local.R == nil {
|
||||
local.R = &{{$varNameSingular}}R{}
|
||||
}
|
||||
|
@ -136,6 +138,5 @@ func ({{$varNameSingular}}L) Load{{$txt.Function.Name}}(e boil.Executor, singula
|
|||
return nil
|
||||
}
|
||||
|
||||
{{end -}}{{/* if ForeignColumnUnique */}}
|
||||
{{- end -}}{{/* range tomany */}}
|
||||
{{end -}}{{/* range tomany */}}
|
||||
{{- end -}}{{/* if IsJoinTable */}}
|
105
templates/10_relationship_to_one_setops.tpl
Normal file
105
templates/10_relationship_to_one_setops.tpl
Normal file
|
@ -0,0 +1,105 @@
|
|||
{{- /* Begin execution of template for one-to-one setops */ -}}
|
||||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.FKeys -}}
|
||||
{{- $txt := txtsFromFKey $dot.Tables $dot.Table . -}}
|
||||
{{- $varNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- $localNameSingular := .Table | singular | camelCase}}
|
||||
// Set{{$txt.Function.Name}} of the {{.Table | singular}} to the related item.
|
||||
// Sets {{$txt.Function.Receiver}}.R.{{$txt.Function.Name}} to related.
|
||||
// Adds {{$txt.Function.Receiver}} to related.R.{{$txt.Function.ForeignName}}.
|
||||
func ({{$txt.Function.Receiver}} *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executor, insert bool, related *{{$txt.ForeignTable.NameGo}}) error {
|
||||
var err error
|
||||
if insert {
|
||||
if err = related.Insert(exec); err != nil {
|
||||
return errors.Wrap(err, "failed to insert into foreign table")
|
||||
}
|
||||
}
|
||||
|
||||
oldVal := {{$txt.Function.Receiver}}.{{$txt.Function.LocalAssignment}}
|
||||
{{$txt.Function.Receiver}}.{{$txt.Function.LocalAssignment}} = related.{{$txt.Function.ForeignAssignment}}
|
||||
{{if .Nullable -}}
|
||||
{{$txt.Function.Receiver}}.{{$txt.LocalTable.ColumnNameGo}}.Valid = true
|
||||
{{- end}}
|
||||
if err = {{$txt.Function.Receiver}}.Update(exec, "{{.Column}}"); err != nil {
|
||||
{{$txt.Function.Receiver}}.{{$txt.Function.LocalAssignment}} = oldVal
|
||||
{{if .Nullable -}}
|
||||
{{$txt.Function.Receiver}}.{{$txt.LocalTable.ColumnNameGo}}.Valid = false
|
||||
{{- end}}
|
||||
return errors.Wrap(err, "failed to update local table")
|
||||
}
|
||||
|
||||
if {{$txt.Function.Receiver}}.R == nil {
|
||||
{{$txt.Function.Receiver}}.R = &{{$localNameSingular}}R{
|
||||
{{$txt.Function.Name}}: related,
|
||||
}
|
||||
} else {
|
||||
{{$txt.Function.Receiver}}.R.{{$txt.Function.Name}} = related
|
||||
}
|
||||
|
||||
{{if .Unique -}}
|
||||
if related.R == nil {
|
||||
related.R = &{{$varNameSingular}}R{
|
||||
{{$txt.Function.ForeignName}}: {{$txt.Function.Receiver}},
|
||||
}
|
||||
} else {
|
||||
related.R.{{$txt.Function.ForeignName}} = {{$txt.Function.Receiver}}
|
||||
}
|
||||
{{else -}}
|
||||
if related.R == nil {
|
||||
related.R = &{{$varNameSingular}}R{
|
||||
{{$txt.Function.ForeignName}}: {{$txt.LocalTable.NameGo}}Slice{{"{"}}{{$txt.Function.Receiver}}{{"}"}},
|
||||
}
|
||||
} else {
|
||||
related.R.{{$txt.Function.ForeignName}} = append(related.R.{{$txt.Function.ForeignName}}, {{$txt.Function.Receiver}})
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
{{- if .Nullable}}
|
||||
// Remove{{$txt.Function.Name}} relationship.
|
||||
// Sets {{$txt.Function.Receiver}}.R.{{$txt.Function.Name}} to nil.
|
||||
// Removes {{$txt.Function.Receiver}} from all passed in related items' relationships struct (Optional).
|
||||
func ({{$txt.Function.Receiver}} *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}(exec boil.Executor, related *{{$txt.ForeignTable.NameGo}}) error {
|
||||
var err error
|
||||
|
||||
{{$txt.Function.Receiver}}.{{$txt.LocalTable.ColumnNameGo}}.Valid = false
|
||||
if err = {{$txt.Function.Receiver}}.Update(exec, "{{.Column}}"); err != nil {
|
||||
{{$txt.Function.Receiver}}.{{$txt.LocalTable.ColumnNameGo}}.Valid = true
|
||||
return errors.Wrap(err, "failed to update local table")
|
||||
}
|
||||
|
||||
{{$txt.Function.Receiver}}.R.{{$txt.Function.Name}} = nil
|
||||
if related == nil || related.R == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
{{if .Unique -}}
|
||||
related.R.{{$txt.Function.ForeignName}} = nil
|
||||
{{else -}}
|
||||
for i, ri := range related.R.{{$txt.Function.ForeignName}} {
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare({{$txt.Function.Receiver}}.{{$txt.Function.LocalAssignment}}, ri.{{$txt.Function.LocalAssignment}}) {
|
||||
{{else -}}
|
||||
if {{$txt.Function.Receiver}}.{{$txt.Function.LocalAssignment}} != ri.{{$txt.Function.LocalAssignment}} {
|
||||
{{end -}}
|
||||
continue
|
||||
}
|
||||
|
||||
ln := len(related.R.{{$txt.Function.ForeignName}})
|
||||
if ln > 1 && i < ln-1 {
|
||||
related.R.{{$txt.Function.ForeignName}}[i] = related.R.{{$txt.Function.ForeignName}}[ln-1]
|
||||
}
|
||||
related.R.{{$txt.Function.ForeignName}} = related.R.{{$txt.Function.ForeignName}}[:ln-1]
|
||||
break
|
||||
}
|
||||
{{end -}}
|
||||
|
||||
return nil
|
||||
}
|
||||
{{end -}}{{/* if foreignkey nullable */}}
|
||||
{{- end -}}{{/* range */}}
|
||||
{{- end -}}{{/* join table */}}
|
79
templates/11_relationship_one_to_one_setops.tpl
Normal file
79
templates/11_relationship_one_to_one_setops.tpl
Normal file
|
@ -0,0 +1,79 @@
|
|||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.ToOneRelationships -}}
|
||||
{{- $txt := txtsFromOneToOne $dot.Tables $dot.Table . -}}
|
||||
{{- $varNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- $localNameSingular := .Table | singular | camelCase}}
|
||||
// Set{{$txt.Function.Name}} of the {{.Table | singular}} to the related item.
|
||||
// Sets {{$txt.Function.Receiver}}.R.{{$txt.Function.Name}} to related.
|
||||
// Adds {{$txt.Function.Receiver}} to related.R.{{$txt.Function.ForeignName}}.
|
||||
func ({{$txt.Function.Receiver}} *{{$txt.LocalTable.NameGo}}) Set{{$txt.Function.Name}}(exec boil.Executor, insert bool, related *{{$txt.ForeignTable.NameGo}}) error {
|
||||
var err error
|
||||
|
||||
oldVal := related.{{$txt.Function.ForeignAssignment}}
|
||||
related.{{$txt.Function.ForeignAssignment}} = {{$txt.Function.Receiver}}.{{$txt.Function.LocalAssignment}}
|
||||
{{if .ForeignColumnNullable -}}
|
||||
related.{{$txt.ForeignTable.ColumnNameGo}}.Valid = true
|
||||
{{- end}}
|
||||
|
||||
if insert {
|
||||
if err = related.Insert(exec); err != nil {
|
||||
related.{{$txt.Function.ForeignAssignment}} = oldVal
|
||||
{{if .ForeignColumnNullable -}}
|
||||
related.{{$txt.ForeignTable.ColumnNameGo}}.Valid = false
|
||||
{{- end}}
|
||||
return errors.Wrap(err, "failed to insert into foreign table")
|
||||
}
|
||||
} else {
|
||||
if err = related.Update(exec, "{{.ForeignColumn}}"); err != nil {
|
||||
related.{{$txt.Function.ForeignAssignment}} = oldVal
|
||||
{{if .ForeignColumnNullable -}}
|
||||
related.{{$txt.ForeignTable.ColumnNameGo}}.Valid = false
|
||||
{{- end}}
|
||||
return errors.Wrap(err, "failed to update foreign table")
|
||||
}
|
||||
}
|
||||
|
||||
if {{$txt.Function.Receiver}}.R == nil {
|
||||
{{$txt.Function.Receiver}}.R = &{{$localNameSingular}}R{
|
||||
{{$txt.Function.Name}}: related,
|
||||
}
|
||||
} else {
|
||||
{{$txt.Function.Receiver}}.R.{{$txt.Function.Name}} = related
|
||||
}
|
||||
|
||||
if related.R == nil {
|
||||
related.R = &{{$varNameSingular}}R{
|
||||
{{$txt.Function.ForeignName}}: {{$txt.Function.Receiver}},
|
||||
}
|
||||
} else {
|
||||
related.R.{{$txt.Function.ForeignName}} = {{$txt.Function.Receiver}}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
{{- if .ForeignColumnNullable}}
|
||||
// Remove{{$txt.Function.Name}} relationship.
|
||||
// Sets {{$txt.Function.Receiver}}.R.{{$txt.Function.Name}} to nil.
|
||||
// Removes {{$txt.Function.Receiver}} from all passed in related items' relationships struct (Optional).
|
||||
func ({{$txt.Function.Receiver}} *{{$txt.LocalTable.NameGo}}) Remove{{$txt.Function.Name}}(exec boil.Executor, related *{{$txt.ForeignTable.NameGo}}) error {
|
||||
var err error
|
||||
|
||||
related.{{$txt.ForeignTable.ColumnNameGo}}.Valid = false
|
||||
if err = related.Update(exec, "{{.ForeignColumn}}"); err != nil {
|
||||
related.{{$txt.ForeignTable.ColumnNameGo}}.Valid = true
|
||||
return errors.Wrap(err, "failed to update local table")
|
||||
}
|
||||
|
||||
{{$txt.Function.Receiver}}.R.{{$txt.Function.Name}} = nil
|
||||
if related == nil || related.R == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
related.R.{{$txt.Function.ForeignName}} = nil
|
||||
return nil
|
||||
}
|
||||
{{end -}}{{/* if foreignkey nullable */}}
|
||||
{{- end -}}{{/* range */}}
|
||||
{{- end -}}{{/* join table */}}
|
|
@ -5,14 +5,9 @@
|
|||
{{- $table := .Table -}}
|
||||
{{- range .Table.ToManyRelationships -}}
|
||||
{{- $varNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- if (and .ForeignColumnUnique (not .ToJoinTable)) -}}
|
||||
{{- /* Begin execution of template for many-to-one setops */ -}}
|
||||
{{- $txt := textsFromOneToOneRelationship $dot.PkgName $dot.Tables $table . -}}
|
||||
{{- template "relationship_to_one_setops_helper" (preserveDot $dot $txt) -}}
|
||||
{{- else -}}
|
||||
{{- $rel := textsFromRelationship $dot.Tables $table . -}}
|
||||
{{- $localNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignNameSingular := .ForeignTable | singular | camelCase}}
|
||||
{{- $rel := txtsFromToMany $dot.Tables $table . -}}
|
||||
{{- $localNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignNameSingular := .ForeignTable | singular | camelCase}}
|
||||
// Add{{$rel.Function.Name}} adds the given related objects to the existing relationships
|
||||
// of the {{$table.Name | singular}}, optionally inserting them as new records.
|
||||
// Appends related to {{$rel.Function.Receiver}}.R.{{$rel.Function.Name}}.
|
||||
|
@ -200,7 +195,11 @@ func remove{{$rel.LocalTable.NameGo}}From{{$rel.ForeignTable.NameGo}}Slice({{$re
|
|||
continue
|
||||
}
|
||||
for i, ri := range rel.R.{{$rel.Function.ForeignName}} {
|
||||
{{if $rel.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare({{$rel.Function.Receiver}}.{{$rel.Function.LocalAssignment}}, ri.{{$rel.Function.LocalAssignment}}) {
|
||||
{{else -}}
|
||||
if {{$rel.Function.Receiver}}.{{$rel.Function.LocalAssignment}} != ri.{{$rel.Function.LocalAssignment}} {
|
||||
{{end -}}
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -215,6 +214,5 @@ func remove{{$rel.LocalTable.NameGo}}From{{$rel.ForeignTable.NameGo}}Slice({{$re
|
|||
}
|
||||
{{end -}}{{- /* if ToJoinTable */ -}}
|
||||
{{- end -}}{{- /* if nullable foreign key */ -}}
|
||||
{{- end -}}{{- /* if unique foreign key */ -}}
|
||||
{{- end -}}{{- /* range relationships */ -}}
|
||||
{{- end -}}{{- /* if IsJoinTable */ -}}
|
|
@ -69,7 +69,7 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
|
|||
|
||||
if len(cache.retMapping) != 0 {
|
||||
{{if .UseLastInsertID -}}
|
||||
cache.retQuery = fmt.Sprintf("SELECT %s FROM {{$schemaTable}} WHERE %s", strings.Join(returnColumns, "{{.LQ}},{{.RQ}}"), strmangle.WhereClause("{{.LQ}}", "{{.RQ}}", {{if .Dialect.IndexPlaceholders}}1{{else}}0{{end}}, {{$varNameSingular}}PrimaryKeyColumns))
|
||||
cache.retQuery = fmt.Sprintf("SELECT {{.LQ}}%s{{.RQ}} FROM {{$schemaTable}} WHERE %s", strings.Join(returnColumns, "{{.LQ}},{{.RQ}}"), strmangle.WhereClause("{{.LQ}}", "{{.RQ}}", {{if .Dialect.IndexPlaceholders}}1{{else}}0{{end}}, {{$varNameSingular}}PrimaryKeyColumns))
|
||||
{{else -}}
|
||||
cache.query += fmt.Sprintf(" RETURNING {{.LQ}}%s{{.RQ}}", strings.Join(returnColumns, "{{.LQ}},{{.RQ}}"))
|
||||
{{end -}}
|
||||
|
@ -100,20 +100,23 @@ func (o *{{$tableNameSingular}}) Insert(exec boil.Executor, whitelist ... string
|
|||
if err != nil {
|
||||
return ErrSyncFail
|
||||
}
|
||||
|
||||
if lastID != 0 {
|
||||
{{- $colName := index .Table.PKey.Columns 0 -}}
|
||||
{{- $col := .Table.GetColumn $colName -}}
|
||||
{{- $colTitled := $colName | singular | titleCase}}
|
||||
o.{{$colTitled}} = {{$col.Type}}(lastID)
|
||||
identifierCols = []interface{}{lastID}
|
||||
} else {
|
||||
identifierCols = []interface{}{
|
||||
{{range .Table.PKey.Columns -}}
|
||||
o.{{. | singular | titleCase}},
|
||||
{{end -}}
|
||||
}
|
||||
|
||||
{{- $colName := index .Table.PKey.Columns 0 -}}
|
||||
{{- $col := .Table.GetColumn $colName -}}
|
||||
{{- $colTitled := $colName | singular | titleCase}}
|
||||
{{if eq 1 (len .Table.PKey.Columns)}}
|
||||
{{$cnames := .Table.Columns | filterColumnsByDefault true | columnNames}}
|
||||
{{if setInclude $colName $cnames}}
|
||||
o.{{$colTitled}} = {{$col.Type}}(lastID)
|
||||
identifierCols = []interface{}{lastID}
|
||||
{{end}}
|
||||
{{else}}
|
||||
identifierCols = []interface{}{
|
||||
{{range .Table.PKey.Columns -}}
|
||||
o.{{. | singular | titleCase}},
|
||||
{{end -}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
if lastID == 0 || len(cache.retMapping) != 1 || cache.retMapping[0] == {{$varNameSingular}}Mapping["{{$colTitled}}"] {
|
||||
if boil.DebugMode {
|
|
@ -74,15 +74,11 @@ func (o *{{$tableNameSingular}}) Update(exec boil.Executor, whitelist ... string
|
|||
fmt.Fprintln(boil.DebugWriter, values)
|
||||
}
|
||||
|
||||
result, err := exec.Exec(cache.query, values...)
|
||||
_, err = exec.Exec(cache.query, values...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "{{.PkgName}}: unable to update {{.Table.Name}} row")
|
||||
}
|
||||
|
||||
if r, err := result.RowsAffected(); err == nil && r != 1 {
|
||||
return errors.Errorf("failed to update single row, updated %d rows", r)
|
||||
}
|
||||
|
||||
if !cached {
|
||||
{{$varNameSingular}}UpdateCacheMut.Lock()
|
||||
{{$varNameSingular}}UpdateCache[key] = cache
|
||||
|
@ -172,14 +168,10 @@ func (o {{$tableNameSingular}}Slice) UpdateAll(exec boil.Executor, cols M) error
|
|||
fmt.Fprintln(boil.DebugWriter, args...)
|
||||
}
|
||||
|
||||
result, err := exec.Exec(sql, args...)
|
||||
_, err := exec.Exec(sql, args...)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "{{.PkgName}}: unable to update all in {{$varNameSingular}} slice")
|
||||
}
|
||||
|
||||
if r, err := result.RowsAffected(); err == nil && r != ln {
|
||||
return errors.Errorf("failed to update %d rows, only affected %d", ln, r)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -142,19 +142,22 @@ func (o *{{$tableNameSingular}}) Upsert(exec boil.Executor, {{if ne .DriverName
|
|||
return ErrSyncFail
|
||||
}
|
||||
|
||||
if lastID != 0 {
|
||||
{{- $colName := index .Table.PKey.Columns 0 -}}
|
||||
{{- $col := .Table.GetColumn $colName -}}
|
||||
{{- $colTitled := $colName | singular | titleCase}}
|
||||
o.{{$colTitled}} = {{$col.Type}}(lastID)
|
||||
identifierCols = []interface{}{lastID}
|
||||
} else {
|
||||
identifierCols = []interface{}{
|
||||
{{range .Table.PKey.Columns -}}
|
||||
o.{{. | singular | titleCase}},
|
||||
{{end -}}
|
||||
}
|
||||
{{- $colName := index .Table.PKey.Columns 0 -}}
|
||||
{{- $col := .Table.GetColumn $colName -}}
|
||||
{{- $colTitled := $colName | singular | titleCase}}
|
||||
{{if eq 1 (len .Table.PKey.Columns)}}
|
||||
{{$cnames := .Table.Columns | filterColumnsByDefault true | columnNames}}
|
||||
{{if setInclude $colName $cnames}}
|
||||
o.{{$colTitled}} = {{$col.Type}}(lastID)
|
||||
identifierCols = []interface{}{lastID}
|
||||
{{end}}
|
||||
{{else}}
|
||||
identifierCols = []interface{}{
|
||||
{{range .Table.PKey.Columns -}}
|
||||
o.{{. | singular | titleCase}},
|
||||
{{end -}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
if lastID == 0 || len(cache.retMapping) != 1 || cache.retMapping[0] == {{$varNameSingular}}Mapping["{{$colTitled}}"] {
|
||||
if boil.DebugMode {
|
69
templates_test/relationship_one_to_one.tpl
Normal file
69
templates_test/relationship_one_to_one.tpl
Normal file
|
@ -0,0 +1,69 @@
|
|||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.ToOneRelationships -}}
|
||||
{{- $txt := txtsFromOneToOne $dot.Tables $dot.Table . -}}
|
||||
{{- $varNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
func test{{$txt.LocalTable.NameGo}}OneToOne{{$txt.ForeignTable.NameGo}}_{{$txt.Function.Name}}(t *testing.T) {
|
||||
tx := MustTx(boil.Begin())
|
||||
defer tx.Rollback()
|
||||
|
||||
var foreign {{$txt.ForeignTable.NameGo}}
|
||||
var local {{$txt.LocalTable.NameGo}}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err := randomize.Struct(seed, &foreign, {{$foreignVarNameSingular}}DBTypes, true, {{$foreignVarNameSingular}}ColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize {{$txt.ForeignTable.NameGo}} struct: %s", err)
|
||||
}
|
||||
if err := randomize.Struct(seed, &local, {{$varNameSingular}}DBTypes, true, {{$varNameSingular}}ColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize {{$txt.LocalTable.NameGo}} struct: %s", err)
|
||||
}
|
||||
|
||||
{{if .ForeignColumnNullable -}}
|
||||
foreign.{{$txt.ForeignTable.ColumnNameGo}}.Valid = true
|
||||
{{- end}}
|
||||
{{if .Nullable -}}
|
||||
local.{{$txt.LocalTable.ColumnNameGo}}.Valid = true
|
||||
{{- end}}
|
||||
|
||||
if err := local.Insert(tx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
foreign.{{$txt.Function.ForeignAssignment}} = local.{{$txt.Function.LocalAssignment}}
|
||||
if err := foreign.Insert(tx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
check, err := local.{{$txt.Function.Name}}(tx).One()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(check.{{$txt.Function.ForeignAssignment}}, foreign.{{$txt.Function.ForeignAssignment}}) {
|
||||
{{else -}}
|
||||
if check.{{$txt.Function.ForeignAssignment}} != foreign.{{$txt.Function.ForeignAssignment}} {
|
||||
{{end -}}
|
||||
t.Errorf("want: %v, got %v", foreign.{{$txt.Function.ForeignAssignment}}, check.{{$txt.Function.ForeignAssignment}})
|
||||
}
|
||||
|
||||
slice := {{$txt.LocalTable.NameGo}}Slice{&local}
|
||||
if err = local.L.Load{{$txt.Function.Name}}(tx, false, &slice); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if local.R.{{$txt.Function.Name}} == nil {
|
||||
t.Error("struct should have been eager loaded")
|
||||
}
|
||||
|
||||
local.R.{{$txt.Function.Name}} = nil
|
||||
if err = local.L.Load{{$txt.Function.Name}}(tx, true, &local); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if local.R.{{$txt.Function.Name}} == nil {
|
||||
t.Error("struct should have been eager loaded")
|
||||
}
|
||||
}
|
||||
{{end -}}{{/* range */}}
|
||||
{{- end -}}{{/* join table */}}
|
129
templates_test/relationship_one_to_one_setops.tpl
Normal file
129
templates_test/relationship_one_to_one_setops.tpl
Normal file
|
@ -0,0 +1,129 @@
|
|||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.ToOneRelationships -}}
|
||||
{{- $txt := txtsFromOneToOne $dot.Tables $dot.Table .}}
|
||||
{{- $varNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase}}
|
||||
func test{{$txt.LocalTable.NameGo}}OneToOneSetOp{{$txt.ForeignTable.NameGo}}_{{$txt.Function.Name}}(t *testing.T) {
|
||||
var err error
|
||||
|
||||
tx := MustTx(boil.Begin())
|
||||
defer tx.Rollback()
|
||||
|
||||
var a {{$txt.LocalTable.NameGo}}
|
||||
var b, c {{$txt.ForeignTable.NameGo}}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, strmangle.SetComplement({{$varNameSingular}}PrimaryKeyColumns, {{$varNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = randomize.Struct(seed, &b, {{$foreignVarNameSingular}}DBTypes, false, strmangle.SetComplement({{$foreignVarNameSingular}}PrimaryKeyColumns, {{$foreignVarNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = randomize.Struct(seed, &c, {{$foreignVarNameSingular}}DBTypes, false, strmangle.SetComplement({{$foreignVarNameSingular}}PrimaryKeyColumns, {{$foreignVarNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := a.Insert(tx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = b.Insert(tx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i, x := range []*{{$txt.ForeignTable.NameGo}}{&b, &c} {
|
||||
err = a.Set{{$txt.Function.Name}}(tx, i != 0, x)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if a.R.{{$txt.Function.Name}} != x {
|
||||
t.Error("relationship struct not set to correct value")
|
||||
}
|
||||
if x.R.{{$txt.Function.ForeignName}} != &a {
|
||||
t.Error("failed to append to foreign relationship struct")
|
||||
}
|
||||
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(a.{{$txt.Function.LocalAssignment}}, x.{{$txt.Function.ForeignAssignment}}) {
|
||||
{{else -}}
|
||||
if a.{{$txt.Function.LocalAssignment}} != x.{{$txt.Function.ForeignAssignment}} {
|
||||
{{end -}}
|
||||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}})
|
||||
}
|
||||
|
||||
zero := reflect.Zero(reflect.TypeOf(x.{{$txt.Function.ForeignAssignment}}))
|
||||
reflect.Indirect(reflect.ValueOf(&x.{{$txt.Function.ForeignAssignment}})).Set(zero)
|
||||
|
||||
if err = x.Reload(tx); err != nil {
|
||||
t.Fatal("failed to reload", err)
|
||||
}
|
||||
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(a.{{$txt.Function.LocalAssignment}}, x.{{$txt.Function.ForeignAssignment}}) {
|
||||
{{else -}}
|
||||
if a.{{$txt.Function.LocalAssignment}} != x.{{$txt.Function.ForeignAssignment}} {
|
||||
{{end -}}
|
||||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}}, x.{{$txt.Function.ForeignAssignment}})
|
||||
}
|
||||
|
||||
if err = x.Delete(tx); err != nil {
|
||||
t.Fatal("failed to delete x", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
{{- if .ForeignColumnNullable}}
|
||||
|
||||
func test{{$txt.LocalTable.NameGo}}OneToOneRemoveOp{{$txt.ForeignTable.NameGo}}_{{$txt.Function.Name}}(t *testing.T) {
|
||||
var err error
|
||||
|
||||
tx := MustTx(boil.Begin())
|
||||
defer tx.Rollback()
|
||||
|
||||
var a {{$txt.LocalTable.NameGo}}
|
||||
var b {{$txt.ForeignTable.NameGo}}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, strmangle.SetComplement({{$varNameSingular}}PrimaryKeyColumns, {{$varNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = randomize.Struct(seed, &b, {{$foreignVarNameSingular}}DBTypes, false, strmangle.SetComplement({{$foreignVarNameSingular}}PrimaryKeyColumns, {{$foreignVarNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = a.Insert(tx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = a.Set{{$txt.Function.Name}}(tx, true, &b); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = a.Remove{{$txt.Function.Name}}(tx, &b); err != nil {
|
||||
t.Error("failed to remove relationship")
|
||||
}
|
||||
|
||||
count, err := a.{{$txt.Function.Name}}(tx).Count()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if count != 0 {
|
||||
t.Error("want no relationships remaining")
|
||||
}
|
||||
|
||||
if a.R.{{$txt.Function.Name}} != nil {
|
||||
t.Error("R struct entry should be nil")
|
||||
}
|
||||
|
||||
if b.{{$txt.ForeignTable.ColumnNameGo}}.Valid {
|
||||
t.Error("foreign key column should be nil")
|
||||
}
|
||||
|
||||
if b.R.{{$txt.Function.ForeignName}} != nil {
|
||||
t.Error("failed to remove a from b's relationships")
|
||||
}
|
||||
}
|
||||
{{end -}}{{/* end if foreign key nullable */}}
|
||||
{{- end -}}{{/* range */}}
|
||||
{{- end -}}{{/* join table */}}
|
|
@ -3,25 +3,27 @@
|
|||
{{- $dot := . }}
|
||||
{{- $table := .Table }}
|
||||
{{- range .Table.ToManyRelationships -}}
|
||||
{{- if (and .ForeignColumnUnique (not .ToJoinTable)) -}}
|
||||
{{- template "relationship_to_one_test_helper" (textsFromOneToOneRelationship $dot.PkgName $dot.Tables $table .) -}}
|
||||
{{- else -}}
|
||||
{{- $rel := textsFromRelationship $dot.Tables $table . -}}
|
||||
func test{{$rel.LocalTable.NameGo}}ToMany{{$rel.Function.Name}}(t *testing.T) {
|
||||
{{- $txt := txtsFromToMany $dot.Tables $table .}}
|
||||
{{- $varNameSingular := .Table | singular | camelCase -}}
|
||||
func test{{$txt.LocalTable.NameGo}}ToMany{{$txt.Function.Name}}(t *testing.T) {
|
||||
var err error
|
||||
tx := MustTx(boil.Begin())
|
||||
defer tx.Rollback()
|
||||
|
||||
var a {{$rel.LocalTable.NameGo}}
|
||||
var b, c {{$rel.ForeignTable.NameGo}}
|
||||
var a {{$txt.LocalTable.NameGo}}
|
||||
var b, c {{$txt.ForeignTable.NameGo}}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, true, {{$varNameSingular}}ColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize {{$txt.LocalTable.NameGo}} struct: %s", err)
|
||||
}
|
||||
|
||||
if err := a.Insert(tx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
randomize.Struct(seed, &b, {{$rel.ForeignTable.NameSingular | camelCase}}DBTypes, false, "{{.ForeignColumn}}")
|
||||
randomize.Struct(seed, &c, {{$rel.ForeignTable.NameSingular | camelCase}}DBTypes, false, "{{.ForeignColumn}}")
|
||||
randomize.Struct(seed, &b, {{$txt.ForeignTable.NameSingular | camelCase}}DBTypes, false{{if not $txt.Function.UsesBytes}}, "{{.ForeignColumn}}"{{end}})
|
||||
randomize.Struct(seed, &c, {{$txt.ForeignTable.NameSingular | camelCase}}DBTypes, false{{if not $txt.Function.UsesBytes}}, "{{.ForeignColumn}}"{{end}})
|
||||
{{if .Nullable -}}
|
||||
a.{{.Column | titleCase}}.Valid = true
|
||||
{{- end}}
|
||||
|
@ -30,8 +32,8 @@ func test{{$rel.LocalTable.NameGo}}ToMany{{$rel.Function.Name}}(t *testing.T) {
|
|||
c.{{.ForeignColumn | titleCase}}.Valid = true
|
||||
{{- end}}
|
||||
{{if not .ToJoinTable -}}
|
||||
b.{{$rel.Function.ForeignAssignment}} = a.{{$rel.Function.LocalAssignment}}
|
||||
c.{{$rel.Function.ForeignAssignment}} = a.{{$rel.Function.LocalAssignment}}
|
||||
b.{{$txt.Function.ForeignAssignment}} = a.{{$txt.Function.LocalAssignment}}
|
||||
c.{{$txt.Function.ForeignAssignment}} = a.{{$txt.Function.LocalAssignment}}
|
||||
{{- end}}
|
||||
if err = b.Insert(tx); err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -41,30 +43,39 @@ func test{{$rel.LocalTable.NameGo}}ToMany{{$rel.Function.Name}}(t *testing.T) {
|
|||
}
|
||||
|
||||
{{if .ToJoinTable -}}
|
||||
_, err = tx.Exec("insert into {{.JoinTable | $dot.SchemaTable}} ({{.JoinLocalColumn | $dot.Quotes}}, {{.JoinForeignColumn | $dot.Quotes}}) values {{if $dot.Dialect.IndexPlaceholders}}($1, $2){{else}}(?, ?){{end}}", a.{{$rel.LocalTable.ColumnNameGo}}, b.{{$rel.ForeignTable.ColumnNameGo}})
|
||||
_, err = tx.Exec("insert into {{.JoinTable | $dot.SchemaTable}} ({{.JoinLocalColumn | $dot.Quotes}}, {{.JoinForeignColumn | $dot.Quotes}}) values {{if $dot.Dialect.IndexPlaceholders}}($1, $2){{else}}(?, ?){{end}}", a.{{$txt.LocalTable.ColumnNameGo}}, b.{{$txt.ForeignTable.ColumnNameGo}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = tx.Exec("insert into {{.JoinTable | $dot.SchemaTable}} ({{.JoinLocalColumn | $dot.Quotes}}, {{.JoinForeignColumn | $dot.Quotes}}) values {{if $dot.Dialect.IndexPlaceholders}}($1, $2){{else}}(?, ?){{end}}", a.{{$rel.LocalTable.ColumnNameGo}}, c.{{$rel.ForeignTable.ColumnNameGo}})
|
||||
_, err = tx.Exec("insert into {{.JoinTable | $dot.SchemaTable}} ({{.JoinLocalColumn | $dot.Quotes}}, {{.JoinForeignColumn | $dot.Quotes}}) values {{if $dot.Dialect.IndexPlaceholders}}($1, $2){{else}}(?, ?){{end}}", a.{{$txt.LocalTable.ColumnNameGo}}, c.{{$txt.ForeignTable.ColumnNameGo}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{$varname := .ForeignTable | singular | camelCase -}}
|
||||
{{$varname}}, err := a.{{$rel.Function.Name}}(tx).All()
|
||||
{{$varname}}, err := a.{{$txt.Function.Name}}(tx).All()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
bFound, cFound := false, false
|
||||
for _, v := range {{$varname}} {
|
||||
if v.{{$rel.Function.ForeignAssignment}} == b.{{$rel.Function.ForeignAssignment}} {
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 == bytes.Compare(v.{{$txt.Function.ForeignAssignment}}, b.{{$txt.Function.ForeignAssignment}}) {
|
||||
bFound = true
|
||||
}
|
||||
if v.{{$rel.Function.ForeignAssignment}} == c.{{$rel.Function.ForeignAssignment}} {
|
||||
if 0 == bytes.Compare(v.{{$txt.Function.ForeignAssignment}}, c.{{$txt.Function.ForeignAssignment}}) {
|
||||
cFound = true
|
||||
}
|
||||
{{else -}}
|
||||
if v.{{$txt.Function.ForeignAssignment}} == b.{{$txt.Function.ForeignAssignment}} {
|
||||
bFound = true
|
||||
}
|
||||
if v.{{$txt.Function.ForeignAssignment}} == c.{{$txt.Function.ForeignAssignment}} {
|
||||
cFound = true
|
||||
}
|
||||
{{end -}}
|
||||
}
|
||||
|
||||
if !bFound {
|
||||
|
@ -74,19 +85,19 @@ func test{{$rel.LocalTable.NameGo}}ToMany{{$rel.Function.Name}}(t *testing.T) {
|
|||
t.Error("expected to find c")
|
||||
}
|
||||
|
||||
slice := {{$rel.LocalTable.NameGo}}Slice{&a}
|
||||
if err = a.L.Load{{$rel.Function.Name}}(tx, false, &slice); err != nil {
|
||||
slice := {{$txt.LocalTable.NameGo}}Slice{&a}
|
||||
if err = a.L.Load{{$txt.Function.Name}}(tx, false, &slice); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := len(a.R.{{$rel.Function.Name}}); got != 2 {
|
||||
if got := len(a.R.{{$txt.Function.Name}}); got != 2 {
|
||||
t.Error("number of eager loaded records wrong, got:", got)
|
||||
}
|
||||
|
||||
a.R.{{$rel.Function.Name}} = nil
|
||||
if err = a.L.Load{{$rel.Function.Name}}(tx, true, &a); err != nil {
|
||||
a.R.{{$txt.Function.Name}} = nil
|
||||
if err = a.L.Load{{$txt.Function.Name}}(tx, true, &a); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got := len(a.R.{{$rel.Function.Name}}); got != 2 {
|
||||
if got := len(a.R.{{$txt.Function.Name}}); got != 2 {
|
||||
t.Error("number of eager loaded records wrong, got:", got)
|
||||
}
|
||||
|
||||
|
@ -95,6 +106,5 @@ func test{{$rel.LocalTable.NameGo}}ToMany{{$rel.Function.Name}}(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
{{end -}}{{- /* if unique */ -}}
|
||||
{{- end -}}{{- /* range */ -}}
|
||||
{{end -}}{{- /* range */ -}}
|
||||
{{- end -}}{{- /* outer if join table */ -}}
|
||||
|
|
|
@ -3,13 +3,9 @@
|
|||
{{- $dot := . -}}
|
||||
{{- $table := .Table -}}
|
||||
{{- range .Table.ToManyRelationships -}}
|
||||
{{- if (and .ForeignColumnUnique (not .ToJoinTable)) -}}
|
||||
{{- template "relationship_to_one_setops_test_helper" (textsFromOneToOneRelationship $dot.PkgName $dot.Tables $table .) -}}
|
||||
{{- else -}}
|
||||
{{- $varNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- $rel := textsFromRelationship $dot.Tables $table .}}
|
||||
|
||||
{{- $varNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
{{- $rel := txtsFromToMany $dot.Tables $table .}}
|
||||
func test{{$rel.LocalTable.NameGo}}ToManyAddOp{{$rel.Function.Name}}(t *testing.T) {
|
||||
var err error
|
||||
|
||||
|
@ -20,12 +16,12 @@ func test{{$rel.LocalTable.NameGo}}ToManyAddOp{{$rel.Function.Name}}(t *testing.
|
|||
var b, c, d, e {{$rel.ForeignTable.NameGo}}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, {{$varNameSingular}}PrimaryKeyColumns...); err != nil {
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, strmangle.SetComplement({{$varNameSingular}}PrimaryKeyColumns, {{$varNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
foreigners := []*{{$rel.ForeignTable.NameGo}}{&b, &c, &d, &e}
|
||||
for _, x := range foreigners {
|
||||
if err = randomize.Struct(seed, x, {{$foreignVarNameSingular}}DBTypes, false, {{$foreignVarNameSingular}}PrimaryKeyColumns...); err != nil {
|
||||
if err = randomize.Struct(seed, x, {{$foreignVarNameSingular}}DBTypes, false, strmangle.SetComplement({{$foreignVarNameSingular}}PrimaryKeyColumns, {{$foreignVarNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -63,12 +59,21 @@ func test{{$rel.LocalTable.NameGo}}ToManyAddOp{{$rel.Function.Name}}(t *testing.
|
|||
}
|
||||
{{- else}}
|
||||
|
||||
{{if $rel.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(a.{{$rel.Function.LocalAssignment}}, first.{{$rel.Function.ForeignAssignment}}) {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, first.{{$rel.Function.ForeignAssignment}})
|
||||
}
|
||||
if 0 != bytes.Compare(a.{{$rel.Function.LocalAssignment}}, second.{{$rel.Function.ForeignAssignment}}) {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, second.{{$rel.Function.ForeignAssignment}})
|
||||
}
|
||||
{{else -}}
|
||||
if a.{{$rel.Function.LocalAssignment}} != first.{{$rel.Function.ForeignAssignment}} {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, first.{{$rel.Function.ForeignAssignment}})
|
||||
}
|
||||
if a.{{$rel.Function.LocalAssignment}} != second.{{$rel.Function.ForeignAssignment}} {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, second.{{$rel.Function.ForeignAssignment}})
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
if first.R.{{$rel.Function.ForeignName}} != &a {
|
||||
t.Error("relationship was not added properly to the foreign slice")
|
||||
|
@ -106,12 +111,12 @@ func test{{$rel.LocalTable.NameGo}}ToManySetOp{{$rel.Function.Name}}(t *testing.
|
|||
var b, c, d, e {{$rel.ForeignTable.NameGo}}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, {{$varNameSingular}}PrimaryKeyColumns...); err != nil {
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, strmangle.SetComplement({{$varNameSingular}}PrimaryKeyColumns, {{$varNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
foreigners := []*{{$rel.ForeignTable.NameGo}}{&b, &c, &d, &e}
|
||||
for _, x := range foreigners {
|
||||
if err = randomize.Struct(seed, x, {{$foreignVarNameSingular}}DBTypes, false, {{$foreignVarNameSingular}}PrimaryKeyColumns...); err != nil {
|
||||
if err = randomize.Struct(seed, x, {{$foreignVarNameSingular}}DBTypes, false, strmangle.SetComplement({{$foreignVarNameSingular}}PrimaryKeyColumns, {{$foreignVarNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -174,12 +179,21 @@ func test{{$rel.LocalTable.NameGo}}ToManySetOp{{$rel.Function.Name}}(t *testing.
|
|||
if c.{{$rel.ForeignTable.ColumnNameGo}}.Valid {
|
||||
t.Error("want c's foreign key value to be nil")
|
||||
}
|
||||
{{if $rel.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(a.{{$rel.Function.LocalAssignment}}, d.{{$rel.Function.ForeignAssignment}}) {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, d.{{$rel.Function.ForeignAssignment}})
|
||||
}
|
||||
if 0 != bytes.Compare(a.{{$rel.Function.LocalAssignment}}, e.{{$rel.Function.ForeignAssignment}}) {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, e.{{$rel.Function.ForeignAssignment}})
|
||||
}
|
||||
{{else -}}
|
||||
if a.{{$rel.Function.LocalAssignment}} != d.{{$rel.Function.ForeignAssignment}} {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, d.{{$rel.Function.ForeignAssignment}})
|
||||
}
|
||||
if a.{{$rel.Function.LocalAssignment}} != e.{{$rel.Function.ForeignAssignment}} {
|
||||
t.Error("foreign key was wrong value", a.{{$rel.Function.LocalAssignment}}, e.{{$rel.Function.ForeignAssignment}})
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
if b.R.{{$rel.Function.ForeignName}} != nil {
|
||||
t.Error("relationship was not removed properly from the foreign struct")
|
||||
|
@ -213,12 +227,12 @@ func test{{$rel.LocalTable.NameGo}}ToManyRemoveOp{{$rel.Function.Name}}(t *testi
|
|||
var b, c, d, e {{$rel.ForeignTable.NameGo}}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, {{$varNameSingular}}PrimaryKeyColumns...); err != nil {
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, strmangle.SetComplement({{$varNameSingular}}PrimaryKeyColumns, {{$varNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
foreigners := []*{{$rel.ForeignTable.NameGo}}{&b, &c, &d, &e}
|
||||
for _, x := range foreigners {
|
||||
if err = randomize.Struct(seed, x, {{$foreignVarNameSingular}}DBTypes, false, {{$foreignVarNameSingular}}PrimaryKeyColumns...); err != nil {
|
||||
if err = randomize.Struct(seed, x, {{$foreignVarNameSingular}}DBTypes, false, strmangle.SetComplement({{$foreignVarNameSingular}}PrimaryKeyColumns, {{$foreignVarNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
@ -303,6 +317,5 @@ func test{{$rel.LocalTable.NameGo}}ToManyRemoveOp{{$rel.Function.Name}}(t *testi
|
|||
}
|
||||
}
|
||||
{{end -}}
|
||||
{{- end -}}{{- /* if unique foreign key */ -}}
|
||||
{{- end -}}{{- /* range relationships */ -}}
|
||||
{{- end -}}{{- /* outer if join table */ -}}
|
||||
|
|
|
@ -1,69 +1,69 @@
|
|||
{{- define "relationship_to_one_test_helper"}}
|
||||
func test{{.LocalTable.NameGo}}ToOne{{.ForeignTable.NameGo}}_{{.Function.Name}}(t *testing.T) {
|
||||
tx := MustTx(boil.Begin())
|
||||
defer tx.Rollback()
|
||||
|
||||
var foreign {{.ForeignTable.NameGo}}
|
||||
var local {{.LocalTable.NameGo}}
|
||||
{{if .ForeignKey.Nullable -}}
|
||||
local.{{.ForeignKey.Column | titleCase}}.Valid = true
|
||||
{{end}}
|
||||
{{- if .ForeignKey.ForeignColumnNullable -}}
|
||||
foreign.{{.ForeignKey.ForeignColumn | titleCase}}.Valid = true
|
||||
{{end}}
|
||||
|
||||
{{if not .Function.OneToOne -}}
|
||||
if err := foreign.Insert(tx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
local.{{.Function.LocalAssignment}} = foreign.{{.Function.ForeignAssignment}}
|
||||
if err := local.Insert(tx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
{{else -}}
|
||||
if err := local.Insert(tx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
foreign.{{.Function.ForeignAssignment}} = local.{{.Function.LocalAssignment}}
|
||||
if err := foreign.Insert(tx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
{{end -}}
|
||||
|
||||
check, err := local.{{.Function.Name}}(tx).One()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if check.{{.Function.ForeignAssignment}} != foreign.{{.Function.ForeignAssignment}} {
|
||||
t.Errorf("want: %v, got %v", foreign.{{.Function.ForeignAssignment}}, check.{{.Function.ForeignAssignment}})
|
||||
}
|
||||
|
||||
slice := {{.LocalTable.NameGo}}Slice{&local}
|
||||
if err = local.L.Load{{.Function.Name}}(tx, false, &slice); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if local.R.{{.Function.Name}} == nil {
|
||||
t.Error("struct should have been eager loaded")
|
||||
}
|
||||
|
||||
local.R.{{.Function.Name}} = nil
|
||||
if err = local.L.Load{{.Function.Name}}(tx, true, &local); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if local.R.{{.Function.Name}} == nil {
|
||||
t.Error("struct should have been eager loaded")
|
||||
}
|
||||
}
|
||||
|
||||
{{end -}}
|
||||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.FKeys -}}
|
||||
{{- $rel := textsFromForeignKey $dot.PkgName $dot.Tables $dot.Table . -}}
|
||||
{{- template "relationship_to_one_test_helper" $rel -}}
|
||||
{{end -}}
|
||||
{{- end -}}
|
||||
{{- $txt := txtsFromFKey $dot.Tables $dot.Table . -}}
|
||||
{{- $varNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase -}}
|
||||
func test{{$txt.LocalTable.NameGo}}ToOne{{$txt.ForeignTable.NameGo}}_{{$txt.Function.Name}}(t *testing.T) {
|
||||
tx := MustTx(boil.Begin())
|
||||
defer tx.Rollback()
|
||||
|
||||
var local {{$txt.LocalTable.NameGo}}
|
||||
var foreign {{$txt.ForeignTable.NameGo}}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err := randomize.Struct(seed, &local, {{$varNameSingular}}DBTypes, true, {{$varNameSingular}}ColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize {{$txt.LocalTable.NameGo}} struct: %s", err)
|
||||
}
|
||||
if err := randomize.Struct(seed, &foreign, {{$foreignVarNameSingular}}DBTypes, true, {{$foreignVarNameSingular}}ColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize {{$txt.ForeignTable.NameGo}} struct: %s", err)
|
||||
}
|
||||
|
||||
{{if .Nullable -}}
|
||||
local.{{$txt.LocalTable.ColumnNameGo}}.Valid = true
|
||||
{{- end}}
|
||||
{{if .ForeignColumnNullable -}}
|
||||
foreign.{{$txt.ForeignTable.ColumnNameGo}}.Valid = true
|
||||
{{- end}}
|
||||
|
||||
if err := foreign.Insert(tx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
local.{{$txt.Function.LocalAssignment}} = foreign.{{$txt.Function.ForeignAssignment}}
|
||||
if err := local.Insert(tx); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
check, err := local.{{$txt.Function.Name}}(tx).One()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(check.{{$txt.Function.ForeignAssignment}}, foreign.{{$txt.Function.ForeignAssignment}}) {
|
||||
{{else -}}
|
||||
if check.{{$txt.Function.ForeignAssignment}} != foreign.{{$txt.Function.ForeignAssignment}} {
|
||||
{{end -}}
|
||||
t.Errorf("want: %v, got %v", foreign.{{$txt.Function.ForeignAssignment}}, check.{{$txt.Function.ForeignAssignment}})
|
||||
}
|
||||
|
||||
slice := {{$txt.LocalTable.NameGo}}Slice{&local}
|
||||
if err = local.L.Load{{$txt.Function.Name}}(tx, false, &slice); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if local.R.{{$txt.Function.Name}} == nil {
|
||||
t.Error("struct should have been eager loaded")
|
||||
}
|
||||
|
||||
local.R.{{$txt.Function.Name}} = nil
|
||||
if err = local.L.Load{{$txt.Function.Name}}(tx, true, &local); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if local.R.{{$txt.Function.Name}} == nil {
|
||||
t.Error("struct should have been eager loaded")
|
||||
}
|
||||
}
|
||||
{{end -}}{{/* range */}}
|
||||
{{- end -}}{{/* join table */}}
|
||||
|
|
|
@ -1,23 +1,27 @@
|
|||
{{- define "relationship_to_one_setops_test_helper" -}}
|
||||
{{- $varNameSingular := .ForeignKey.Table | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignKey.ForeignTable | singular | camelCase}}
|
||||
func test{{.LocalTable.NameGo}}ToOneSetOp{{.ForeignTable.NameGo}}_{{.Function.Name}}(t *testing.T) {
|
||||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.FKeys -}}
|
||||
{{- $txt := txtsFromFKey $dot.Tables $dot.Table .}}
|
||||
{{- $varNameSingular := .Table | singular | camelCase -}}
|
||||
{{- $foreignVarNameSingular := .ForeignTable | singular | camelCase}}
|
||||
func test{{$txt.LocalTable.NameGo}}ToOneSetOp{{$txt.ForeignTable.NameGo}}_{{$txt.Function.Name}}(t *testing.T) {
|
||||
var err error
|
||||
|
||||
tx := MustTx(boil.Begin())
|
||||
defer tx.Rollback()
|
||||
|
||||
var a {{.LocalTable.NameGo}}
|
||||
var b, c {{.ForeignTable.NameGo}}
|
||||
var a {{$txt.LocalTable.NameGo}}
|
||||
var b, c {{$txt.ForeignTable.NameGo}}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, {{$varNameSingular}}PrimaryKeyColumns...); err != nil {
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, strmangle.SetComplement({{$varNameSingular}}PrimaryKeyColumns, {{$varNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = randomize.Struct(seed, &b, {{$foreignVarNameSingular}}DBTypes, false, {{$foreignVarNameSingular}}PrimaryKeyColumns...); err != nil {
|
||||
if err = randomize.Struct(seed, &b, {{$foreignVarNameSingular}}DBTypes, false, strmangle.SetComplement({{$foreignVarNameSingular}}PrimaryKeyColumns, {{$foreignVarNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = randomize.Struct(seed, &c, {{$foreignVarNameSingular}}DBTypes, false, {{$foreignVarNameSingular}}PrimaryKeyColumns...); err != nil {
|
||||
if err = randomize.Struct(seed, &c, {{$foreignVarNameSingular}}DBTypes, false, strmangle.SetComplement({{$foreignVarNameSingular}}PrimaryKeyColumns, {{$foreignVarNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -28,57 +32,66 @@ func test{{.LocalTable.NameGo}}ToOneSetOp{{.ForeignTable.NameGo}}_{{.Function.Na
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i, x := range []*{{.ForeignTable.NameGo}}{&b, &c} {
|
||||
err = a.Set{{.Function.Name}}(tx, i != 0, x)
|
||||
for i, x := range []*{{$txt.ForeignTable.NameGo}}{&b, &c} {
|
||||
err = a.Set{{$txt.Function.Name}}(tx, i != 0, x)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if a.{{.Function.LocalAssignment}} != x.{{.Function.ForeignAssignment}} {
|
||||
t.Error("foreign key was wrong value", a.{{.Function.LocalAssignment}})
|
||||
}
|
||||
if a.R.{{.Function.Name}} != x {
|
||||
if a.R.{{$txt.Function.Name}} != x {
|
||||
t.Error("relationship struct not set to correct value")
|
||||
}
|
||||
|
||||
zero := reflect.Zero(reflect.TypeOf(a.{{.Function.LocalAssignment}}))
|
||||
reflect.Indirect(reflect.ValueOf(&a.{{.Function.LocalAssignment}})).Set(zero)
|
||||
{{if .Unique -}}
|
||||
if x.R.{{$txt.Function.ForeignName}} != &a {
|
||||
t.Error("failed to append to foreign relationship struct")
|
||||
}
|
||||
{{else -}}
|
||||
if x.R.{{$txt.Function.ForeignName}}[0] != &a {
|
||||
t.Error("failed to append to foreign relationship struct")
|
||||
}
|
||||
{{end -}}
|
||||
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(a.{{$txt.Function.LocalAssignment}}, x.{{$txt.Function.ForeignAssignment}}) {
|
||||
{{else -}}
|
||||
if a.{{$txt.Function.LocalAssignment}} != x.{{$txt.Function.ForeignAssignment}} {
|
||||
{{end -}}
|
||||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}})
|
||||
}
|
||||
|
||||
zero := reflect.Zero(reflect.TypeOf(a.{{$txt.Function.LocalAssignment}}))
|
||||
reflect.Indirect(reflect.ValueOf(&a.{{$txt.Function.LocalAssignment}})).Set(zero)
|
||||
|
||||
if err = a.Reload(tx); err != nil {
|
||||
t.Fatal("failed to reload", err)
|
||||
}
|
||||
|
||||
if a.{{.Function.LocalAssignment}} != x.{{.Function.ForeignAssignment}} {
|
||||
t.Error("foreign key was wrong value", a.{{.Function.LocalAssignment}}, x.{{.Function.ForeignAssignment}})
|
||||
}
|
||||
|
||||
{{if .ForeignKey.Unique -}}
|
||||
if x.R.{{.Function.ForeignName}} != &a {
|
||||
t.Error("failed to append to foreign relationship struct")
|
||||
}
|
||||
{{if $txt.Function.UsesBytes -}}
|
||||
if 0 != bytes.Compare(a.{{$txt.Function.LocalAssignment}}, x.{{$txt.Function.ForeignAssignment}}) {
|
||||
{{else -}}
|
||||
if x.R.{{.Function.ForeignName}}[0] != &a {
|
||||
t.Error("failed to append to foreign relationship struct")
|
||||
}
|
||||
if a.{{$txt.Function.LocalAssignment}} != x.{{$txt.Function.ForeignAssignment}} {
|
||||
{{end -}}
|
||||
t.Error("foreign key was wrong value", a.{{$txt.Function.LocalAssignment}}, x.{{$txt.Function.ForeignAssignment}})
|
||||
}
|
||||
}
|
||||
}
|
||||
{{- if .ForeignKey.Nullable}}
|
||||
{{- if .Nullable}}
|
||||
|
||||
func test{{.LocalTable.NameGo}}ToOneRemoveOp{{.ForeignTable.NameGo}}_{{.Function.Name}}(t *testing.T) {
|
||||
func test{{$txt.LocalTable.NameGo}}ToOneRemoveOp{{$txt.ForeignTable.NameGo}}_{{$txt.Function.Name}}(t *testing.T) {
|
||||
var err error
|
||||
|
||||
tx := MustTx(boil.Begin())
|
||||
defer tx.Rollback()
|
||||
|
||||
var a {{.LocalTable.NameGo}}
|
||||
var b {{.ForeignTable.NameGo}}
|
||||
var a {{$txt.LocalTable.NameGo}}
|
||||
var b {{$txt.ForeignTable.NameGo}}
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, {{$varNameSingular}}PrimaryKeyColumns...); err != nil {
|
||||
if err = randomize.Struct(seed, &a, {{$varNameSingular}}DBTypes, false, strmangle.SetComplement({{$varNameSingular}}PrimaryKeyColumns, {{$varNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = randomize.Struct(seed, &b, {{$foreignVarNameSingular}}DBTypes, false, {{$foreignVarNameSingular}}PrimaryKeyColumns...); err != nil {
|
||||
if err = randomize.Struct(seed, &b, {{$foreignVarNameSingular}}DBTypes, false, strmangle.SetComplement({{$foreignVarNameSingular}}PrimaryKeyColumns, {{$foreignVarNameSingular}}ColumnsWithoutDefault)...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -86,15 +99,15 @@ func test{{.LocalTable.NameGo}}ToOneRemoveOp{{.ForeignTable.NameGo}}_{{.Function
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = a.Set{{.Function.Name}}(tx, true, &b); err != nil {
|
||||
if err = a.Set{{$txt.Function.Name}}(tx, true, &b); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err = a.Remove{{.Function.Name}}(tx, &b); err != nil {
|
||||
if err = a.Remove{{$txt.Function.Name}}(tx, &b); err != nil {
|
||||
t.Error("failed to remove relationship")
|
||||
}
|
||||
|
||||
count, err := a.{{.Function.Name}}(tx).Count()
|
||||
count, err := a.{{$txt.Function.Name}}(tx).Count()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
@ -102,32 +115,24 @@ func test{{.LocalTable.NameGo}}ToOneRemoveOp{{.ForeignTable.NameGo}}_{{.Function
|
|||
t.Error("want no relationships remaining")
|
||||
}
|
||||
|
||||
if a.R.{{.Function.Name}} != nil {
|
||||
if a.R.{{$txt.Function.Name}} != nil {
|
||||
t.Error("R struct entry should be nil")
|
||||
}
|
||||
|
||||
if a.{{.LocalTable.ColumnNameGo}}.Valid {
|
||||
t.Error("R struct entry should be nil")
|
||||
if a.{{$txt.LocalTable.ColumnNameGo}}.Valid {
|
||||
t.Error("foreign key value should be nil")
|
||||
}
|
||||
|
||||
{{if .ForeignKey.Unique -}}
|
||||
if b.R.{{.Function.ForeignName}} != nil {
|
||||
{{if .Unique -}}
|
||||
if b.R.{{$txt.Function.ForeignName}} != nil {
|
||||
t.Error("failed to remove a from b's relationships")
|
||||
}
|
||||
{{else -}}
|
||||
if len(b.R.{{.Function.ForeignName}}) != 0 {
|
||||
if len(b.R.{{$txt.Function.ForeignName}}) != 0 {
|
||||
t.Error("failed to remove a from b's relationships")
|
||||
}
|
||||
{{end -}}
|
||||
{{- end}}
|
||||
}
|
||||
{{end -}}
|
||||
{{- end -}}
|
||||
{{- if .Table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- $dot := . -}}
|
||||
{{- range .Table.FKeys -}}
|
||||
{{- $rel := textsFromForeignKey $dot.PkgName $dot.Tables $dot.Table .}}
|
||||
|
||||
{{template "relationship_to_one_setops_test_helper" $rel -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{end -}}{{/* end if foreign key nullable */}}
|
||||
{{- end -}}{{/* range */}}
|
||||
{{- end -}}{{/* join table */}}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
{{- $dot := .}}
|
||||
// This test suite runs each operation test in parallel.
|
||||
// Example, if your database has 3 tables, the suite will run:
|
||||
// table1, table2 and table3 Delete in parallel
|
||||
|
@ -130,35 +131,41 @@ func TestInsert(t *testing.T) {
|
|||
// TestToOne tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
func TestToOne(t *testing.T) {
|
||||
{{- $dot := . -}}
|
||||
{{- range $index, $table := .Tables}}
|
||||
{{- if $table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- range $table.FKeys -}}
|
||||
{{- $rel := textsFromForeignKey $dot.PkgName $dot.Tables $table . -}}
|
||||
t.Run("{{$rel.LocalTable.NameGo}}To{{$rel.ForeignTable.NameGo}}_{{$rel.Function.Name}}", test{{$rel.LocalTable.NameGo}}ToOne{{$rel.ForeignTable.NameGo}}_{{$rel.Function.Name}})
|
||||
{{- $txt := txtsFromFKey $dot.Tables $table . -}}
|
||||
t.Run("{{$txt.LocalTable.NameGo}}To{{$txt.ForeignTable.NameGo}}_{{$txt.Function.Name}}", test{{$txt.LocalTable.NameGo}}ToOne{{$txt.ForeignTable.NameGo}}_{{$txt.Function.Name}})
|
||||
{{end -}}{{- /* fkey range */ -}}
|
||||
{{- end -}}{{- /* if join table */ -}}
|
||||
{{- end -}}{{- /* tables range */ -}}
|
||||
}
|
||||
|
||||
// TestOneToOne tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
func TestOneToOne(t *testing.T) {
|
||||
{{- range $index, $table := .Tables}}
|
||||
{{- if $table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- range $table.ToOneRelationships -}}
|
||||
{{- $txt := txtsFromOneToOne $dot.Tables $table . -}}
|
||||
t.Run("{{$txt.LocalTable.NameGo}}To{{$txt.Function.Name}}", test{{$txt.LocalTable.NameGo}}OneToOne{{$txt.Function.Name}}_{{$txt.Function.Name}})
|
||||
{{end -}}{{- /* range */ -}}
|
||||
{{- end -}}{{- /* outer if join table */ -}}
|
||||
{{- end -}}{{- /* outer tables range */ -}}
|
||||
}
|
||||
|
||||
// TestToMany tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
func TestToMany(t *testing.T) {
|
||||
{{- $dot := .}}
|
||||
{{- range $index, $table := .Tables}}
|
||||
{{- $tableName := $table.Name | plural | titleCase -}}
|
||||
{{- if $table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- range $table.ToManyRelationships -}}
|
||||
{{- $rel := textsFromRelationship $dot.Tables $table . -}}
|
||||
{{- if (and .ForeignColumnUnique (not .ToJoinTable)) -}}
|
||||
{{- $oneToOne := textsFromOneToOneRelationship $dot.PkgName $dot.Tables $table . -}}
|
||||
t.Run("{{$oneToOne.LocalTable.NameGo}}OneToOne{{$oneToOne.ForeignTable.NameGo}}_{{$oneToOne.Function.Name}}", test{{$oneToOne.LocalTable.NameGo}}ToOne{{$oneToOne.ForeignTable.NameGo}}_{{$oneToOne.Function.Name}})
|
||||
{{else -}}
|
||||
t.Run("{{$rel.LocalTable.NameGo}}ToMany{{$rel.Function.Name}}", test{{$rel.LocalTable.NameGo}}ToMany{{$rel.Function.Name}})
|
||||
{{end -}}{{- /* if unique */ -}}
|
||||
{{- end -}}{{- /* range */ -}}
|
||||
{{- $txt := txtsFromToMany $dot.Tables $table . -}}
|
||||
t.Run("{{$txt.LocalTable.NameGo}}To{{$txt.Function.Name}}", test{{$txt.LocalTable.NameGo}}ToMany{{$txt.Function.Name}})
|
||||
{{end -}}{{- /* range */ -}}
|
||||
{{- end -}}{{- /* outer if join table */ -}}
|
||||
{{- end -}}{{- /* outer tables range */ -}}
|
||||
}
|
||||
|
@ -166,13 +173,12 @@ func TestToMany(t *testing.T) {
|
|||
// TestToOneSet tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
func TestToOneSet(t *testing.T) {
|
||||
{{- $dot := . -}}
|
||||
{{- range $index, $table := .Tables}}
|
||||
{{- if $table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- range $table.FKeys -}}
|
||||
{{- $rel := textsFromForeignKey $dot.PkgName $dot.Tables $table . -}}
|
||||
t.Run("{{$rel.LocalTable.NameGo}}To{{$rel.ForeignTable.NameGo}}_{{$rel.Function.Name}}", test{{$rel.LocalTable.NameGo}}ToOneSetOp{{$rel.ForeignTable.NameGo}}_{{$rel.Function.Name}})
|
||||
{{- $txt := txtsFromFKey $dot.Tables $table . -}}
|
||||
t.Run("{{$txt.LocalTable.NameGo}}To{{$txt.ForeignTable.NameGo}}_{{$txt.Function.Name}}", test{{$txt.LocalTable.NameGo}}ToOneSetOp{{$txt.ForeignTable.NameGo}}_{{$txt.Function.Name}})
|
||||
{{end -}}{{- /* fkey range */ -}}
|
||||
{{- end -}}{{- /* if join table */ -}}
|
||||
{{- end -}}{{- /* tables range */ -}}
|
||||
|
@ -181,35 +187,59 @@ func TestToOneSet(t *testing.T) {
|
|||
// TestToOneRemove tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
func TestToOneRemove(t *testing.T) {
|
||||
{{- $dot := . -}}
|
||||
{{- range $index, $table := .Tables}}
|
||||
{{- if $table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- range $table.FKeys -}}
|
||||
{{- $rel := textsFromForeignKey $dot.PkgName $dot.Tables $table . -}}
|
||||
{{- if $rel.ForeignKey.Nullable -}}
|
||||
t.Run("{{$rel.LocalTable.NameGo}}To{{$rel.ForeignTable.NameGo}}_{{$rel.Function.Name}}", test{{$rel.LocalTable.NameGo}}ToOneRemoveOp{{$rel.ForeignTable.NameGo}}_{{$rel.Function.Name}})
|
||||
{{- $txt := txtsFromFKey $dot.Tables $table . -}}
|
||||
{{- if $txt.ForeignKey.Nullable -}}
|
||||
t.Run("{{$txt.LocalTable.NameGo}}To{{$txt.ForeignTable.NameGo}}_{{$txt.Function.Name}}", test{{$txt.LocalTable.NameGo}}ToOneRemoveOp{{$txt.ForeignTable.NameGo}}_{{$txt.Function.Name}})
|
||||
{{end -}}{{- /* if foreign key nullable */ -}}
|
||||
{{- end -}}{{- /* fkey range */ -}}
|
||||
{{- end -}}{{- /* if join table */ -}}
|
||||
{{- end -}}{{- /* tables range */ -}}
|
||||
}
|
||||
|
||||
// TestOneToOneSet tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
func TestOneToOneSet(t *testing.T) {
|
||||
{{- range $index, $table := .Tables}}
|
||||
{{- if $table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- range $table.ToOneRelationships -}}
|
||||
{{- $txt := txtsFromOneToOne $dot.Tables $table . -}}
|
||||
t.Run("{{$txt.LocalTable.NameGo}}To{{$txt.Function.Name}}", test{{$txt.LocalTable.NameGo}}OneToOneSetOp{{$txt.Function.Name}}_{{$txt.Function.Name}})
|
||||
{{end -}}{{- /* range to one relationships */ -}}
|
||||
{{- end -}}{{- /* outer if join table */ -}}
|
||||
{{- end -}}{{- /* outer tables range */ -}}
|
||||
}
|
||||
|
||||
// TestOneToOneRemove tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
func TestOneToOneRemove(t *testing.T) {
|
||||
{{- range $index, $table := .Tables}}
|
||||
{{- if $table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- range $table.ToOneRelationships -}}
|
||||
{{- if .ForeignColumnNullable -}}
|
||||
{{- $txt := txtsFromOneToOne $dot.Tables $table . -}}
|
||||
t.Run("{{$txt.LocalTable.NameGo}}To{{$txt.Function.Name}}", test{{$txt.LocalTable.NameGo}}OneToOneRemoveOp{{$txt.Function.Name}}_{{$txt.Function.Name}})
|
||||
{{end -}}{{- /* if foreign column nullable */ -}}
|
||||
{{- end -}}{{- /* range */ -}}
|
||||
{{- end -}}{{- /* outer if join table */ -}}
|
||||
{{- end -}}{{- /* outer tables range */ -}}
|
||||
}
|
||||
|
||||
// TestToManyAdd tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
func TestToManyAdd(t *testing.T) {
|
||||
{{- $dot := .}}
|
||||
{{- range $index, $table := .Tables}}
|
||||
{{- $tableName := $table.Name | plural | titleCase -}}
|
||||
{{- if $table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- range $table.ToManyRelationships -}}
|
||||
{{- $rel := textsFromRelationship $dot.Tables $table . -}}
|
||||
{{- if (and .ForeignColumnUnique (not .ToJoinTable)) -}}
|
||||
{{- else -}}
|
||||
t.Run("{{$rel.LocalTable.NameGo}}ToMany{{$rel.Function.Name}}", test{{$rel.LocalTable.NameGo}}ToManyAddOp{{$rel.Function.Name}})
|
||||
{{end -}}{{- /* if unique */ -}}
|
||||
{{- end -}}{{- /* range */ -}}
|
||||
{{- $txt := txtsFromToMany $dot.Tables $table . -}}
|
||||
t.Run("{{$txt.LocalTable.NameGo}}To{{$txt.Function.Name}}", test{{$txt.LocalTable.NameGo}}ToManyAddOp{{$txt.Function.Name}})
|
||||
{{end -}}{{- /* range */ -}}
|
||||
{{- end -}}{{- /* outer if join table */ -}}
|
||||
{{- end -}}{{- /* outer tables range */ -}}
|
||||
}
|
||||
|
@ -217,22 +247,15 @@ func TestToManyAdd(t *testing.T) {
|
|||
// TestToManySet tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
func TestToManySet(t *testing.T) {
|
||||
{{- $dot := .}}
|
||||
{{- range $index, $table := .Tables}}
|
||||
{{- $tableName := $table.Name | plural | titleCase -}}
|
||||
{{- if $table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- range $table.ToManyRelationships -}}
|
||||
{{- if not .ForeignColumnNullable -}}
|
||||
{{- else -}}
|
||||
{{- $rel := textsFromRelationship $dot.Tables $table . -}}
|
||||
{{- if (and .ForeignColumnUnique (not .ToJoinTable)) -}}
|
||||
{{- $oneToOne := textsFromOneToOneRelationship $dot.PkgName $dot.Tables $table . -}}
|
||||
t.Run("{{$oneToOne.LocalTable.NameGo}}OneToOne{{$oneToOne.ForeignTable.NameGo}}_{{$oneToOne.Function.Name}}", test{{$oneToOne.LocalTable.NameGo}}ToOneSetOp{{$oneToOne.ForeignTable.NameGo}}_{{$oneToOne.Function.Name}})
|
||||
{{else -}}
|
||||
t.Run("{{$rel.LocalTable.NameGo}}ToMany{{$rel.Function.Name}}", test{{$rel.LocalTable.NameGo}}ToManySetOp{{$rel.Function.Name}})
|
||||
{{end -}}{{- /* if unique */ -}}
|
||||
{{- end -}}{{- /* if foreign column nullable */ -}}
|
||||
{{- $txt := txtsFromToMany $dot.Tables $table . -}}
|
||||
t.Run("{{$txt.LocalTable.NameGo}}To{{$txt.Function.Name}}", test{{$txt.LocalTable.NameGo}}ToManySetOp{{$txt.Function.Name}})
|
||||
{{end -}}{{- /* if foreign column nullable */ -}}
|
||||
{{- end -}}{{- /* range */ -}}
|
||||
{{- end -}}{{- /* outer if join table */ -}}
|
||||
{{- end -}}{{- /* outer tables range */ -}}
|
||||
|
@ -241,22 +264,15 @@ func TestToManySet(t *testing.T) {
|
|||
// TestToManyRemove tests cannot be run in parallel
|
||||
// or deadlocks can occur.
|
||||
func TestToManyRemove(t *testing.T) {
|
||||
{{- $dot := .}}
|
||||
{{- range $index, $table := .Tables}}
|
||||
{{- $tableName := $table.Name | plural | titleCase -}}
|
||||
{{- if $table.IsJoinTable -}}
|
||||
{{- else -}}
|
||||
{{- range $table.ToManyRelationships -}}
|
||||
{{- if not .ForeignColumnNullable -}}
|
||||
{{- else -}}
|
||||
{{- $rel := textsFromRelationship $dot.Tables $table . -}}
|
||||
{{- if (and .ForeignColumnUnique (not .ToJoinTable)) -}}
|
||||
{{- $oneToOne := textsFromOneToOneRelationship $dot.PkgName $dot.Tables $table . -}}
|
||||
t.Run("{{$oneToOne.LocalTable.NameGo}}OneToOne{{$oneToOne.ForeignTable.NameGo}}_{{$oneToOne.Function.Name}}", test{{$oneToOne.LocalTable.NameGo}}ToOneRemoveOp{{$oneToOne.ForeignTable.NameGo}}_{{$oneToOne.Function.Name}})
|
||||
{{else -}}
|
||||
t.Run("{{$rel.LocalTable.NameGo}}ToMany{{$rel.Function.Name}}", test{{$rel.LocalTable.NameGo}}ToManyRemoveOp{{$rel.Function.Name}})
|
||||
{{end -}}{{- /* if unique */ -}}
|
||||
{{- end -}}{{- /* if foreign column nullable */ -}}
|
||||
{{- $txt := txtsFromToMany $dot.Tables $table . -}}
|
||||
t.Run("{{$txt.LocalTable.NameGo}}To{{$txt.Function.Name}}", test{{$txt.LocalTable.NameGo}}ToManyRemoveOp{{$txt.Function.Name}})
|
||||
{{end -}}{{- /* if foreign column nullable */ -}}
|
||||
{{- end -}}{{- /* range */ -}}
|
||||
{{- end -}}{{- /* outer if join table */ -}}
|
||||
{{- end -}}{{- /* outer tables range */ -}}
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
{{- $varNameSingular := .Table.Name | singular | camelCase -}}
|
||||
var {{$varNameSingular}}DBTypes = map[string]string{{"{"}}{{.Table.Columns | columnDBTypes | makeStringMap}}{{"}"}}
|
||||
var (
|
||||
{{$varNameSingular}}DBTypes = map[string]string{{"{"}}{{.Table.Columns | columnDBTypes | makeStringMap}}{{"}"}}
|
||||
_ = bytes.MinRead
|
||||
)
|
||||
|
|
|
@ -27,7 +27,7 @@ func test{{$tableNamePlural}}Update(t *testing.T) {
|
|||
t.Error("want one record, got:", count)
|
||||
}
|
||||
|
||||
if err = randomize.Struct(seed, {{$varNameSingular}}, {{$varNameSingular}}DBTypes, true, {{$varNameSingular}}PrimaryKeyColumns...); err != nil {
|
||||
if err = randomize.Struct(seed, {{$varNameSingular}}, {{$varNameSingular}}DBTypes, true, {{$varNameSingular}}ColumnsWithDefault...); err != nil {
|
||||
t.Errorf("Unable to randomize {{$tableNameSingular}} struct: %s", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
{{- $varNamePlural := .Table.Name | plural | camelCase -}}
|
||||
{{- $varNameSingular := .Table.Name | singular | camelCase -}}
|
||||
func test{{$tableNamePlural}}Upsert(t *testing.T) {
|
||||
{{if not (eq .DriverName "postgres") -}}
|
||||
t.Skip("not implemented for {{.DriverName}}")
|
||||
{{end -}}
|
||||
t.Parallel()
|
||||
|
||||
seed := randomize.NewSeed()
|
||||
|
|
275
testdata/mysql_test_schema.sql
vendored
Normal file
275
testdata/mysql_test_schema.sql
vendored
Normal file
|
@ -0,0 +1,275 @@
|
|||
CREATE TABLE magic (
|
||||
id int PRIMARY KEY NOT NULL AUTO_INCREMENT,
|
||||
id_two int NOT NULL,
|
||||
id_three int,
|
||||
bool_zero bool,
|
||||
bool_one bool NULL,
|
||||
bool_two bool NOT NULL,
|
||||
bool_three bool NULL DEFAULT FALSE,
|
||||
bool_four bool NULL DEFAULT TRUE,
|
||||
bool_five bool NOT NULL DEFAULT FALSE,
|
||||
bool_six bool NOT NULL DEFAULT TRUE,
|
||||
string_zero VARCHAR(1),
|
||||
string_one VARCHAR(1) NULL,
|
||||
string_two VARCHAR(1) NOT NULL,
|
||||
string_three VARCHAR(1) NULL DEFAULT 'a',
|
||||
string_four VARCHAR(1) NOT NULL DEFAULT 'b',
|
||||
string_five VARCHAR(1000),
|
||||
string_six VARCHAR(1000) NULL,
|
||||
string_seven VARCHAR(1000) NOT NULL,
|
||||
string_eight VARCHAR(1000) NULL DEFAULT 'abcdefgh',
|
||||
string_nine VARCHAR(1000) NOT NULL DEFAULT 'abcdefgh',
|
||||
string_ten VARCHAR(1000) NULL DEFAULT '',
|
||||
string_eleven VARCHAR(1000) NOT NULL DEFAULT '',
|
||||
big_int_zero bigint,
|
||||
big_int_one bigint NULL,
|
||||
big_int_two bigint NOT NULL,
|
||||
big_int_three bigint NULL DEFAULT 111111,
|
||||
big_int_four bigint NOT NULL DEFAULT 222222,
|
||||
big_int_five bigint NULL DEFAULT 0,
|
||||
big_int_six bigint NOT NULL DEFAULT 0,
|
||||
int_zero int,
|
||||
int_one int NULL,
|
||||
int_two int NOT NULL,
|
||||
int_three int NULL DEFAULT 333333,
|
||||
int_four int NOT NULL DEFAULT 444444,
|
||||
int_five int NULL DEFAULT 0,
|
||||
int_six int NOT NULL DEFAULT 0,
|
||||
float_zero float,
|
||||
float_one float,
|
||||
float_two float(2,1),
|
||||
float_three float(2,1),
|
||||
float_four float(2,1) NULL,
|
||||
float_five float(2,1) NOT NULL,
|
||||
float_six float(2,1) NULL DEFAULT 1.1,
|
||||
float_seven float(2,1) NOT NULL DEFAULT 1.1,
|
||||
float_eight float(2,1) NULL DEFAULT 0.0,
|
||||
float_nine float(2,1) NULL DEFAULT 0.0,
|
||||
bytea_zero binary,
|
||||
bytea_one binary NULL,
|
||||
bytea_two binary NOT NULL,
|
||||
bytea_three binary NOT NULL DEFAULT 'a',
|
||||
bytea_four binary NULL DEFAULT 'b',
|
||||
bytea_five binary(100) NOT NULL DEFAULT 'abcdefghabcdefghabcdefgh',
|
||||
bytea_six binary(100) NULL DEFAULT 'hgfedcbahgfedcbahgfedcba',
|
||||
bytea_seven binary NOT NULL DEFAULT '',
|
||||
bytea_eight binary NOT NULL DEFAULT '',
|
||||
time_zero timestamp,
|
||||
time_one date,
|
||||
time_two timestamp NULL DEFAULT NULL,
|
||||
time_three timestamp NULL,
|
||||
time_five timestamp NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
time_nine timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
time_eleven date NULL,
|
||||
time_twelve date NOT NULL,
|
||||
time_fifteen date NULL DEFAULT '19990108',
|
||||
time_sixteen date NOT NULL DEFAULT '1999-01-08'
|
||||
);
|
||||
|
||||
CREATE TABLE magicest (
|
||||
id int primary key not null auto_increment,
|
||||
aa json NULL,
|
||||
bb json NOT NULL,
|
||||
kk double precision NULL,
|
||||
ll double precision NOT NULL,
|
||||
mm tinyint NULL,
|
||||
nn tinyint NOT NULL,
|
||||
oo tinyint(1) NULL,
|
||||
pp tinyint(1) NOT NULL,
|
||||
qq smallint NULL,
|
||||
rr smallint NOT NULL,
|
||||
ss mediumint NULL,
|
||||
tt mediumint NOT NULL,
|
||||
uu bigint NULL,
|
||||
vv bigint NOT NULL,
|
||||
ww float NULL,
|
||||
xx float NOT NULL,
|
||||
yy double NULL,
|
||||
zz double NOT NULL,
|
||||
aaa double precision NULL,
|
||||
bbb double precision NOT NULL,
|
||||
ccc real NULL,
|
||||
ddd real NOT NULL,
|
||||
eee boolean NULL,
|
||||
fff boolean NOT NULL,
|
||||
ggg date NULL,
|
||||
hhh date NOT NULL,
|
||||
iii datetime NULL,
|
||||
jjj datetime NOT NULL,
|
||||
kkk timestamp NULL,
|
||||
lll timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
mmm binary NULL,
|
||||
nnn binary NOT NULL,
|
||||
ooo varbinary(100) NULL,
|
||||
ppp varbinary(100) NOT NULL,
|
||||
qqq tinyblob NULL,
|
||||
rrr tinyblob NOT NULL,
|
||||
sss blob NULL,
|
||||
ttt blob NOT NULL,
|
||||
uuu mediumblob NULL,
|
||||
vvv mediumblob NOT NULL,
|
||||
www longblob NULL,
|
||||
xxx longblob NOT NULL,
|
||||
yyy varchar(100) NULL,
|
||||
zzz varchar(100) NOT NULL,
|
||||
aaaa char NULL,
|
||||
bbbb char NOT NULL,
|
||||
cccc text NULL,
|
||||
dddd text NOT NULL
|
||||
);
|
||||
|
||||
create table owner (
|
||||
id int primary key not null auto_increment,
|
||||
name varchar(255) not null
|
||||
);
|
||||
|
||||
create table cats (
|
||||
id int primary key not null auto_increment,
|
||||
name varchar(255) not null,
|
||||
owner_id int references owner (id)
|
||||
);
|
||||
|
||||
create table toys (
|
||||
id int primary key not null auto_increment,
|
||||
name varchar(255) not null
|
||||
);
|
||||
|
||||
create table cat_toys (
|
||||
cat_id int not null references cats (id),
|
||||
toy_id int not null references toys (id),
|
||||
primary key (cat_id, toy_id)
|
||||
);
|
||||
|
||||
create table dog_toys (
|
||||
dog_id int not null,
|
||||
toy_id int not null,
|
||||
primary key (dog_id, toy_id)
|
||||
);
|
||||
|
||||
create table dragon_toys (
|
||||
dragon_id varchar(100),
|
||||
toy_id varchar(100),
|
||||
primary key (dragon_id, toy_id)
|
||||
);
|
||||
|
||||
create table spider_toys (
|
||||
spider_id varchar(100) primary key,
|
||||
name varchar(100)
|
||||
);
|
||||
|
||||
create table pals (
|
||||
pal varchar(100) primary key
|
||||
);
|
||||
|
||||
create table friend (
|
||||
friend varchar(100) primary key
|
||||
);
|
||||
|
||||
create table bro (
|
||||
bros varchar(100) primary key
|
||||
);
|
||||
|
||||
create table enemies (
|
||||
enemies varchar(100) primary key
|
||||
);
|
||||
|
||||
create table tigers (
|
||||
id binary primary key,
|
||||
name binary null
|
||||
);
|
||||
|
||||
create table elephants (
|
||||
id binary primary key,
|
||||
name binary not null,
|
||||
tiger_id binary null unique,
|
||||
foreign key (tiger_id) references tigers (id)
|
||||
);
|
||||
|
||||
create table wolves (
|
||||
id binary primary key,
|
||||
name binary not null,
|
||||
tiger_id binary not null unique,
|
||||
foreign key (tiger_id) references tigers (id)
|
||||
);
|
||||
|
||||
create table ants (
|
||||
id binary primary key,
|
||||
name binary not null,
|
||||
tiger_id binary not null,
|
||||
foreign key (tiger_id) references tigers (id)
|
||||
);
|
||||
|
||||
create table worms (
|
||||
id binary primary key,
|
||||
name binary not null,
|
||||
tiger_id binary null,
|
||||
foreign key (tiger_id) references tigers (id)
|
||||
);
|
||||
|
||||
create table pilots (
|
||||
id int primary key not null auto_increment,
|
||||
name varchar(255)
|
||||
);
|
||||
|
||||
create table airports (
|
||||
id int primary key not null auto_increment,
|
||||
name varchar(255)
|
||||
);
|
||||
|
||||
create table languages (
|
||||
id int primary key not null auto_increment,
|
||||
name varchar(255)
|
||||
);
|
||||
|
||||
create table jets (
|
||||
id int primary key not null auto_increment,
|
||||
name varchar(255),
|
||||
pilot_id integer,
|
||||
airport_id integer,
|
||||
|
||||
foreign key (pilot_id) references pilots (id),
|
||||
foreign key (airport_id) references airports (id)
|
||||
);
|
||||
|
||||
create table pilot_languages (
|
||||
pilot_id integer not null,
|
||||
language_id integer not null,
|
||||
|
||||
primary key (pilot_id, language_id),
|
||||
foreign key (pilot_id) references pilots (id),
|
||||
foreign key (language_id) references languages (id)
|
||||
);
|
||||
|
||||
create table byte_pilots (
|
||||
id binary primary key not null,
|
||||
name varchar(255)
|
||||
);
|
||||
|
||||
create table byte_airports (
|
||||
id binary primary key not null,
|
||||
name varchar(255)
|
||||
);
|
||||
|
||||
create table byte_languages (
|
||||
id binary primary key not null,
|
||||
name varchar(255)
|
||||
);
|
||||
|
||||
create table byte_jets (
|
||||
id binary primary key not null,
|
||||
name varchar(255),
|
||||
byte_pilot_id binary unique,
|
||||
byte_airport_id binary,
|
||||
|
||||
foreign key (byte_pilot_id) references byte_pilots (id),
|
||||
foreign key (byte_airport_id) references byte_airports (id)
|
||||
);
|
||||
|
||||
create table byte_pilot_languages (
|
||||
byte_pilot_id binary not null,
|
||||
byte_language_id binary not null,
|
||||
|
||||
primary key (byte_pilot_id, byte_language_id),
|
||||
foreign key (byte_pilot_id) references byte_pilots (id),
|
||||
foreign key (byte_language_id) references byte_languages (id)
|
||||
);
|
315
testdata/postgres_test_schema.sql
vendored
Normal file
315
testdata/postgres_test_schema.sql
vendored
Normal file
|
@ -0,0 +1,315 @@
|
|||
CREATE TABLE magic (
|
||||
id serial PRIMARY KEY NOT NULL,
|
||||
id_two serial NOT NULL,
|
||||
id_three serial,
|
||||
|
||||
bool_zero bool,
|
||||
bool_one bool NULL,
|
||||
bool_two bool NOT NULL,
|
||||
bool_three bool NULL DEFAULT FALSE,
|
||||
bool_four bool NULL DEFAULT TRUE,
|
||||
bool_five bool NOT NULL DEFAULT FALSE,
|
||||
bool_six bool NOT NULL DEFAULT TRUE,
|
||||
|
||||
string_zero VARCHAR(1),
|
||||
string_one VARCHAR(1) NULL,
|
||||
string_two VARCHAR(1) NOT NULL,
|
||||
string_three VARCHAR(1) NULL DEFAULT 'a',
|
||||
string_four VARCHAR(1) NOT NULL DEFAULT 'b',
|
||||
string_five VARCHAR(1000),
|
||||
string_six VARCHAR(1000) NULL,
|
||||
string_seven VARCHAR(1000) NOT NULL,
|
||||
string_eight VARCHAR(1000) NULL DEFAULT 'abcdefgh',
|
||||
string_nine VARCHAR(1000) NOT NULL DEFAULT 'abcdefgh',
|
||||
string_ten VARCHAR(1000) NULL DEFAULT '',
|
||||
string_eleven VARCHAR(1000) NOT NULL DEFAULT '',
|
||||
|
||||
big_int_zero bigint,
|
||||
big_int_one bigint NULL,
|
||||
big_int_two bigint NOT NULL,
|
||||
big_int_three bigint NULL DEFAULT 111111,
|
||||
big_int_four bigint NOT NULL DEFAULT 222222,
|
||||
big_int_five bigint NULL DEFAULT 0,
|
||||
big_int_six bigint NOT NULL DEFAULT 0,
|
||||
|
||||
int_zero int,
|
||||
int_one int NULL,
|
||||
int_two int NOT NULL,
|
||||
int_three int NULL DEFAULT 333333,
|
||||
int_four int NOT NULL DEFAULT 444444,
|
||||
int_five int NULL DEFAULT 0,
|
||||
int_six int NOT NULL DEFAULT 0,
|
||||
|
||||
float_zero decimal,
|
||||
float_one numeric,
|
||||
float_two numeric(2,1),
|
||||
float_three numeric(2,1),
|
||||
float_four numeric(2,1) NULL,
|
||||
float_five numeric(2,1) NOT NULL,
|
||||
float_six numeric(2,1) NULL DEFAULT 1.1,
|
||||
float_seven numeric(2,1) NOT NULL DEFAULT 1.1,
|
||||
float_eight numeric(2,1) NULL DEFAULT 0.0,
|
||||
float_nine numeric(2,1) NULL DEFAULT 0.0,
|
||||
|
||||
bytea_zero bytea,
|
||||
bytea_one bytea NULL,
|
||||
bytea_two bytea NOT NULL,
|
||||
bytea_three bytea NOT NULL DEFAULT 'a',
|
||||
bytea_four bytea NULL DEFAULT 'b',
|
||||
bytea_five bytea NOT NULL DEFAULT 'abcdefghabcdefghabcdefgh',
|
||||
bytea_six bytea NULL DEFAULT 'hgfedcbahgfedcbahgfedcba',
|
||||
bytea_seven bytea NOT NULL DEFAULT '',
|
||||
bytea_eight bytea NOT NULL DEFAULT '',
|
||||
|
||||
time_zero timestamp,
|
||||
time_one date,
|
||||
time_two timestamp NULL DEFAULT NULL,
|
||||
time_three timestamp NULL,
|
||||
time_four timestamp NOT NULL,
|
||||
time_five timestamp NULL DEFAULT '1999-01-08 04:05:06.789',
|
||||
time_six timestamp NULL DEFAULT '1999-01-08 04:05:06.789 -8:00',
|
||||
time_seven timestamp NULL DEFAULT 'January 8 04:05:06 1999 PST',
|
||||
time_eight timestamp NOT NULL DEFAULT '1999-01-08 04:05:06.789',
|
||||
time_nine timestamp NOT NULL DEFAULT '1999-01-08 04:05:06.789 -8:00',
|
||||
time_ten timestamp NOT NULL DEFAULT 'January 8 04:05:06 1999 PST',
|
||||
time_eleven date NULL,
|
||||
time_twelve date NOT NULL,
|
||||
time_thirteen date NULL DEFAULT '1999-01-08',
|
||||
time_fourteen date NULL DEFAULT 'January 8, 1999',
|
||||
time_fifteen date NULL DEFAULT '19990108',
|
||||
time_sixteen date NOT NULL DEFAULT '1999-01-08',
|
||||
time_seventeen date NOT NULL DEFAULT 'January 8, 1999',
|
||||
time_eighteen date NOT NULL DEFAULT '19990108',
|
||||
|
||||
uuid_zero uuid,
|
||||
uuid_one uuid NULL,
|
||||
uuid_two uuid NULL DEFAULT NULL,
|
||||
uuid_three uuid NOT NULL,
|
||||
uuid_four uuid NULL DEFAULT '6ba7b810-9dad-11d1-80b4-00c04fd430c8',
|
||||
uuid_five uuid NOT NULL DEFAULT '6ba7b810-9dad-11d1-80b4-00c04fd430c8',
|
||||
|
||||
strange_one integer DEFAULT '5'::integer,
|
||||
strange_two varchar(1000) DEFAULT 5::varchar,
|
||||
strange_three timestamp without time zone default (now() at time zone 'utc'),
|
||||
strange_four timestamp with time zone default (now() at time zone 'utc'),
|
||||
strange_five interval NOT NULL DEFAULT '21 days',
|
||||
strange_six interval NULL DEFAULT '23 hours',
|
||||
|
||||
aa json NULL,
|
||||
bb json NOT NULL,
|
||||
cc jsonb NULL,
|
||||
dd jsonb NOT NULL,
|
||||
ee box NULL,
|
||||
ff box NOT NULL,
|
||||
gg cidr NULL,
|
||||
hh cidr NOT NULL,
|
||||
ii circle NULL,
|
||||
jj circle NOT NULL,
|
||||
kk double precision NULL,
|
||||
ll double precision NOT NULL,
|
||||
mm inet NULL,
|
||||
nn inet NOT NULL,
|
||||
oo line NULL,
|
||||
pp line NOT NULL,
|
||||
qq lseg NULL,
|
||||
rr lseg NOT NULL,
|
||||
ss macaddr NULL,
|
||||
tt macaddr NOT NULL,
|
||||
uu money NULL,
|
||||
vv money NOT NULL,
|
||||
ww path NULL,
|
||||
xx path NOT NULL,
|
||||
yy pg_lsn NULL,
|
||||
zz pg_lsn NOT NULL,
|
||||
aaa point NULL,
|
||||
bbb point NOT NULL,
|
||||
ccc polygon NULL,
|
||||
ddd polygon NOT NULL,
|
||||
eee tsquery NULL,
|
||||
fff tsquery NOT NULL,
|
||||
ggg tsvector NULL,
|
||||
hhh tsvector NOT NULL,
|
||||
iii txid_snapshot NULL,
|
||||
jjj txid_snapshot NOT NULL,
|
||||
kkk xml NULL,
|
||||
lll xml NOT NULL
|
||||
);
|
||||
|
||||
create table owner (
|
||||
id serial primary key not null,
|
||||
name varchar(255) not null
|
||||
);
|
||||
|
||||
create table cats (
|
||||
id serial primary key not null,
|
||||
name varchar(255) not null,
|
||||
owner_id int references owner (id)
|
||||
);
|
||||
|
||||
create table toys (
|
||||
id serial primary key not null,
|
||||
name varchar(255) not null
|
||||
);
|
||||
|
||||
create table cat_toys (
|
||||
cat_id int not null references cats (id),
|
||||
toy_id int not null references toys (id),
|
||||
primary key (cat_id, toy_id)
|
||||
);
|
||||
|
||||
create table dog_toys (
|
||||
dog_id int not null,
|
||||
toy_id int not null,
|
||||
primary key (dog_id, toy_id)
|
||||
);
|
||||
|
||||
create table dragon_toys (
|
||||
dragon_id uuid,
|
||||
toy_id uuid,
|
||||
primary key (dragon_id, toy_id)
|
||||
);
|
||||
|
||||
create table spider_toys (
|
||||
spider_id uuid,
|
||||
name character varying,
|
||||
primary key (spider_id)
|
||||
);
|
||||
|
||||
create table pals (
|
||||
pal character varying,
|
||||
primary key (pal)
|
||||
);
|
||||
|
||||
create table friend (
|
||||
friend character varying,
|
||||
primary key (friend)
|
||||
);
|
||||
|
||||
create table bro (
|
||||
bros character varying,
|
||||
primary key (bros)
|
||||
);
|
||||
|
||||
create table enemies (
|
||||
enemies character varying,
|
||||
primary key (enemies)
|
||||
);
|
||||
|
||||
create table fun_arrays (
|
||||
id serial,
|
||||
fun_one integer[] null,
|
||||
fun_two integer[] not null,
|
||||
fun_three boolean[] null,
|
||||
fun_four boolean[] not null,
|
||||
fun_five varchar[] null,
|
||||
fun_six varchar[] not null,
|
||||
fun_seven decimal[] null,
|
||||
fun_eight decimal[] not null,
|
||||
fun_nine bytea[] null,
|
||||
fun_ten bytea[] not null,
|
||||
fun_eleven jsonb[] null,
|
||||
fun_twelve jsonb[] not null,
|
||||
fun_thirteen json[] null,
|
||||
fun_fourteen json[] not null,
|
||||
primary key (id)
|
||||
);
|
||||
|
||||
create table tigers (
|
||||
id bytea primary key,
|
||||
name bytea null
|
||||
);
|
||||
|
||||
create table elephants (
|
||||
id bytea primary key,
|
||||
name bytea not null,
|
||||
tiger_id bytea null unique,
|
||||
foreign key (tiger_id) references tigers (id)
|
||||
);
|
||||
|
||||
create table wolves (
|
||||
id bytea primary key,
|
||||
name bytea not null,
|
||||
tiger_id bytea not null unique,
|
||||
foreign key (tiger_id) references tigers (id)
|
||||
);
|
||||
|
||||
create table ants (
|
||||
id bytea primary key,
|
||||
name bytea not null,
|
||||
tiger_id bytea not null,
|
||||
foreign key (tiger_id) references tigers (id)
|
||||
);
|
||||
|
||||
create table worms (
|
||||
id bytea primary key,
|
||||
name bytea not null,
|
||||
tiger_id bytea null,
|
||||
foreign key (tiger_id) references tigers (id)
|
||||
);
|
||||
|
||||
create table pilots (
|
||||
id serial primary key not null,
|
||||
name character varying
|
||||
);
|
||||
|
||||
create table airports (
|
||||
id serial primary key not null,
|
||||
name character varying
|
||||
);
|
||||
|
||||
create table languages (
|
||||
id serial primary key not null,
|
||||
name character varying
|
||||
);
|
||||
|
||||
create table jets (
|
||||
id serial primary key not null,
|
||||
name character varying,
|
||||
pilot_id integer,
|
||||
airport_id integer,
|
||||
foreign key (pilot_id) references pilots (id),
|
||||
foreign key (airport_id) references airports (id)
|
||||
);
|
||||
|
||||
create table pilot_languages (
|
||||
pilot_id integer not null,
|
||||
language_id integer not null,
|
||||
|
||||
primary key (pilot_id, language_id),
|
||||
foreign key (pilot_id) references pilots (id),
|
||||
foreign key (language_id) references languages (id)
|
||||
);
|
||||
|
||||
create table byte_pilots (
|
||||
id bytea primary key not null,
|
||||
name character varying
|
||||
);
|
||||
|
||||
create table byte_airports (
|
||||
id bytea primary key not null,
|
||||
name character varying
|
||||
);
|
||||
|
||||
create table byte_languages (
|
||||
id bytea primary key not null,
|
||||
name character varying
|
||||
);
|
||||
|
||||
create table byte_jets (
|
||||
id bytea primary key not null,
|
||||
name character varying,
|
||||
byte_pilot_id bytea unique,
|
||||
byte_airport_id bytea,
|
||||
|
||||
foreign key (byte_pilot_id) references byte_pilots (id),
|
||||
foreign key (byte_airport_id) references byte_airports (id)
|
||||
);
|
||||
|
||||
create table byte_pilot_languages (
|
||||
byte_pilot_id bytea not null,
|
||||
byte_language_id bytea not null,
|
||||
|
||||
primary key (byte_pilot_id, byte_language_id),
|
||||
foreign key (byte_pilot_id) references byte_pilots (id),
|
||||
foreign key (byte_language_id) references byte_languages (id)
|
||||
);
|
215
testdata/test_schema.sql
vendored
215
testdata/test_schema.sql
vendored
|
@ -1,215 +0,0 @@
|
|||
CREATE TABLE magic (
|
||||
id serial PRIMARY KEY NOT NULL,
|
||||
id_two serial NOT NULL,
|
||||
id_three serial,
|
||||
|
||||
bool_zero bool,
|
||||
bool_one bool NULL,
|
||||
bool_two bool NOT NULL,
|
||||
bool_three bool NULL DEFAULT FALSE,
|
||||
bool_four bool NULL DEFAULT TRUE,
|
||||
bool_five bool NOT NULL DEFAULT FALSE,
|
||||
bool_six bool NOT NULL DEFAULT TRUE,
|
||||
|
||||
string_zero VARCHAR(1),
|
||||
string_one VARCHAR(1) NULL,
|
||||
string_two VARCHAR(1) NOT NULL,
|
||||
string_three VARCHAR(1) NULL DEFAULT 'a',
|
||||
string_four VARCHAR(1) NOT NULL DEFAULT 'b',
|
||||
string_five VARCHAR(1000),
|
||||
string_six VARCHAR(1000) NULL,
|
||||
string_seven VARCHAR(1000) NOT NULL,
|
||||
string_eight VARCHAR(1000) NULL DEFAULT 'abcdefgh',
|
||||
string_nine VARCHAR(1000) NOT NULL DEFAULT 'abcdefgh',
|
||||
string_ten VARCHAR(1000) NULL DEFAULT '',
|
||||
string_eleven VARCHAR(1000) NOT NULL DEFAULT '',
|
||||
|
||||
big_int_zero bigint,
|
||||
big_int_one bigint NULL,
|
||||
big_int_two bigint NOT NULL,
|
||||
big_int_three bigint NULL DEFAULT 111111,
|
||||
big_int_four bigint NOT NULL DEFAULT 222222,
|
||||
big_int_five bigint NULL DEFAULT 0,
|
||||
big_int_six bigint NOT NULL DEFAULT 0,
|
||||
|
||||
int_zero int,
|
||||
int_one int NULL,
|
||||
int_two int NOT NULL,
|
||||
int_three int NULL DEFAULT 333333,
|
||||
int_four int NOT NULL DEFAULT 444444,
|
||||
int_five int NULL DEFAULT 0,
|
||||
int_six int NOT NULL DEFAULT 0,
|
||||
|
||||
float_zero decimal,
|
||||
float_one numeric,
|
||||
float_two numeric(2,1),
|
||||
float_three numeric(2,1),
|
||||
float_four numeric(2,1) NULL,
|
||||
float_five numeric(2,1) NOT NULL,
|
||||
float_six numeric(2,1) NULL DEFAULT 1.1,
|
||||
float_seven numeric(2,1) NOT NULL DEFAULT 1.1,
|
||||
float_eight numeric(2,1) NULL DEFAULT 0.0,
|
||||
float_nine numeric(2,1) NULL DEFAULT 0.0,
|
||||
|
||||
bytea_zero bytea,
|
||||
bytea_one bytea NULL,
|
||||
bytea_two bytea NOT NULL,
|
||||
bytea_three bytea NOT NULL DEFAULT 'a',
|
||||
bytea_four bytea NULL DEFAULT 'b',
|
||||
bytea_five bytea NOT NULL DEFAULT 'abcdefghabcdefghabcdefgh',
|
||||
bytea_six bytea NULL DEFAULT 'hgfedcbahgfedcbahgfedcba',
|
||||
bytea_seven bytea NOT NULL DEFAULT '',
|
||||
bytea_eight bytea NOT NULL DEFAULT '',
|
||||
|
||||
time_zero timestamp,
|
||||
time_one date,
|
||||
time_two timestamp NULL DEFAULT NULL,
|
||||
time_three timestamp NULL,
|
||||
time_four timestamp NOT NULL,
|
||||
time_five timestamp NULL DEFAULT '1999-01-08 04:05:06.789',
|
||||
time_six timestamp NULL DEFAULT '1999-01-08 04:05:06.789 -8:00',
|
||||
time_seven timestamp NULL DEFAULT 'January 8 04:05:06 1999 PST',
|
||||
time_eight timestamp NOT NULL DEFAULT '1999-01-08 04:05:06.789',
|
||||
time_nine timestamp NOT NULL DEFAULT '1999-01-08 04:05:06.789 -8:00',
|
||||
time_ten timestamp NOT NULL DEFAULT 'January 8 04:05:06 1999 PST',
|
||||
time_eleven date NULL,
|
||||
time_twelve date NOT NULL,
|
||||
time_thirteen date NULL DEFAULT '1999-01-08',
|
||||
time_fourteen date NULL DEFAULT 'January 8, 1999',
|
||||
time_fifteen date NULL DEFAULT '19990108',
|
||||
time_sixteen date NOT NULL DEFAULT '1999-01-08',
|
||||
time_seventeen date NOT NULL DEFAULT 'January 8, 1999',
|
||||
time_eighteen date NOT NULL DEFAULT '19990108',
|
||||
|
||||
uuid_zero uuid,
|
||||
uuid_one uuid NULL,
|
||||
uuid_two uuid NULL DEFAULT NULL,
|
||||
uuid_three uuid NOT NULL,
|
||||
uuid_four uuid NULL DEFAULT '6ba7b810-9dad-11d1-80b4-00c04fd430c8',
|
||||
uuid_five uuid NOT NULL DEFAULT '6ba7b810-9dad-11d1-80b4-00c04fd430c8',
|
||||
|
||||
strange_one integer DEFAULT '5'::integer,
|
||||
strange_two varchar(1000) DEFAULT 5::varchar,
|
||||
strange_three timestamp without time zone default (now() at time zone 'utc'),
|
||||
strange_four timestamp with time zone default (now() at time zone 'utc'),
|
||||
strange_five interval NOT NULL DEFAULT '21 days',
|
||||
strange_six interval NULL DEFAULT '23 hours',
|
||||
|
||||
aa json NULL,
|
||||
bb json NOT NULL,
|
||||
cc jsonb NULL,
|
||||
dd jsonb NOT NULL,
|
||||
ee box NULL,
|
||||
ff box NOT NULL,
|
||||
gg cidr NULL,
|
||||
hh cidr NOT NULL,
|
||||
ii circle NULL,
|
||||
jj circle NOT NULL,
|
||||
kk double precision NULL,
|
||||
ll double precision NOT NULL,
|
||||
mm inet NULL,
|
||||
nn inet NOT NULL,
|
||||
oo line NULL,
|
||||
pp line NOT NULL,
|
||||
qq lseg NULL,
|
||||
rr lseg NOT NULL,
|
||||
ss macaddr NULL,
|
||||
tt macaddr NOT NULL,
|
||||
uu money NULL,
|
||||
vv money NOT NULL,
|
||||
ww path NULL,
|
||||
xx path NOT NULL,
|
||||
yy pg_lsn NULL,
|
||||
zz pg_lsn NOT NULL,
|
||||
aaa point NULL,
|
||||
bbb point NOT NULL,
|
||||
ccc polygon NULL,
|
||||
ddd polygon NOT NULL,
|
||||
eee tsquery NULL,
|
||||
fff tsquery NOT NULL,
|
||||
ggg tsvector NULL,
|
||||
hhh tsvector NOT NULL,
|
||||
iii txid_snapshot NULL,
|
||||
jjj txid_snapshot NOT NULL,
|
||||
kkk xml NULL,
|
||||
lll xml NOT NULL
|
||||
);
|
||||
|
||||
create table owner (
|
||||
id serial primary key not null,
|
||||
name varchar(255) not null
|
||||
);
|
||||
|
||||
create table cats (
|
||||
id serial primary key not null,
|
||||
name varchar(255) not null,
|
||||
owner_id int references owner (id)
|
||||
);
|
||||
|
||||
create table toys (
|
||||
id serial primary key not null,
|
||||
name varchar(255) not null
|
||||
);
|
||||
|
||||
create table cat_toys (
|
||||
cat_id int not null references cats (id),
|
||||
toy_id int not null references toys (id),
|
||||
primary key (cat_id, toy_id)
|
||||
);
|
||||
|
||||
create table dog_toys (
|
||||
dog_id int not null,
|
||||
toy_id int not null,
|
||||
primary key (dog_id, toy_id)
|
||||
);
|
||||
|
||||
create table dragon_toys (
|
||||
dragon_id uuid,
|
||||
toy_id uuid,
|
||||
primary key (dragon_id, toy_id)
|
||||
);
|
||||
|
||||
create table spider_toys (
|
||||
spider_id uuid,
|
||||
name character varying,
|
||||
primary key (spider_id)
|
||||
);
|
||||
|
||||
create table pals (
|
||||
pal character varying,
|
||||
primary key (pal)
|
||||
);
|
||||
|
||||
create table friend (
|
||||
friend character varying,
|
||||
primary key (friend)
|
||||
);
|
||||
|
||||
create table bro (
|
||||
bros character varying,
|
||||
primary key (bros)
|
||||
);
|
||||
|
||||
create table enemies (
|
||||
enemies character varying,
|
||||
primary key (enemies)
|
||||
);
|
||||
|
||||
create table fun_arrays (
|
||||
id serial,
|
||||
fun_one integer[] null,
|
||||
fun_two integer[] not null,
|
||||
fun_three boolean[] null,
|
||||
fun_four boolean[] not null,
|
||||
fun_five varchar[] null,
|
||||
fun_six varchar[] not null,
|
||||
fun_seven decimal[] null,
|
||||
fun_eight decimal[] not null,
|
||||
fun_nine bytea[] null,
|
||||
fun_ten bytea[] not null,
|
||||
fun_eleven jsonb[] null,
|
||||
fun_twelve jsonb[] not null,
|
||||
fun_thirteen json[] null,
|
||||
fun_fourteen json[] not null,
|
||||
primary key (id)
|
||||
)
|
|
@ -8,8 +8,9 @@ import (
|
|||
"github.com/vattle/sqlboiler/strmangle"
|
||||
)
|
||||
|
||||
// RelationshipToOneTexts contains text that will be used by templates.
|
||||
type RelationshipToOneTexts struct {
|
||||
// TxtToOne contains text that will be used by templates for a one-to-many or
|
||||
// a one-to-one relationship.
|
||||
type TxtToOne struct {
|
||||
ForeignKey bdb.ForeignKey
|
||||
|
||||
LocalTable struct {
|
||||
|
@ -26,21 +27,20 @@ type RelationshipToOneTexts struct {
|
|||
}
|
||||
|
||||
Function struct {
|
||||
PackageName string
|
||||
Name string
|
||||
ForeignName string
|
||||
|
||||
Varname string
|
||||
Receiver string
|
||||
OneToOne bool
|
||||
Varname string
|
||||
Receiver string
|
||||
UsesBytes bool
|
||||
|
||||
LocalAssignment string
|
||||
ForeignAssignment string
|
||||
}
|
||||
}
|
||||
|
||||
func textsFromForeignKey(packageName string, tables []bdb.Table, table bdb.Table, fkey bdb.ForeignKey) RelationshipToOneTexts {
|
||||
r := RelationshipToOneTexts{}
|
||||
func txtsFromFKey(tables []bdb.Table, table bdb.Table, fkey bdb.ForeignKey) TxtToOne {
|
||||
r := TxtToOne{}
|
||||
|
||||
r.ForeignKey = fkey
|
||||
|
||||
|
@ -53,7 +53,6 @@ func textsFromForeignKey(packageName string, tables []bdb.Table, table bdb.Table
|
|||
r.ForeignTable.ColumnName = fkey.ForeignColumn
|
||||
r.ForeignTable.ColumnNameGo = strmangle.TitleCase(strmangle.Singular(fkey.ForeignColumn))
|
||||
|
||||
r.Function.PackageName = packageName
|
||||
r.Function.Name = strmangle.TitleCase(strmangle.Singular(strings.TrimSuffix(fkey.Column, "_id")))
|
||||
plurality := strmangle.Plural
|
||||
if fkey.Unique {
|
||||
|
@ -70,40 +69,51 @@ func textsFromForeignKey(packageName string, tables []bdb.Table, table bdb.Table
|
|||
r.Function.LocalAssignment = strmangle.TitleCase(fkey.Column)
|
||||
}
|
||||
|
||||
foreignTable := bdb.GetTable(tables, fkey.ForeignTable)
|
||||
foreignColumn := foreignTable.GetColumn(fkey.ForeignColumn)
|
||||
|
||||
if fkey.ForeignColumnNullable {
|
||||
foreignTable := bdb.GetTable(tables, fkey.ForeignTable)
|
||||
col := foreignTable.GetColumn(fkey.ForeignColumn)
|
||||
r.Function.ForeignAssignment = fmt.Sprintf("%s.%s", strmangle.TitleCase(fkey.ForeignColumn), strings.TrimPrefix(col.Type, "null."))
|
||||
r.Function.ForeignAssignment = fmt.Sprintf("%s.%s", strmangle.TitleCase(fkey.ForeignColumn), strings.TrimPrefix(foreignColumn.Type, "null."))
|
||||
} else {
|
||||
r.Function.ForeignAssignment = strmangle.TitleCase(fkey.ForeignColumn)
|
||||
}
|
||||
|
||||
r.Function.UsesBytes = foreignColumn.Type == "[]byte"
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func textsFromOneToOneRelationship(packageName string, tables []bdb.Table, table bdb.Table, toMany bdb.ToManyRelationship) RelationshipToOneTexts {
|
||||
func txtsFromOneToOne(tables []bdb.Table, table bdb.Table, oneToOne bdb.ToOneRelationship) TxtToOne {
|
||||
fkey := bdb.ForeignKey{
|
||||
Table: toMany.Table,
|
||||
Table: oneToOne.Table,
|
||||
Name: "none",
|
||||
Column: toMany.Column,
|
||||
Nullable: toMany.Nullable,
|
||||
Unique: toMany.Unique,
|
||||
Column: oneToOne.Column,
|
||||
Nullable: oneToOne.Nullable,
|
||||
Unique: oneToOne.Unique,
|
||||
|
||||
ForeignTable: toMany.ForeignTable,
|
||||
ForeignColumn: toMany.ForeignColumn,
|
||||
ForeignColumnNullable: toMany.ForeignColumnNullable,
|
||||
ForeignColumnUnique: toMany.ForeignColumnUnique,
|
||||
ForeignTable: oneToOne.ForeignTable,
|
||||
ForeignColumn: oneToOne.ForeignColumn,
|
||||
ForeignColumnNullable: oneToOne.ForeignColumnNullable,
|
||||
ForeignColumnUnique: oneToOne.ForeignColumnUnique,
|
||||
}
|
||||
|
||||
rel := textsFromForeignKey(packageName, tables, table, fkey)
|
||||
rel.Function.Name = strmangle.TitleCase(strmangle.Singular(toMany.ForeignTable))
|
||||
rel.Function.ForeignName = mkFunctionName(strmangle.Singular(toMany.Table), strmangle.TitleCase(strmangle.Singular(toMany.Table)), toMany.ForeignColumn, false)
|
||||
rel.Function.OneToOne = true
|
||||
rel := txtsFromFKey(tables, table, fkey)
|
||||
col := table.GetColumn(oneToOne.Column)
|
||||
|
||||
// Reverse foreign key
|
||||
rel.ForeignKey.Table, rel.ForeignKey.ForeignTable = rel.ForeignKey.ForeignTable, rel.ForeignKey.Table
|
||||
rel.ForeignKey.Column, rel.ForeignKey.ForeignColumn = rel.ForeignKey.ForeignColumn, rel.ForeignKey.Column
|
||||
rel.ForeignKey.Nullable, rel.ForeignKey.ForeignColumnNullable = rel.ForeignKey.ForeignColumnNullable, rel.ForeignKey.Nullable
|
||||
rel.ForeignKey.Unique, rel.ForeignKey.ForeignColumnUnique = rel.ForeignKey.ForeignColumnUnique, rel.ForeignKey.Unique
|
||||
|
||||
rel.Function.Name = strmangle.TitleCase(strmangle.Singular(oneToOne.ForeignTable))
|
||||
rel.Function.ForeignName = mkFunctionName(strmangle.Singular(oneToOne.Table), strmangle.TitleCase(strmangle.Singular(oneToOne.Table)), oneToOne.ForeignColumn, false)
|
||||
rel.Function.UsesBytes = col.Type == "[]byte"
|
||||
return rel
|
||||
}
|
||||
|
||||
// RelationshipToManyTexts contains text that will be used by templates.
|
||||
type RelationshipToManyTexts struct {
|
||||
// TxtToMany contains text that will be used by many-to-one relationships.
|
||||
type TxtToMany struct {
|
||||
LocalTable struct {
|
||||
NameGo string
|
||||
NameSingular string
|
||||
|
@ -124,15 +134,17 @@ type RelationshipToManyTexts struct {
|
|||
ForeignName string
|
||||
Receiver string
|
||||
|
||||
UsesBytes bool
|
||||
|
||||
LocalAssignment string
|
||||
ForeignAssignment string
|
||||
}
|
||||
}
|
||||
|
||||
// textsFromRelationship creates a struct that does a lot of the text
|
||||
// txtsFromToMany creates a struct that does a lot of the text
|
||||
// transformation in advance for a given relationship.
|
||||
func textsFromRelationship(tables []bdb.Table, table bdb.Table, rel bdb.ToManyRelationship) RelationshipToManyTexts {
|
||||
r := RelationshipToManyTexts{}
|
||||
func txtsFromToMany(tables []bdb.Table, table bdb.Table, rel bdb.ToManyRelationship) TxtToMany {
|
||||
r := TxtToMany{}
|
||||
r.LocalTable.NameSingular = strmangle.Singular(table.Name)
|
||||
r.LocalTable.NameGo = strmangle.TitleCase(r.LocalTable.NameSingular)
|
||||
r.LocalTable.ColumnNameGo = strmangle.TitleCase(rel.Column)
|
||||
|
@ -154,8 +166,8 @@ func textsFromRelationship(tables []bdb.Table, table bdb.Table, rel bdb.ToManyRe
|
|||
}
|
||||
r.Function.ForeignName = strmangle.TitleCase(plurality(strings.TrimSuffix(foreignNamingColumn, "_id")))
|
||||
|
||||
col := table.GetColumn(rel.Column)
|
||||
if rel.Nullable {
|
||||
col := table.GetColumn(rel.Column)
|
||||
r.Function.LocalAssignment = fmt.Sprintf("%s.%s", strmangle.TitleCase(rel.Column), strings.TrimPrefix(col.Type, "null."))
|
||||
} else {
|
||||
r.Function.LocalAssignment = strmangle.TitleCase(rel.Column)
|
||||
|
@ -163,12 +175,14 @@ func textsFromRelationship(tables []bdb.Table, table bdb.Table, rel bdb.ToManyRe
|
|||
|
||||
if rel.ForeignColumnNullable {
|
||||
foreignTable := bdb.GetTable(tables, rel.ForeignTable)
|
||||
col := foreignTable.GetColumn(rel.ForeignColumn)
|
||||
r.Function.ForeignAssignment = fmt.Sprintf("%s.%s", strmangle.TitleCase(rel.ForeignColumn), strings.TrimPrefix(col.Type, "null."))
|
||||
foreignColumn := foreignTable.GetColumn(rel.ForeignColumn)
|
||||
r.Function.ForeignAssignment = fmt.Sprintf("%s.%s", strmangle.TitleCase(rel.ForeignColumn), strings.TrimPrefix(foreignColumn.Type, "null."))
|
||||
} else {
|
||||
r.Function.ForeignAssignment = strmangle.TitleCase(rel.ForeignColumn)
|
||||
}
|
||||
|
||||
r.Function.UsesBytes = col.Type == "[]byte"
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
|
@ -183,17 +197,3 @@ func mkFunctionName(fkeyTableSingular, foreignTablePluralGo, fkeyColumn string,
|
|||
|
||||
return strmangle.TitleCase(colName) + foreignTablePluralGo
|
||||
}
|
||||
|
||||
// PreserveDot allows us to pass in templateData to relationship templates
|
||||
// called with the template function.
|
||||
type PreserveDot struct {
|
||||
Dot templateData
|
||||
Rel RelationshipToOneTexts
|
||||
}
|
||||
|
||||
func preserveDot(data templateData, obj RelationshipToOneTexts) PreserveDot {
|
||||
return PreserveDot{
|
||||
Dot: data,
|
||||
Rel: obj,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/vattle/sqlboiler/bdb/drivers"
|
||||
)
|
||||
|
||||
func TestTextsFromForeignKey(t *testing.T) {
|
||||
func TestTxtsFromOne(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tables, err := bdb.Tables(&drivers.MockDriver{}, "public", nil, nil)
|
||||
|
@ -18,8 +18,8 @@ func TestTextsFromForeignKey(t *testing.T) {
|
|||
}
|
||||
|
||||
jets := bdb.GetTable(tables, "jets")
|
||||
texts := textsFromForeignKey("models", tables, jets, jets.FKeys[0])
|
||||
expect := RelationshipToOneTexts{}
|
||||
texts := txtsFromFKey(tables, jets, jets.FKeys[0])
|
||||
expect := TxtToOne{}
|
||||
|
||||
expect.ForeignKey = jets.FKeys[0]
|
||||
|
||||
|
@ -32,12 +32,10 @@ func TestTextsFromForeignKey(t *testing.T) {
|
|||
expect.ForeignTable.ColumnName = "id"
|
||||
expect.ForeignTable.ColumnNameGo = "ID"
|
||||
|
||||
expect.Function.PackageName = "models"
|
||||
expect.Function.Name = "Pilot"
|
||||
expect.Function.ForeignName = "Jet"
|
||||
expect.Function.Varname = "pilot"
|
||||
expect.Function.Receiver = "j"
|
||||
expect.Function.OneToOne = false
|
||||
|
||||
expect.Function.LocalAssignment = "PilotID.Int"
|
||||
expect.Function.ForeignAssignment = "ID"
|
||||
|
@ -46,8 +44,8 @@ func TestTextsFromForeignKey(t *testing.T) {
|
|||
t.Errorf("Want:\n%s\nGot:\n%s\n", spew.Sdump(expect), spew.Sdump(texts))
|
||||
}
|
||||
|
||||
texts = textsFromForeignKey("models", tables, jets, jets.FKeys[1])
|
||||
expect = RelationshipToOneTexts{}
|
||||
texts = txtsFromFKey(tables, jets, jets.FKeys[1])
|
||||
expect = TxtToOne{}
|
||||
expect.ForeignKey = jets.FKeys[1]
|
||||
|
||||
expect.LocalTable.NameGo = "Jet"
|
||||
|
@ -59,12 +57,10 @@ func TestTextsFromForeignKey(t *testing.T) {
|
|||
expect.ForeignTable.ColumnName = "id"
|
||||
expect.ForeignTable.ColumnNameGo = "ID"
|
||||
|
||||
expect.Function.PackageName = "models"
|
||||
expect.Function.Name = "Airport"
|
||||
expect.Function.ForeignName = "Jets"
|
||||
expect.Function.Varname = "airport"
|
||||
expect.Function.Receiver = "j"
|
||||
expect.Function.OneToOne = false
|
||||
|
||||
expect.Function.LocalAssignment = "AirportID"
|
||||
expect.Function.ForeignAssignment = "ID"
|
||||
|
@ -78,7 +74,7 @@ func TestTextsFromForeignKey(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTextsFromOneToOneRelationship(t *testing.T) {
|
||||
func TestTxtsFromOneToOne(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tables, err := bdb.Tables(&drivers.MockDriver{}, "public", nil, nil)
|
||||
|
@ -87,20 +83,21 @@ func TestTextsFromOneToOneRelationship(t *testing.T) {
|
|||
}
|
||||
|
||||
pilots := bdb.GetTable(tables, "pilots")
|
||||
texts := textsFromOneToOneRelationship("models", tables, pilots, pilots.ToManyRelationships[0])
|
||||
expect := RelationshipToOneTexts{}
|
||||
texts := txtsFromOneToOne(tables, pilots, pilots.ToOneRelationships[0])
|
||||
expect := TxtToOne{}
|
||||
|
||||
expect.ForeignKey = bdb.ForeignKey{
|
||||
Table: "pilots",
|
||||
Name: "none",
|
||||
Column: "id",
|
||||
Nullable: false,
|
||||
Unique: false,
|
||||
Name: "none",
|
||||
|
||||
ForeignTable: "jets",
|
||||
ForeignColumn: "pilot_id",
|
||||
ForeignColumnNullable: true,
|
||||
ForeignColumnUnique: true,
|
||||
Table: "jets",
|
||||
Column: "pilot_id",
|
||||
Nullable: true,
|
||||
Unique: true,
|
||||
|
||||
ForeignTable: "pilots",
|
||||
ForeignColumn: "id",
|
||||
ForeignColumnNullable: false,
|
||||
ForeignColumnUnique: false,
|
||||
}
|
||||
|
||||
expect.LocalTable.NameGo = "Pilot"
|
||||
|
@ -112,12 +109,10 @@ func TestTextsFromOneToOneRelationship(t *testing.T) {
|
|||
expect.ForeignTable.ColumnName = "pilot_id"
|
||||
expect.ForeignTable.ColumnNameGo = "PilotID"
|
||||
|
||||
expect.Function.PackageName = "models"
|
||||
expect.Function.Name = "Jet"
|
||||
expect.Function.ForeignName = "Pilot"
|
||||
expect.Function.Varname = "jet"
|
||||
expect.Function.Receiver = "p"
|
||||
expect.Function.OneToOne = true
|
||||
|
||||
expect.Function.LocalAssignment = "ID"
|
||||
expect.Function.ForeignAssignment = "PilotID.Int"
|
||||
|
@ -127,7 +122,7 @@ func TestTextsFromOneToOneRelationship(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTextsFromRelationship(t *testing.T) {
|
||||
func TestTxtsFromMany(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tables, err := bdb.Tables(&drivers.MockDriver{}, "public", nil, nil)
|
||||
|
@ -136,31 +131,8 @@ func TestTextsFromRelationship(t *testing.T) {
|
|||
}
|
||||
|
||||
pilots := bdb.GetTable(tables, "pilots")
|
||||
texts := textsFromRelationship(tables, pilots, pilots.ToManyRelationships[0])
|
||||
expect := RelationshipToManyTexts{}
|
||||
expect.LocalTable.NameGo = "Pilot"
|
||||
expect.LocalTable.NameSingular = "pilot"
|
||||
expect.LocalTable.ColumnNameGo = "ID"
|
||||
|
||||
expect.ForeignTable.NameGo = "Jet"
|
||||
expect.ForeignTable.NameSingular = "jet"
|
||||
expect.ForeignTable.NamePluralGo = "Jets"
|
||||
expect.ForeignTable.NameHumanReadable = "jets"
|
||||
expect.ForeignTable.ColumnNameGo = "PilotID"
|
||||
expect.ForeignTable.Slice = "JetSlice"
|
||||
|
||||
expect.Function.Name = "Jets"
|
||||
expect.Function.ForeignName = "Pilot"
|
||||
expect.Function.Receiver = "p"
|
||||
expect.Function.LocalAssignment = "ID"
|
||||
expect.Function.ForeignAssignment = "PilotID.Int"
|
||||
|
||||
if !reflect.DeepEqual(expect, texts) {
|
||||
t.Errorf("Want:\n%s\nGot:\n%s\n", spew.Sdump(expect), spew.Sdump(texts))
|
||||
}
|
||||
|
||||
texts = textsFromRelationship(tables, pilots, pilots.ToManyRelationships[1])
|
||||
expect = RelationshipToManyTexts{}
|
||||
texts := txtsFromToMany(tables, pilots, pilots.ToManyRelationships[0])
|
||||
expect := TxtToMany{}
|
||||
expect.LocalTable.NameGo = "Pilot"
|
||||
expect.LocalTable.NameSingular = "pilot"
|
||||
expect.LocalTable.ColumnNameGo = "ID"
|
||||
|
@ -182,8 +154,8 @@ func TestTextsFromRelationship(t *testing.T) {
|
|||
t.Errorf("Want:\n%s\nGot:\n%s\n", spew.Sdump(expect), spew.Sdump(texts))
|
||||
}
|
||||
|
||||
texts = textsFromRelationship(tables, pilots, pilots.ToManyRelationships[2])
|
||||
expect = RelationshipToManyTexts{}
|
||||
texts = txtsFromToMany(tables, pilots, pilots.ToManyRelationships[1])
|
||||
expect = TxtToMany{}
|
||||
expect.LocalTable.NameGo = "Pilot"
|
||||
expect.LocalTable.NameSingular = "pilot"
|
||||
expect.LocalTable.ColumnNameGo = "ID"
|
||||
|
|
Loading…
Add table
Reference in a new issue