gitee.com/h79/goutils@v1.22.10/dao/wrapper/join.go (about)

     1  package wrapper
     2  
     3  import (
     4  	commonoption "gitee.com/h79/goutils/common/option"
     5  	"strings"
     6  )
     7  
     8  // 内连接(inner join…on…)
     9  // 全外连接(full join…on…)
    10  // 左连接(left join…on…)
    11  // 右连接(right join…on…)
    12  // 交叉连接(cross join …on…)
    13  const (
    14  	JoinLeft  = "LEFT"
    15  	JoinRight = "RIGHT"
    16  	JoinInner = "INNER"
    17  	JoinFull  = "FULL"
    18  	JonnCross = "CROSS"
    19  )
    20  
    21  var _ IBuilder = (*Join)(nil)
    22  
    23  type Join struct {
    24  	Type  string   `json:"type" yaml:"type"`
    25  	Table string   `json:"table" yaml:"table"`
    26  	Alias string   `json:"as" yaml:"as"`
    27  	ON    string   `json:"expr" yaml:"expr"`
    28  	Using []string `json:"using" yaml:"using"`
    29  }
    30  
    31  func (jn *Join) Is() bool {
    32  	if jn.Type == "" {
    33  		return false
    34  	}
    35  	if jn.Table == "" {
    36  		if jn.ON == "" {
    37  			return false
    38  		}
    39  	} else if jn.ON == "" && len(jn.Using) == 0 {
    40  		return false
    41  	}
    42  	return true
    43  }
    44  
    45  func (jn *Join) JoinType() (string, bool) {
    46  	jt := strings.ToUpper(jn.Type)
    47  	return jt, (jt == JoinLeft ||
    48  		jt == JoinRight ||
    49  		jt == JoinFull ||
    50  		jt == JoinInner ||
    51  		jt == JonnCross) && jn.Is()
    52  }
    53  
    54  func (jn *Join) Build(opts ...commonoption.Option) string {
    55  	joinType, ok := jn.JoinType()
    56  	if !ok {
    57  		return ""
    58  	}
    59  	var builder = strings.Builder{}
    60  	builder.WriteByte(' ')
    61  	builder.WriteString(joinType)
    62  	builder.WriteString(" JOIN ")
    63  	if jn.Table != "" {
    64  		AddQuoted(&builder, jn.Table)
    65  		AddAlias(&builder, jn.Alias)
    66  		if len(jn.ON) > 0 {
    67  			builder.WriteString(" ON ")
    68  			builder.WriteString(jn.ON)
    69  		} else if len(jn.Using) > 0 {
    70  			builder.WriteString(" USING (")
    71  			for idx, c := range jn.Using {
    72  				if idx > 0 {
    73  					builder.WriteByte(',')
    74  				}
    75  				builder.WriteByte('\'')
    76  				builder.WriteString(c)
    77  				builder.WriteByte('\'')
    78  			}
    79  			builder.WriteByte(')')
    80  		}
    81  	} else {
    82  		// 直接表达式
    83  		builder.WriteString(jn.ON)
    84  	}
    85  	return builder.String()
    86  }
    87  
    88  var _ IBuilder = (*MultiJoin)(nil)
    89  
    90  type MultiJoin struct {
    91  	Joins []Join
    92  }
    93  
    94  func (j *MultiJoin) Add(join Join) {
    95  	j.Joins = append(j.Joins, join)
    96  }
    97  
    98  func (j *MultiJoin) Is() bool {
    99  	return len(j.Joins) > 0
   100  }
   101  
   102  func (j *MultiJoin) Query() string {
   103  	return ""
   104  }
   105  
   106  func (j *MultiJoin) Value() []interface{} {
   107  	return nil
   108  }
   109  
   110  func (j *MultiJoin) Build(opts ...commonoption.Option) string {
   111  	var b = strings.Builder{}
   112  	for i := range j.Joins {
   113  		b.WriteString(" ")
   114  		b.WriteString(j.Joins[i].Build(opts...))
   115  	}
   116  	b.WriteString(" ")
   117  	return b.String()
   118  }