Add enum const generation

- Make postgres name its enums
- Add way to filter columns by whether or not they're an enum
- Split parsing of enums into name & values
- Add strmangle check functions: IsEnumNormal, ShouldTitleCaseEnum
- Add new strmangle enum functions to template test
- Implement a set type called "once" inside the templates so that we can
  ensure certain things only generate one time via some unique name.
This commit is contained in:
Aaron L 2016-11-11 01:01:09 -08:00
parent d27823de53
commit ede97dea5b
8 changed files with 228 additions and 16 deletions
strmangle

View file

@ -17,7 +17,9 @@ var (
idAlphabet = []byte("abcdefghijklmnopqrstuvwxyz")
smartQuoteRgx = regexp.MustCompile(`^(?i)"?[a-z_][_a-z0-9]*"?(\."?[_a-z][_a-z0-9]*"?)*(\.\*)?$`)
rgxEnum = regexp.MustCompile(`^enum\((,?'[^']+')+\)$`)
rgxEnum = regexp.MustCompile(`^enum(\.[a-z_]+)?\((,?'[^']+')+\)$`)
rgxEnumIsOK = regexp.MustCompile(`^(?i)[a-z][a-z0-9_]*$`)
rgxEnumShouldTitle = regexp.MustCompile(`^[a-z][a-z0-9_]*$`)
)
var uppercaseWords = map[string]struct{}{
@ -577,15 +579,54 @@ func GenerateIgnoreTags(tags []string) string {
return buf.String()
}
// ParseEnum takes a string that looks like:
// enum('one','two') and returns the strings one, two
func ParseEnum(s string) []string {
// ParseEnumVals returns the values from an enum string
//
// Postgres and MySQL drivers return different values
// psql: enum.enum_name('values'...)
// mysql: enum('values'...)
func ParseEnumVals(s string) []string {
if !rgxEnum.MatchString(s) {
return nil
}
s = strings.TrimPrefix(s, "enum('")
s = strings.TrimSuffix(s, "')")
startIndex := strings.IndexByte(s, '(')
s = s[startIndex+2 : len(s)-2]
return strings.Split(s, "','")
}
// ParseEnumName returns the name portion of an enum if it exists
//
// Postgres and MySQL drivers return different values
// psql: enum.enum_name('values'...)
// mysql: enum('values'...)
// In the case of mysql, the name will never return anything
func ParseEnumName(s string) string {
if !rgxEnum.MatchString(s) {
return ""
}
endIndex := strings.IndexByte(s, '(')
s = s[:endIndex]
startIndex := strings.IndexByte(s, '.')
if startIndex < 0 {
return ""
}
return s[startIndex+1:]
}
// IsEnumNormal checks a set of eval values to see if they're "normal"
func IsEnumNormal(values []string) bool {
for _, v := range values {
if !rgxEnumIsOK.MatchString(v) {
return false
}
}
return true
}
// ShouldTitleCaseEnum checks a value to see if it's title-case-able
func ShouldTitleCaseEnum(value string) bool {
return rgxEnumShouldTitle.MatchString(value)
}