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  }