github.com/unionj-cloud/go-doudou/v2@v2.3.5/toolkit/gormgen/field/association.go (about)

     1  package field
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"gorm.io/gorm"
     8  	"gorm.io/gorm/clause"
     9  	"gorm.io/gorm/schema"
    10  )
    11  
    12  // RelationshipType table relationship
    13  type RelationshipType schema.RelationshipType
    14  
    15  const (
    16  	// HasOne a has one association sets up a one-to-one connection with another model. Reference https://gorm.io/docs/has_one.html
    17  	HasOne RelationshipType = RelationshipType(schema.HasOne) // HasOneRel has one relationship
    18  	// HasMany a has many association sets up a one-to-many connection with another model. Reference https://gorm.io/docs/has_many.html
    19  	HasMany RelationshipType = RelationshipType(schema.HasMany) // HasManyRel has many relationships
    20  	// BelongsTo A belongs to association sets up a one-to-one connection with another model. Reference https://gorm.io/docs/belongs_to.html
    21  	BelongsTo RelationshipType = RelationshipType(schema.BelongsTo) // BelongsToRel belongs to relationship
    22  	// Many2Many Many to Many add a join table between two models. Reference https://gorm.io/docs/many2many.html
    23  	Many2Many RelationshipType = RelationshipType(schema.Many2Many) // Many2ManyRel many to many relationship
    24  )
    25  
    26  type relationScope func(*gorm.DB) *gorm.DB
    27  
    28  var (
    29  	// RelationFieldUnscoped relation fild unscoped
    30  	RelationFieldUnscoped relationScope = func(tx *gorm.DB) *gorm.DB {
    31  		return tx.Unscoped()
    32  	}
    33  )
    34  
    35  var ns = schema.NamingStrategy{}
    36  
    37  // RelationField interface for relation field
    38  type RelationField interface {
    39  	Name() string
    40  	Path() string
    41  	// Field return expr for Select
    42  	// Field() return "<self>" field name in struct
    43  	// Field("RelateField") return "<self>.RelateField" for Select
    44  	// Field("RelateField", "RelateRelateField") return "<self>.RelateField.RelateRelateField" for Select
    45  	// ex:
    46  	// 	Select(u.CreditCards.Field()) equals to GORM: Select("CreditCards")
    47  	// 	Select(u.CreditCards.Field("Bank")) equals to GORM: Select("CreditCards.Bank")
    48  	// 	Select(u.CreditCards.Field("Bank","Owner")) equals to GORM: Select("CreditCards.Bank.Owner")
    49  	Field(fields ...string) Expr
    50  
    51  	On(conds ...Expr) RelationField
    52  	Select(conds ...Expr) RelationField
    53  	Order(columns ...Expr) RelationField
    54  	Clauses(hints ...clause.Expression) RelationField
    55  	Scopes(funcs ...relationScope) RelationField
    56  	Offset(offset int) RelationField
    57  	Limit(limit int) RelationField
    58  
    59  	GetConds() []Expr
    60  	GetSelects() []Expr
    61  	GetOrderCol() []Expr
    62  	GetClauses() []clause.Expression
    63  	GetScopes() []relationScope
    64  	GetPage() (offset, limit int)
    65  }
    66  
    67  // Relation relation meta info
    68  type Relation struct {
    69  	relationship RelationshipType
    70  
    71  	fieldName  string
    72  	fieldType  string
    73  	fieldPath  string
    74  	fieldModel interface{} // store relaiton model
    75  
    76  	childRelations []Relation
    77  
    78  	conds         []Expr
    79  	selects       []Expr
    80  	order         []Expr
    81  	clauses       []clause.Expression
    82  	scopes        []relationScope
    83  	limit, offset int
    84  }
    85  
    86  // Name relation field' name
    87  func (r Relation) Name() string { return r.fieldName }
    88  
    89  // Path relation field's path
    90  func (r Relation) Path() string { return r.fieldPath }
    91  
    92  // Type relation field's type
    93  func (r Relation) Type() string { return r.fieldType }
    94  
    95  // Model relation field's model
    96  func (r Relation) Model() interface{} { return r.fieldModel }
    97  
    98  // Relationship relationship between field and table struct
    99  func (r Relation) Relationship() RelationshipType { return r.relationship }
   100  
   101  // RelationshipName relationship's name
   102  func (r Relation) RelationshipName() string { return ns.SchemaName(string(r.relationship)) }
   103  
   104  // ChildRelations return child relations
   105  func (r Relation) ChildRelations() []Relation { return r.childRelations }
   106  
   107  // Field build field
   108  func (r Relation) Field(fields ...string) Expr {
   109  	if len(fields) > 0 {
   110  		return NewString("", r.fieldName+"."+strings.Join(fields, ".")).appendBuildOpts(WithoutQuote)
   111  	}
   112  	return NewString("", r.fieldName).appendBuildOpts(WithoutQuote)
   113  }
   114  
   115  // AppendChildRelation append child relationship
   116  func (r *Relation) AppendChildRelation(relations ...Relation) {
   117  	r.childRelations = append(r.childRelations, wrapPath(r.fieldPath, relations)...)
   118  }
   119  
   120  // On relation condition
   121  func (r Relation) On(conds ...Expr) RelationField {
   122  	r.conds = append(r.conds, conds...)
   123  	return &r
   124  }
   125  
   126  // Select relation select columns
   127  func (r Relation) Select(columns ...Expr) RelationField {
   128  	r.selects = append(r.selects, columns...)
   129  	return &r
   130  }
   131  
   132  // Order relation order columns
   133  func (r Relation) Order(columns ...Expr) RelationField {
   134  	r.order = append(r.order, columns...)
   135  	return &r
   136  }
   137  
   138  // Clauses set relation clauses
   139  func (r Relation) Clauses(hints ...clause.Expression) RelationField {
   140  	r.clauses = append(r.clauses, hints...)
   141  	return &r
   142  }
   143  
   144  // Scopes set scopes func
   145  func (r Relation) Scopes(funcs ...relationScope) RelationField {
   146  	r.scopes = append(r.scopes, funcs...)
   147  	return &r
   148  }
   149  
   150  // Offset set relation offset
   151  func (r Relation) Offset(offset int) RelationField {
   152  	r.offset = offset
   153  	return &r
   154  }
   155  
   156  // Limit set relation limit
   157  func (r Relation) Limit(limit int) RelationField {
   158  	r.limit = limit
   159  	return &r
   160  }
   161  
   162  // GetConds get query conditions
   163  func (r *Relation) GetConds() []Expr { return r.conds }
   164  
   165  // GetSelects get select columns
   166  func (r *Relation) GetSelects() []Expr { return r.selects }
   167  
   168  // GetOrderCol get order columns
   169  func (r *Relation) GetOrderCol() []Expr { return r.order }
   170  
   171  // GetClauses get clauses
   172  func (r *Relation) GetClauses() []clause.Expression { return r.clauses }
   173  
   174  // GetScopes get scope functions
   175  func (r *Relation) GetScopes() []relationScope { return r.scopes } // nolint
   176  
   177  // GetPage get offset and limit
   178  func (r *Relation) GetPage() (offset, limit int) { return r.offset, r.limit }
   179  
   180  // StructField return struct field code
   181  func (r *Relation) StructField() (fieldStr string) {
   182  	for _, relation := range r.childRelations {
   183  		fieldStr += relation.fieldName + " struct {\nfield.RelationField\n" + relation.StructField() + "}\n"
   184  	}
   185  	return fieldStr
   186  }
   187  
   188  // StructFieldInit return field initialize code
   189  func (r *Relation) StructFieldInit() string {
   190  	initStr := fmt.Sprintf("RelationField: field.NewRelation(%q, %q),\n", r.fieldPath, r.fieldType)
   191  	for _, relation := range r.childRelations {
   192  		initStr += relation.fieldName + ": struct {\nfield.RelationField\n" + strings.TrimSpace(relation.StructField()) + "}"
   193  		initStr += "{\n" + relation.StructFieldInit() + "},\n"
   194  	}
   195  	return initStr
   196  }
   197  
   198  func wrapPath(root string, rs []Relation) []Relation {
   199  	result := make([]Relation, len(rs))
   200  	for i, r := range rs {
   201  		r.fieldPath = root + "." + r.fieldPath
   202  		r.childRelations = wrapPath(root, r.childRelations)
   203  		result[i] = r
   204  	}
   205  	return result
   206  }
   207  
   208  var defaultRelationshipPrefix = map[RelationshipType]string{
   209  	// HasOne:    "",
   210  	// BelongsTo: "",
   211  	HasMany:   "[]",
   212  	Many2Many: "[]",
   213  }
   214  
   215  // RelateConfig config for relationship
   216  type RelateConfig struct {
   217  	RelatePointer      bool
   218  	RelateSlice        bool
   219  	RelateSlicePointer bool
   220  
   221  	JSONTag      string
   222  	GORMTag      GormTag
   223  	Tag          Tag
   224  	OverwriteTag Tag
   225  }
   226  
   227  // RelateFieldPrefix return generated relation field's type
   228  func (c *RelateConfig) RelateFieldPrefix(relationshipType RelationshipType) string {
   229  	switch {
   230  	case c.RelatePointer:
   231  		return "*"
   232  	case c.RelateSlice:
   233  		return "[]"
   234  	case c.RelateSlicePointer:
   235  		return "[]*"
   236  	default:
   237  		return defaultRelationshipPrefix[relationshipType]
   238  	}
   239  }
   240  func (c *RelateConfig) GetTag(fieldName string) Tag {
   241  	if c == nil {
   242  		return Tag{}
   243  	}
   244  	if c.OverwriteTag != nil {
   245  		return c.OverwriteTag
   246  	}
   247  	if c.Tag == nil {
   248  		c.Tag = Tag{}
   249  	}
   250  	if c.JSONTag == "" {
   251  		c.JSONTag = ns.ColumnName("", fieldName)
   252  	}
   253  	c.Tag.Set(TagKeyJson, c.JSONTag)
   254  	return c.Tag
   255  }