package schema
import (
"fmt"
"sort"
"strconv"
"strings"
)
type Index struct {
Name string
Class string
Type string
Where string
Comment string
Option string
Fields []IndexOption
}
type IndexOption struct {
*Field
Expression string
Sort string
Collate string
Length int
priority int
}
func (schema *Schema ) ParseIndexes () map [string ]Index {
indexes := map [string ]Index {}
for _ , field := range schema .Fields {
if field .TagSettings ["INDEX" ] != "" || field .TagSettings ["UNIQUEINDEX" ] != "" {
fieldIndexes , err := parseFieldIndexes (field )
if err != nil {
schema .err = err
break
}
for _ , index := range fieldIndexes {
idx := indexes [index .Name ]
idx .Name = index .Name
if idx .Class == "" {
idx .Class = index .Class
}
if idx .Type == "" {
idx .Type = index .Type
}
if idx .Where == "" {
idx .Where = index .Where
}
if idx .Comment == "" {
idx .Comment = index .Comment
}
if idx .Option == "" {
idx .Option = index .Option
}
idx .Fields = append (idx .Fields , index .Fields ...)
sort .Slice (idx .Fields , func (i , j int ) bool {
return idx .Fields [i ].priority < idx .Fields [j ].priority
})
indexes [index .Name ] = idx
}
}
}
for _ , index := range indexes {
if index .Class == "UNIQUE" && len (index .Fields ) == 1 {
index .Fields [0 ].Field .Unique = true
}
}
return indexes
}
func (schema *Schema ) LookIndex (name string ) *Index {
if schema != nil {
indexes := schema .ParseIndexes ()
for _ , index := range indexes {
if index .Name == name {
return &index
}
for _ , field := range index .Fields {
if field .Name == name {
return &index
}
}
}
}
return nil
}
func parseFieldIndexes(field *Field ) (indexes []Index , err error ) {
for _ , value := range strings .Split (field .Tag .Get ("gorm" ), ";" ) {
if value != "" {
v := strings .Split (value , ":" )
k := strings .TrimSpace (strings .ToUpper (v [0 ]))
if k == "INDEX" || k == "UNIQUEINDEX" {
var (
name string
tag = strings .Join (v [1 :], ":" )
idx = strings .Index (tag , "," )
tagSetting = strings .Join (strings .Split (tag , "," )[1 :], "," )
settings = ParseTagSetting (tagSetting , "," )
length , _ = strconv .Atoi (settings ["LENGTH" ])
)
if idx == -1 {
idx = len (tag )
}
if idx != -1 {
name = tag [0 :idx ]
}
if name == "" {
subName := field .Name
const key = "COMPOSITE"
if composite , found := settings [key ]; found {
if len (composite ) == 0 || composite == key {
err = fmt .Errorf (
"The composite tag of %s.%s cannot be empty" ,
field .Schema .Name ,
field .Name )
return
}
subName = composite
}
name = field .Schema .namer .IndexName (
field .Schema .Table , subName )
}
if (k == "UNIQUEINDEX" ) || settings ["UNIQUE" ] != "" {
settings ["CLASS" ] = "UNIQUE"
}
priority , err := strconv .Atoi (settings ["PRIORITY" ])
if err != nil {
priority = 10
}
indexes = append (indexes , Index {
Name : name ,
Class : settings ["CLASS" ],
Type : settings ["TYPE" ],
Where : settings ["WHERE" ],
Comment : settings ["COMMENT" ],
Option : settings ["OPTION" ],
Fields : []IndexOption {{
Field : field ,
Expression : settings ["EXPRESSION" ],
Sort : settings ["SORT" ],
Collate : settings ["COLLATE" ],
Length : length ,
priority : priority ,
}},
})
}
}
}
err = nil
return
}
The pages are generated with Golds v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds .