github.com/mailru/activerecord@v1.12.2/internal/pkg/parser/index.go (about) 1 package parser 2 3 import ( 4 "fmt" 5 "go/ast" 6 "strconv" 7 "strings" 8 9 "github.com/mailru/activerecord/internal/pkg/arerror" 10 "github.com/mailru/activerecord/internal/pkg/ds" 11 ) 12 13 func ParseIndexPartTag(field *ast.Field, ind *ds.IndexDeclaration, indexMap map[string]int, fields []ds.FieldDeclaration, indexes []ds.IndexDeclaration) error { 14 tagParam, err := splitTag(field, CheckFlagEmpty, map[TagNameType]ParamValueRule{}) 15 if err != nil { 16 return &arerror.ErrParseTypeIndexDecl{IndexType: "indexpart", Name: ind.Name, Err: err} 17 } 18 19 var exInd ds.IndexDeclaration 20 21 var fieldnum int64 = 1 22 23 for _, kv := range tagParam { 24 switch kv[0] { 25 case "selector": 26 ind.Selector = kv[1] 27 case "index": 28 exIndNum, ex := indexMap[kv[1]] 29 if !ex { 30 return &arerror.ErrParseTypeIndexTagDecl{IndexType: "indexpart", Name: ind.Name, TagName: kv[0], TagValue: kv[1], Err: arerror.ErrIndexNotExist} 31 } 32 33 exInd = indexes[exIndNum] 34 ind.Num = exInd.Num 35 case "fieldnum": 36 fNum, err := strconv.ParseInt(kv[1], 10, 64) 37 if err != nil { 38 return &arerror.ErrParseTypeIndexTagDecl{IndexType: "indexpart", Name: ind.Name, TagName: kv[0], TagValue: kv[1], Err: arerror.ErrParseTagValueInvalid} 39 } 40 41 fieldnum = fNum 42 default: 43 return &arerror.ErrParseTypeIndexTagDecl{IndexType: "indexpart", Name: ind.Name, TagName: kv[0], TagValue: kv[1], Err: arerror.ErrParseTagUnknown} 44 } 45 } 46 47 if int64(len(exInd.Fields)) < fieldnum { 48 return &arerror.ErrParseTypeIndexDecl{IndexType: "indexpart", Name: ind.Name, Err: arerror.ErrParseIndexFieldnumToBig} 49 } 50 51 if int64(len(exInd.Fields)) == fieldnum { 52 return &arerror.ErrParseTypeIndexDecl{IndexType: "indexpart", Name: ind.Name, Err: arerror.ErrParseIndexFieldnumEqual} 53 } 54 55 for f := int64(0); f < fieldnum; f++ { 56 ind.Fields = append(ind.Fields, exInd.Fields[f]) 57 ind.FieldsMap[fields[exInd.Fields[f]].Name] = exInd.FieldsMap[fields[exInd.Fields[f]].Name] 58 } 59 60 return nil 61 } 62 63 func ParseIndexPart(dst *ds.RecordPackage, fields []*ast.Field) error { 64 if len(fields) == 0 { 65 return nil 66 } 67 68 for _, field := range fields { 69 if field.Names == nil || len(field.Names) != 1 { 70 return &arerror.ErrParseTypeIndexDecl{IndexType: "indexpart", Err: arerror.ErrNameDeclaration} 71 } 72 73 ind := ds.IndexDeclaration{ 74 Name: field.Names[0].Name, 75 Fields: []int{}, 76 FieldsMap: map[string]ds.IndexField{}, 77 Selector: "SelectBy" + field.Names[0].Name, 78 Partial: true, 79 } 80 81 if err := checkBoolType(field.Type); err != nil { 82 return &arerror.ErrParseTypeIndexDecl{IndexType: "indexpart", Name: ind.Name, Err: arerror.ErrTypeNotBool} 83 } 84 85 if err := ParseIndexPartTag(field, &ind, dst.IndexMap, dst.Fields, dst.Indexes); err != nil { 86 return fmt.Errorf("error parse trigger tag: %w", err) 87 } 88 89 if len(ind.Fields) == 0 { 90 return &arerror.ErrParseTypeIndexDecl{IndexType: "indexpart", Name: ind.Name, Err: arerror.ErrParseIndexFieldnumRequired} 91 } 92 93 if err := dst.AddIndex(ind); err != nil { 94 return err 95 } 96 } 97 98 return nil 99 } 100 101 func ParseIndexTag(field *ast.Field, ind *ds.IndexDeclaration, fieldsMap map[string]int) error { 102 tagParam, err := splitTag(field, CheckFlagEmpty, map[TagNameType]ParamValueRule{PrimaryKeyTag: ParamNotNeedValue, UniqueTag: ParamNotNeedValue}) 103 if err != nil { 104 return &arerror.ErrParseTypeIndexDecl{IndexType: "index", Name: ind.Name, Err: err} 105 } 106 107 for _, kv := range tagParam { 108 switch TagNameType(kv[0]) { 109 case PrimaryKeyTag: 110 ind.Primary = true 111 case UniqueTag: 112 ind.Unique = true 113 case SelectorTag: 114 ind.Selector = kv[1] 115 case FieldsTag: 116 for _, fieldName := range strings.Split(kv[1], ",") { 117 if fldNum, ex := fieldsMap[fieldName]; !ex { 118 return &arerror.ErrParseTypeIndexTagDecl{IndexType: "index", Name: ind.Name, TagName: kv[0], TagValue: kv[1], Err: arerror.ErrFieldNotExist} 119 } else if _, ex := ind.FieldsMap[fieldName]; ex { 120 return &arerror.ErrParseTypeIndexTagDecl{IndexType: "index", Name: ind.Name, TagName: kv[0], TagValue: kv[1], Err: arerror.ErrDuplicate} 121 } else { 122 ind.FieldsMap[fieldName] = ds.IndexField{IndField: fldNum, Order: ds.IndexOrderAsc} 123 ind.Fields = append(ind.Fields, fldNum) 124 } 125 } 126 case OrderDescTag: 127 for _, fn := range strings.Split(kv[1], ",") { 128 if _, ex := fieldsMap[fn]; !ex { 129 return &arerror.ErrParseTypeIndexTagDecl{IndexType: "index", Name: ind.Name, TagName: kv[0], TagValue: kv[1], Err: arerror.ErrFieldNotExist} 130 } else if indField, ex := ind.FieldsMap[fn]; !ex { 131 return &arerror.ErrParseTypeIndexTagDecl{IndexType: "index", Name: ind.Name, TagName: kv[0], TagValue: kv[1], Err: arerror.ErrFieldNotExist} 132 } else { 133 indField.Order = ds.IndexOrderDesc 134 } 135 } 136 default: 137 return &arerror.ErrParseTypeIndexTagDecl{IndexType: "index", Name: ind.Name, TagName: kv[0], TagValue: kv[1], Err: arerror.ErrParseTagUnknown} 138 } 139 } 140 141 return nil 142 } 143 144 func ParseIndexes(dst *ds.RecordPackage, fields []*ast.Field) error { 145 if len(fields) == 0 { 146 return nil 147 } 148 149 for _, field := range fields { 150 if field.Names == nil || len(field.Names) != 1 { 151 return &arerror.ErrParseTypeIndexDecl{IndexType: "index", Err: arerror.ErrNameDeclaration} 152 } 153 154 ind := ds.IndexDeclaration{ 155 Name: field.Names[0].Name, 156 Fields: []int{}, 157 FieldsMap: map[string]ds.IndexField{}, 158 Selector: "SelectBy" + field.Names[0].Name} 159 160 if err := checkBoolType(field.Type); err != nil { 161 return &arerror.ErrParseTypeIndexDecl{IndexType: "index", Name: ind.Name, Err: arerror.ErrTypeNotBool} 162 } 163 164 if err := ParseIndexTag(field, &ind, dst.FieldsMap); err != nil { 165 return fmt.Errorf("error parse indexTag: %w", err) 166 } 167 168 if err := dst.AddIndex(ind); err != nil { 169 return err 170 } 171 } 172 173 return nil 174 }