-
Notifications
You must be signed in to change notification settings - Fork 553
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Add the foreign key name to the relationships structs from the driver - Modify text helpers to do a lot less work. - Add an Aliases type in the configuration to allow specifying aliases as well as carrying the aliases into the templates. This will now be used everywhere for all Go type names inside the templates. - Add tests for the new config pieces.
- Loading branch information
Showing
11 changed files
with
731 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package boilingcore | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/volatiletech/sqlboiler/drivers" | ||
"github.com/volatiletech/sqlboiler/strmangle" | ||
) | ||
|
||
// Aliases defines aliases for the generation run | ||
type Aliases struct { | ||
Tables map[string]TableAlias `toml:"tables,omitempty" json:"tables,omitempty"` | ||
Relationships map[string]RelationshipAlias `toml:"relationships,omitempty" json:"relationships,omitempty"` | ||
} | ||
|
||
// TableAlias defines the spellings for a table name in Go | ||
type TableAlias struct { | ||
UpPlural string `toml:"up_plural,omitempty" json:"up_plural,omitempty"` | ||
UpSingular string `toml:"up_singular,omitempty" json:"up_singular,omitempty"` | ||
DownPlural string `toml:"down_plural,omitempty" json:"down_plural,omitempty"` | ||
DownSingular string `toml:"down_singular,omitempty" json:"down_singular,omitempty"` | ||
|
||
Columns map[string]string `toml:"columns,omitempty" json:"columns,omitempty"` | ||
} | ||
|
||
// RelationshipAlias defines the naming for both sides of | ||
// a foreign key. | ||
type RelationshipAlias struct { | ||
Local string `toml:"local,omitempty" json:"local,omitempty"` | ||
Foreign string `toml:"foreign,omitempty" json:"foreign,omitempty"` | ||
} | ||
|
||
// FillAliases takes the table information from the driver | ||
// and fills in aliases where the user has provided none. | ||
// | ||
// This leaves us with a complete list of Go names for all tables, | ||
// columns, and relationships. | ||
func FillAliases(a *Aliases, tables []drivers.Table) { | ||
for _, t := range tables { | ||
if t.IsJoinTable { | ||
continue | ||
} | ||
|
||
if a.Tables == nil { | ||
a.Tables = make(map[string]TableAlias) | ||
} | ||
|
||
table := a.Tables[t.Name] | ||
|
||
if len(table.UpPlural) == 0 { | ||
table.UpPlural = strmangle.TitleCase(strmangle.Plural(t.Name)) | ||
} | ||
if len(table.UpSingular) == 0 { | ||
table.UpSingular = strmangle.TitleCase(strmangle.Singular(t.Name)) | ||
} | ||
if len(table.DownPlural) == 0 { | ||
table.DownPlural = strmangle.CamelCase(strmangle.Plural(t.Name)) | ||
} | ||
if len(table.DownSingular) == 0 { | ||
table.DownSingular = strmangle.CamelCase(strmangle.Singular(t.Name)) | ||
} | ||
|
||
if table.Columns == nil { | ||
table.Columns = make(map[string]string) | ||
} | ||
|
||
for _, c := range t.Columns { | ||
if _, ok := table.Columns[c.Name]; !ok { | ||
table.Columns[c.Name] = strmangle.TitleCase(c.Name) | ||
} | ||
} | ||
|
||
a.Tables[t.Name] = table | ||
|
||
if a.Relationships == nil { | ||
a.Relationships = make(map[string]RelationshipAlias) | ||
} | ||
|
||
for _, k := range t.FKeys { | ||
r := a.Relationships[k.Name] | ||
if len(r.Local) != 0 && len(r.Foreign) != 0 { | ||
continue | ||
} | ||
|
||
local, foreign := txtNameToOne(k) | ||
if len(r.Local) == 0 { | ||
r.Local = local | ||
} | ||
if len(r.Foreign) == 0 { | ||
r.Foreign = foreign | ||
} | ||
|
||
a.Relationships[k.Name] = r | ||
} | ||
|
||
for _, rel := range t.ToManyRelationships { | ||
localFacingAlias, okLocal := a.Relationships[rel.JoinLocalFKeyName] | ||
foreignFacingAlias, okForeign := a.Relationships[rel.JoinForeignFKeyName] | ||
|
||
if okLocal && okForeign { | ||
continue | ||
} | ||
|
||
local, foreign := txtNameToMany(rel) | ||
|
||
switch { | ||
case !okLocal && !okForeign: | ||
localFacingAlias.Local = local | ||
localFacingAlias.Foreign = foreign | ||
foreignFacingAlias.Local = foreign | ||
foreignFacingAlias.Foreign = local | ||
case okLocal: | ||
if len(localFacingAlias.Local) == 0 { | ||
localFacingAlias.Local = local | ||
} | ||
if len(localFacingAlias.Foreign) == 0 { | ||
localFacingAlias.Foreign = foreign | ||
} | ||
|
||
foreignFacingAlias.Local = localFacingAlias.Foreign | ||
foreignFacingAlias.Foreign = localFacingAlias.Local | ||
case okForeign: | ||
if len(foreignFacingAlias.Local) == 0 { | ||
foreignFacingAlias.Local = foreign | ||
} | ||
if len(foreignFacingAlias.Foreign) == 0 { | ||
foreignFacingAlias.Foreign = local | ||
} | ||
|
||
localFacingAlias.Foreign = foreignFacingAlias.Local | ||
localFacingAlias.Local = foreignFacingAlias.Foreign | ||
} | ||
|
||
a.Relationships[rel.JoinLocalFKeyName] = localFacingAlias | ||
a.Relationships[rel.JoinForeignFKeyName] = foreignFacingAlias | ||
} | ||
} | ||
} | ||
|
||
// Table gets a table alias, panics if not found. | ||
func (a Aliases) Table(table string) TableAlias { | ||
t, ok := a.Tables[table] | ||
if !ok { | ||
panic("could not find table aliases for: " + table) | ||
} | ||
|
||
return t | ||
} | ||
|
||
// Column gets a column's aliased name, panics if not found. | ||
func (a Aliases) Column(table, column string) string { | ||
t := a.Table(table) | ||
|
||
c, ok := t.Columns[column] | ||
if !ok { | ||
panic(fmt.Sprintf("could not find column alias for: %s.%s", table, column)) | ||
} | ||
|
||
return c | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
package boilingcore | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/volatiletech/sqlboiler/drivers" | ||
) | ||
|
||
func TestAliasesTables(t *testing.T) { | ||
t.Parallel() | ||
|
||
tables := []drivers.Table{ | ||
{ | ||
Name: "videos", | ||
Columns: []drivers.Column{ | ||
{Name: "id"}, | ||
{Name: "name"}, | ||
}, | ||
}, | ||
} | ||
|
||
t.Run("Automatic", func(t *testing.T) { | ||
expect := TableAlias{ | ||
UpPlural: "Videos", | ||
UpSingular: "Video", | ||
DownPlural: "videos", | ||
DownSingular: "video", | ||
Columns: map[string]string{ | ||
"id": "ID", | ||
"name": "Name", | ||
}, | ||
} | ||
|
||
a := Aliases{} | ||
FillAliases(&a, tables) | ||
|
||
if got := a.Tables["videos"]; !reflect.DeepEqual(expect, got) { | ||
t.Errorf("it should fill in the blanks: %#v", got) | ||
} | ||
}) | ||
|
||
t.Run("UserOverride", func(t *testing.T) { | ||
expect := TableAlias{ | ||
UpPlural: "NotVideos", | ||
UpSingular: "NotVideo", | ||
DownPlural: "notVideos", | ||
DownSingular: "notVideo", | ||
Columns: map[string]string{ | ||
"id": "NotID", | ||
"name": "NotName", | ||
}, | ||
} | ||
|
||
a := Aliases{} | ||
a.Tables = map[string]TableAlias{"videos": expect} | ||
FillAliases(&a, tables) | ||
|
||
if !reflect.DeepEqual(expect, a.Tables["videos"]) { | ||
t.Error("it should not alter things that were specified by user") | ||
} | ||
}) | ||
} | ||
|
||
func TestAliasesRelationships(t *testing.T) { | ||
t.Parallel() | ||
|
||
tables := []drivers.Table{ | ||
{ | ||
Name: "videos", | ||
Columns: []drivers.Column{ | ||
{Name: "id"}, | ||
{Name: "name"}, | ||
}, | ||
FKeys: []drivers.ForeignKey{ | ||
{ | ||
Name: "fkey_1", | ||
Table: "videos", | ||
Column: "user_id", | ||
ForeignTable: "users", | ||
ForeignColumn: "id", | ||
}, | ||
{ | ||
Name: "fkey_2", | ||
Table: "videos", | ||
Column: "publisher_id", | ||
ForeignTable: "users", | ||
ForeignColumn: "id", | ||
}, | ||
{ | ||
Name: "fkey_3", | ||
Table: "videos", | ||
Column: "one_id", | ||
Unique: true, | ||
ForeignTable: "ones", | ||
ForeignColumn: "one", | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
t.Run("Automatic", func(t *testing.T) { | ||
expect1 := RelationshipAlias{ | ||
Local: "User", | ||
Foreign: "Videos", | ||
} | ||
expect2 := RelationshipAlias{ | ||
Local: "Publisher", | ||
Foreign: "PublisherVideos", | ||
} | ||
expect3 := RelationshipAlias{ | ||
Local: "One", | ||
Foreign: "Video", | ||
} | ||
|
||
a := Aliases{} | ||
FillAliases(&a, tables) | ||
|
||
if got := a.Relationships["fkey_1"]; !reflect.DeepEqual(expect1, got) { | ||
t.Errorf("bad values: %#v", got) | ||
} | ||
if got := a.Relationships["fkey_2"]; !reflect.DeepEqual(expect2, got) { | ||
t.Errorf("bad values: %#v", got) | ||
} | ||
if got := a.Relationships["fkey_3"]; !reflect.DeepEqual(expect3, got) { | ||
t.Errorf("bad values: %#v", got) | ||
} | ||
}) | ||
|
||
t.Run("UserOverride", func(t *testing.T) { | ||
expect1 := RelationshipAlias{ | ||
Local: "TheUser", | ||
Foreign: "Videos", | ||
} | ||
expect2 := RelationshipAlias{ | ||
Local: "Publisher", | ||
Foreign: "PublishedVideos", | ||
} | ||
expect3 := RelationshipAlias{ | ||
Local: "TheOne", | ||
Foreign: "AwesomeOneVideo", | ||
} | ||
|
||
a := Aliases{ | ||
Relationships: map[string]RelationshipAlias{ | ||
"fkey_1": {Local: "TheUser"}, | ||
"fkey_2": {Foreign: "PublishedVideos"}, | ||
"fkey_3": {Local: "TheOne", Foreign: "AwesomeOneVideo"}, | ||
}, | ||
} | ||
FillAliases(&a, tables) | ||
|
||
if got := a.Relationships["fkey_1"]; !reflect.DeepEqual(expect1, got) { | ||
t.Errorf("bad values: %#v", got) | ||
} | ||
if got := a.Relationships["fkey_2"]; !reflect.DeepEqual(expect2, got) { | ||
t.Errorf("bad values: %#v", got) | ||
} | ||
if got := a.Relationships["fkey_3"]; !reflect.DeepEqual(expect3, got) { | ||
t.Errorf("bad values: %#v", got) | ||
} | ||
}) | ||
} | ||
|
||
func TestAliasesRelationshipsJoinTable(t *testing.T) { | ||
t.Parallel() | ||
|
||
tables := []drivers.Table{ | ||
{ | ||
Name: "videos", | ||
ToManyRelationships: []drivers.ToManyRelationship{ | ||
{ | ||
Table: "videos", | ||
ForeignTable: "tags", | ||
Column: "id", | ||
ForeignColumn: "id", | ||
|
||
ToJoinTable: true, | ||
JoinTable: "video_tags", | ||
|
||
JoinLocalFKeyName: "fk_video_id", | ||
JoinLocalColumn: "video_id", | ||
JoinForeignFKeyName: "fk_tag_id", | ||
JoinForeignColumn: "tag_id", | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
t.Run("Automatic", func(t *testing.T) { | ||
expect1 := RelationshipAlias{ | ||
Local: "Tags", | ||
Foreign: "Videos", | ||
} | ||
expect2 := RelationshipAlias{ | ||
Local: "Videos", | ||
Foreign: "Tags", | ||
} | ||
|
||
a := Aliases{} | ||
FillAliases(&a, tables) | ||
|
||
if got := a.Relationships["fk_video_id"]; !reflect.DeepEqual(expect1, got) { | ||
t.Errorf("bad values: %#v", got) | ||
} | ||
if got := a.Relationships["fk_tag_id"]; !reflect.DeepEqual(expect2, got) { | ||
t.Errorf("bad values: %#v", got) | ||
} | ||
}) | ||
|
||
t.Run("UserOverride", func(t *testing.T) { | ||
expect1 := RelationshipAlias{ | ||
Local: "NotTags", | ||
Foreign: "NotVideos", | ||
} | ||
expect2 := RelationshipAlias{ | ||
Local: "NotVideos", | ||
Foreign: "NotTags", | ||
} | ||
|
||
a := Aliases{ | ||
Relationships: map[string]RelationshipAlias{ | ||
"fk_video_id": {Local: "NotTags", Foreign: "NotVideos"}, | ||
}, | ||
} | ||
FillAliases(&a, tables) | ||
|
||
if got := a.Relationships["fk_video_id"]; !reflect.DeepEqual(expect1, got) { | ||
t.Errorf("bad values: %#v", got) | ||
} | ||
if got := a.Relationships["fk_tag_id"]; !reflect.DeepEqual(expect2, got) { | ||
t.Errorf("bad values: %#v", got) | ||
} | ||
}) | ||
} |
Oops, something went wrong.