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

     1  package field
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"gorm.io/gorm"
     8  	"gorm.io/gorm/clause"
     9  )
    10  
    11  var (
    12  	// Star a symbol of "*"
    13  	Star = NewAsterisk("")
    14  	// ALL same with Star
    15  	ALL = Star
    16  )
    17  
    18  // Option field option
    19  type Option func(clause.Column) clause.Column
    20  
    21  var (
    22  	banColumnRaw Option = func(col clause.Column) clause.Column {
    23  		col.Raw = false
    24  		return col
    25  	}
    26  )
    27  
    28  // ======================== generic field =======================
    29  
    30  // NewField create new field
    31  func NewField(table, column string, opts ...Option) Field {
    32  	return Field{expr: expr{col: toColumn(table, column, opts...)}}
    33  }
    34  
    35  // NewSerializer create new field2
    36  func NewSerializer(table, column string, opts ...Option) Serializer {
    37  	return Serializer{expr: expr{col: toColumn(table, column, opts...)}}
    38  }
    39  
    40  // NewAsterisk create new * field
    41  func NewAsterisk(table string, opts ...Option) Asterisk {
    42  	return Asterisk{asteriskExpr: asteriskExpr{expr{col: toColumn(table, "*", opts...)}}}
    43  }
    44  
    45  // ======================== integer =======================
    46  
    47  // NewInt create new Int
    48  func NewInt(table, column string, opts ...Option) Int {
    49  	return Int{expr: expr{col: toColumn(table, column, opts...)}}
    50  }
    51  
    52  // NewInt8 create new Int8
    53  func NewInt8(table, column string, opts ...Option) Int8 {
    54  	return Int8{expr: expr{col: toColumn(table, column, opts...)}}
    55  }
    56  
    57  // NewInt16 ...
    58  func NewInt16(table, column string, opts ...Option) Int16 {
    59  	return Int16{expr: expr{col: toColumn(table, column, opts...)}}
    60  }
    61  
    62  // NewInt32 ...
    63  func NewInt32(table, column string, opts ...Option) Int32 {
    64  	return Int32{expr: expr{col: toColumn(table, column, opts...)}}
    65  }
    66  
    67  // NewInt64 ...
    68  func NewInt64(table, column string, opts ...Option) Int64 {
    69  	return Int64{expr: expr{col: toColumn(table, column, opts...)}}
    70  }
    71  
    72  // NewUint ...
    73  func NewUint(table, column string, opts ...Option) Uint {
    74  	return Uint{expr: expr{col: toColumn(table, column, opts...)}}
    75  }
    76  
    77  // NewUint8 ...
    78  func NewUint8(table, column string, opts ...Option) Uint8 {
    79  	return Uint8{expr: expr{col: toColumn(table, column, opts...)}}
    80  }
    81  
    82  // NewUint16 ...
    83  func NewUint16(table, column string, opts ...Option) Uint16 {
    84  	return Uint16{expr: expr{col: toColumn(table, column, opts...)}}
    85  }
    86  
    87  // NewUint32 ...
    88  func NewUint32(table, column string, opts ...Option) Uint32 {
    89  	return Uint32{expr: expr{col: toColumn(table, column, opts...)}}
    90  }
    91  
    92  // NewUint64 ...
    93  func NewUint64(table, column string, opts ...Option) Uint64 {
    94  	return Uint64{expr: expr{col: toColumn(table, column, opts...)}}
    95  }
    96  
    97  // ======================== float =======================
    98  
    99  // NewFloat32 ...
   100  func NewFloat32(table, column string, opts ...Option) Float32 {
   101  	return Float32{expr: expr{col: toColumn(table, column, opts...)}}
   102  }
   103  
   104  // NewFloat64 ...
   105  func NewFloat64(table, column string, opts ...Option) Float64 {
   106  	return Float64{expr: expr{col: toColumn(table, column, opts...)}}
   107  }
   108  
   109  // ======================== string =======================
   110  
   111  // NewString ...
   112  func NewString(table, column string, opts ...Option) String {
   113  	return String{expr: expr{col: toColumn(table, column, opts...)}}
   114  }
   115  
   116  // NewBytes ...
   117  func NewBytes(table, column string, opts ...Option) Bytes {
   118  	return Bytes{expr: expr{col: toColumn(table, column, opts...)}}
   119  }
   120  
   121  // ======================== bool =======================
   122  
   123  // NewBool ...
   124  func NewBool(table, column string, opts ...Option) Bool {
   125  	return Bool{expr: expr{col: toColumn(table, column, opts...)}}
   126  }
   127  
   128  // ======================== time =======================
   129  
   130  // NewTime ...
   131  func NewTime(table, column string, opts ...Option) Time {
   132  	return Time{expr: expr{col: toColumn(table, column, opts...)}}
   133  }
   134  
   135  func toColumn(table, column string, opts ...Option) clause.Column {
   136  	col := clause.Column{Table: table, Name: column}
   137  	for _, opt := range opts {
   138  		col = opt(col)
   139  	}
   140  	return banColumnRaw(col)
   141  }
   142  
   143  // ======================== boolean operate ========================
   144  
   145  // Or return or condition
   146  func Or(exprs ...Expr) Expr {
   147  	return &expr{e: clause.Or(toExpression(exprs...)...)}
   148  }
   149  
   150  // And return and condition
   151  func And(exprs ...Expr) Expr {
   152  	return &expr{e: clause.And(toExpression(exprs...)...)}
   153  }
   154  
   155  // Not return not condition
   156  func Not(exprs ...Expr) Expr {
   157  	return &expr{e: clause.Not(toExpression(exprs...)...)}
   158  }
   159  
   160  func toExpression(conds ...Expr) []clause.Expression {
   161  	exprs := make([]clause.Expression, len(conds))
   162  	for i, cond := range conds {
   163  		exprs[i] = cond.expression()
   164  	}
   165  	return exprs
   166  }
   167  
   168  // ======================== subquery method ========================
   169  
   170  // ContainsSubQuery return contains subquery
   171  // when len(columns) == 1, equal to columns[0] IN (subquery)
   172  // when len(columns) > 1, equal to (columns[0], columns[1], ...) IN (subquery)
   173  func ContainsSubQuery(columns []Expr, subQuery *gorm.DB) Expr {
   174  	switch len(columns) {
   175  	case 0:
   176  		return expr{e: clause.Expr{}}
   177  	case 1:
   178  		return expr{e: clause.Expr{
   179  			SQL:  "? IN (?)",
   180  			Vars: []interface{}{columns[0].RawExpr(), subQuery},
   181  		}}
   182  	default: // len(columns) > 0
   183  		placeholders := make([]string, len(columns))
   184  		cols := make([]interface{}, len(columns))
   185  		for i, c := range columns {
   186  			placeholders[i], cols[i] = "?", c.RawExpr()
   187  		}
   188  		return expr{e: clause.Expr{
   189  			SQL:  fmt.Sprintf("(%s) IN (?)", strings.Join(placeholders, ",")),
   190  			Vars: append(cols, subQuery),
   191  		}}
   192  	}
   193  }
   194  
   195  // AssignSubQuery assign with subquery
   196  func AssignSubQuery(columns []Expr, subQuery *gorm.DB) AssignExpr {
   197  	cols := make([]string, len(columns))
   198  	for i, c := range columns {
   199  		cols[i] = string(c.BuildColumn(subQuery.Statement))
   200  	}
   201  
   202  	name := cols[0]
   203  	if len(cols) > 1 {
   204  		name = "(" + strings.Join(cols, ",") + ")"
   205  	}
   206  
   207  	return expr{e: clause.Set{{
   208  		Column: clause.Column{Name: name, Raw: true},
   209  		Value:  gorm.Expr("(?)", subQuery),
   210  	}}}
   211  }
   212  
   213  // CompareOperator compare operator
   214  type CompareOperator string
   215  
   216  const (
   217  	// EqOp =
   218  	EqOp CompareOperator = " = "
   219  	// NeqOp <>
   220  	NeqOp CompareOperator = " <> "
   221  	// GtOp >
   222  	GtOp CompareOperator = " > "
   223  	// GteOp >=
   224  	GteOp CompareOperator = " >= "
   225  	// LtOp <
   226  	LtOp CompareOperator = " < "
   227  	// LteOp <=
   228  	LteOp CompareOperator = " <= "
   229  	// ExistsOp EXISTS
   230  	ExistsOp CompareOperator = "EXISTS "
   231  )
   232  
   233  // CompareSubQuery compare with sub query
   234  func CompareSubQuery(op CompareOperator, column Expr, subQuery *gorm.DB) Expr {
   235  	if op == ExistsOp {
   236  		return expr{e: clause.Expr{
   237  			SQL:  fmt.Sprint(op, "(?)"),
   238  			Vars: []interface{}{subQuery},
   239  		}}
   240  	}
   241  	return expr{e: clause.Expr{
   242  		SQL:  fmt.Sprint("?", op, "(?)"),
   243  		Vars: []interface{}{column.RawExpr(), subQuery},
   244  	}}
   245  }
   246  
   247  // Value ...
   248  type Value interface {
   249  	expr() clause.Expr
   250  
   251  	// implement Condition
   252  	BeCond() interface{}
   253  	CondError() error
   254  }
   255  
   256  type val clause.Expr
   257  
   258  func (v val) expr() clause.Expr   { return clause.Expr(v) }
   259  func (v val) BeCond() interface{} { return v }
   260  func (val) CondError() error      { return nil }
   261  
   262  // Values convert value to expression which implement Value
   263  func Values(value interface{}) Value {
   264  	return val(clause.Expr{
   265  		SQL:                "?",
   266  		Vars:               []interface{}{value},
   267  		WithoutParentheses: true,
   268  	})
   269  }
   270  
   271  // ContainsValue return expression which compare with value
   272  func ContainsValue(columns []Expr, value Value) Expr {
   273  	switch len(columns) {
   274  	case 0:
   275  		return expr{e: clause.Expr{}}
   276  	case 1:
   277  		return expr{e: clause.Expr{
   278  			SQL:  "? IN (?)",
   279  			Vars: []interface{}{columns[0].RawExpr(), value.expr()},
   280  		}}
   281  	default: // len(columns) > 0
   282  		vars := make([]string, len(columns))
   283  		queryCols := make([]interface{}, len(columns))
   284  		for i, c := range columns {
   285  			vars[i], queryCols[i] = "?", c.RawExpr()
   286  		}
   287  		return expr{e: clause.Expr{
   288  			SQL:  fmt.Sprintf("(%s) IN (?)", strings.Join(vars, ", ")),
   289  			Vars: append(queryCols, value.expr()),
   290  		}}
   291  	}
   292  }
   293  
   294  // EmptyExpr return a empty expression
   295  func EmptyExpr() Expr { return expr{e: clause.Expr{}} }
   296  
   297  // AssociationFields all association
   298  var AssociationFields Expr = NewString("", clause.Associations).appendBuildOpts(WithoutQuote)
   299  
   300  // Associations ...
   301  var Associations RelationField = NewRelation(clause.Associations, "")
   302  
   303  // NewRelation return a new Relation for association
   304  func NewRelation(fieldName string, fieldType string, relations ...Relation) *Relation {
   305  	return &Relation{
   306  		fieldName:      fieldName,
   307  		fieldPath:      fieldName,
   308  		fieldType:      fieldType,
   309  		childRelations: wrapPath(fieldName, relations),
   310  	}
   311  }
   312  
   313  // NewRelationWithType return a Relation with specified field type
   314  func NewRelationWithType(relationship RelationshipType, fieldName string, fieldType string, relations ...Relation) *Relation {
   315  	return &Relation{
   316  		relationship:   relationship,
   317  		fieldName:      fieldName,
   318  		fieldType:      fieldType,
   319  		fieldPath:      fieldName,
   320  		childRelations: wrapPath(fieldName, relations),
   321  	}
   322  }
   323  
   324  // NewRelationWithModel return a Relation with specified model struct
   325  func NewRelationWithModel(relationship RelationshipType, fieldName string, fieldType string, fieldModel interface{}, relations ...Relation) *Relation {
   326  	return &Relation{
   327  		relationship: relationship,
   328  		fieldName:    fieldName,
   329  		fieldType:    fieldType,
   330  		fieldPath:    fieldName,
   331  		fieldModel:   fieldModel,
   332  	}
   333  }