Last active
June 23, 2018 10:17
-
-
Save nadilas/b14476f8bce00e7c689d7c5b90798909 to your computer and use it in GitHub Desktop.
lowercase lookup conversion as quick-fix for mssql
This file contains hidden or 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
package boilingcore | |
import ( | |
"fmt" | |
"github.com/volatiletech/sqlboiler/drivers" | |
"github.com/volatiletech/sqlboiler/strmangle" | |
"strings" | |
) | |
// Aliases defines aliases for the generation run | |
type Aliases struct { | |
Tables map[string]TableAlias `toml:"tables,omitempty" json:"tables,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"` | |
Relationships map[string]RelationshipAlias `toml:"relationships,omitempty" json:"relationships,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) { | |
if a.Tables == nil { | |
a.Tables = make(map[string]TableAlias) | |
} | |
for _, t := range tables { | |
lowercaseTname := strings.ToLower(t.Name) | |
if t.IsJoinTable { | |
if _, ok := a.Tables[lowercaseTname]; !ok { | |
a.Tables[lowercaseTname] = TableAlias{Relationships: make(map[string]RelationshipAlias)} | |
} | |
continue | |
} | |
table := a.Tables[lowercaseTname] | |
if len(table.UpPlural) == 0 { | |
table.UpPlural = strmangle.TitleCase(strmangle.Plural(lowercaseTname)) | |
} | |
if len(table.UpSingular) == 0 { | |
table.UpSingular = strmangle.TitleCase(strmangle.Singular(lowercaseTname)) | |
} | |
if len(table.DownPlural) == 0 { | |
table.DownPlural = strmangle.CamelCase(strmangle.Plural(lowercaseTname)) | |
} | |
if len(table.DownSingular) == 0 { | |
table.DownSingular = strmangle.CamelCase(strmangle.Singular(lowercaseTname)) | |
} | |
if table.Columns == nil { | |
table.Columns = make(map[string]string) | |
} | |
if table.Relationships == nil { | |
table.Relationships = make(map[string]RelationshipAlias) | |
} | |
for _, c := range t.Columns { | |
if _, ok := table.Columns[c.Name]; !ok { | |
table.Columns[c.Name] = strmangle.TitleCase(c.Name) | |
} | |
} | |
a.Tables[lowercaseTname] = table | |
for _, k := range t.FKeys { | |
r := table.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 | |
} | |
table.Relationships[k.Name] = r | |
} | |
} | |
for _, t := range tables { | |
if !t.IsJoinTable { | |
continue | |
} | |
table := a.Tables[t.Name] | |
lhs := t.FKeys[0] | |
rhs := t.FKeys[1] | |
lhsAlias, lhsOK := table.Relationships[lhs.Name] | |
rhsAlias, rhsOK := table.Relationships[rhs.Name] | |
if lhsOK && len(lhsAlias.Local) != 0 && len(lhsAlias.Foreign) != 0 && | |
rhsOK && len(rhsAlias.Local) != 0 && len(rhsAlias.Foreign) != 0 { | |
continue | |
} | |
// Here we actually reverse the meaning of local/foreign to be | |
// consistent with the way normal one-to-many relationships are done. | |
// That's to say local = the side with the foreign key. Now in a many-to-many | |
// if we were able to not have a join table our foreign key say "videos_id" | |
// would be on the tags table. Hence the relationships should look like: | |
// videos_tags.relationships.fk_video_id.local = "Tags" | |
// videos_tags.relationships.fk_video_id.foreign = "Videos" | |
// Consistent, yes. Confusing? Also yes. | |
lhsName, rhsName := txtNameToMany(lhs, rhs) | |
if len(lhsAlias.Local) != 0 { | |
rhsName = lhsAlias.Local | |
} else if len(rhsAlias.Local) != 0 { | |
lhsName = rhsAlias.Local | |
} | |
if len(lhsAlias.Foreign) != 0 { | |
lhsName = lhsAlias.Foreign | |
} else if len(rhsAlias.Foreign) != 0 { | |
rhsName = rhsAlias.Foreign | |
} | |
if len(lhsAlias.Local) == 0 { | |
lhsAlias.Local = rhsName | |
} | |
if len(lhsAlias.Foreign) == 0 { | |
lhsAlias.Foreign = lhsName | |
} | |
if len(rhsAlias.Local) == 0 { | |
rhsAlias.Local = lhsName | |
} | |
if len(rhsAlias.Foreign) == 0 { | |
rhsAlias.Foreign = rhsName | |
} | |
table.Relationships[lhs.Name] = lhsAlias | |
table.Relationships[rhs.Name] = rhsAlias | |
} | |
} | |
// Table gets a table alias, panics if not found. | |
func (a Aliases) Table(table string) TableAlias { | |
lowercaseTname := strings.ToLower(table) | |
t, ok := a.Tables[lowercaseTname] | |
if !ok { | |
panic("could not find table aliases for: " + table) | |
} | |
return t | |
} | |
// Column get's a column's aliased name, panics if not found. | |
func (t TableAlias) Column(column string) string { | |
c, ok := t.Columns[column] | |
if !ok { | |
panic(fmt.Sprintf("could not find column alias for: %s.%s", t.UpSingular, column)) | |
} | |
return c | |
} | |
// Relationship looks up a relationship, panics if not found. | |
func (t TableAlias) Relationship(fkey string) RelationshipAlias { | |
r, ok := t.Relationships[fkey] | |
if !ok { | |
panic(fmt.Sprintf("could not find relationship alias for: %s.%s", t.UpSingular, fkey)) | |
} | |
return r | |
} | |
// ManyRelationship looks up a relationship alias, panics if not found. | |
// It will first try to look up a join table relationship, then it will | |
// try a normal one-to-many relationship. That's to say joinTable/joinTableFKey | |
// are used if they're not empty. | |
// | |
// This allows us to skip additional conditionals in the templates. | |
func (a Aliases) ManyRelationship(table, fkey, joinTable, joinTableFKey string) RelationshipAlias { | |
var lookupTable, lookupFKey string | |
if len(joinTable) != 0 { | |
lookupTable, lookupFKey = joinTable, joinTableFKey | |
} else { | |
lookupTable, lookupFKey = table, fkey | |
} | |
t := a.Table(lookupTable) | |
return t.Relationship(lookupFKey) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment