From 152e1bcc6902eacc75b7c0667d806afa73c8afac Mon Sep 17 00:00:00 2001 From: Andrew Thornton Date: Sat, 23 Apr 2022 18:07:58 +0100 Subject: [PATCH] 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 --- tags/parser.go | 58 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/tags/parser.go b/tags/parser.go index 83026862..028f8d0b 100644 --- a/tags/parser.go +++ b/tags/parser.go @@ -21,10 +21,15 @@ import ( "xorm.io/xorm/schemas" ) -var ( - // ErrUnsupportedType represents an unsupported type error - ErrUnsupportedType = errors.New("unsupported type") -) +// ErrUnsupportedType represents an unsupported type error +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 +}