Add interface to allow structs to provide specific index information

The current mechanism for adding information about indices cannot express the ordering
of the columns in the index or add sorting information.

Here we add a new interface TableIndices which a struct would implement to provide
a slice of *schema.Index to provide additional indices to that gleaned from the tags.

Signed-off-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
Andrew Thornton 2022-04-23 18:07:58 +01:00
parent f7e9fb74ac
commit 152e1bcc69
No known key found for this signature in database
GPG Key ID: 3CDE74631F13A748
1 changed files with 52 additions and 6 deletions

View File

@ -21,10 +21,15 @@ import (
"xorm.io/xorm/schemas"
)
var (
// ErrUnsupportedType represents an unsupported type error
ErrUnsupportedType = errors.New("unsupported type")
)
var ErrUnsupportedType = errors.New("unsupported type")
// TableIndices is an interface that describes structs that provide additional index information above that which is automatically parsed
type TableIndices interface {
TableIndices() []*schemas.Index
}
var tpTableIndices = reflect.TypeOf((*TableIndices)(nil)).Elem()
// Parser represents a parser for xorm tag
type Parser struct {
@ -177,7 +182,7 @@ func (parser *Parser) parseFieldWithNoTag(fieldIndex int, field reflect.StructFi
}
func (parser *Parser) parseFieldWithTags(table *schemas.Table, fieldIndex int, field reflect.StructField, fieldValue reflect.Value, tags []tag) (*schemas.Column, error) {
var col = &schemas.Column{
col := &schemas.Column{
FieldName: field.Name,
FieldIndex: []int{fieldIndex},
Nullable: true,
@ -188,7 +193,7 @@ func (parser *Parser) parseFieldWithTags(table *schemas.Table, fieldIndex int, f
DefaultIsEmpty: true,
}
var ctx = Context{
ctx := Context{
table: table,
col: col,
fieldValue: fieldValue,
@ -329,5 +334,46 @@ func (parser *Parser) Parse(v reflect.Value) (*schemas.Table, error) {
table.AddColumn(col)
} // end for
indices := tableIndices(v)
for _, index := range indices {
// Override old information
if oldIndex, ok := table.Indexes[index.Name]; ok {
for _, colName := range oldIndex.Cols {
col := table.GetColumn(colName)
if col == nil {
return nil, ErrUnsupportedType
}
delete(col.Indexes, index.Name)
}
}
table.AddIndex(index)
for _, colName := range index.Cols {
col := table.GetColumn(colName)
if col == nil {
return nil, ErrUnsupportedType
}
col.Indexes[index.Name] = index.Type
}
}
return table, nil
}
func tableIndices(v reflect.Value) []*schemas.Index {
if v.Type().Implements(tpTableIndices) {
return v.Interface().(TableIndices).TableIndices()
}
if v.Kind() == reflect.Ptr {
v = v.Elem()
if v.Type().Implements(tpTableIndices) {
return v.Interface().(TableIndices).TableIndices()
}
} else if v.CanAddr() {
v1 := v.Addr()
if v1.Type().Implements(tpTableIndices) {
return v1.Interface().(TableIndices).TableIndices()
}
}
return nil
}