diff --git a/config.go b/config.go index 1f4c00ee..eca1fa9f 100644 --- a/config.go +++ b/config.go @@ -24,6 +24,9 @@ const ( // WithQueryInterface generate code with exported interface object WithQueryInterface + + // WithGeneric generate code with generic + WithGeneric ) // Config generator's basic configuration diff --git a/field/bool.go b/field/bool.go index 8fd1206b..4c411b74 100644 --- a/field/bool.go +++ b/field/bool.go @@ -1,11 +1,13 @@ package field // Bool boolean type field -type Bool Field +type Bool struct { + genericsField[bool] +} // Not ... func (field Bool) Not() Bool { - return Bool{field.not()} + return Bool{genericsField[bool]{field.not()}} } // Is ... @@ -15,37 +17,32 @@ func (field Bool) Is(value bool) Expr { // And boolean and func (field Bool) And(value bool) Expr { - return Bool{field.and(value)} + return Bool{genericsField[bool]{field.and(value)}} } // Or boolean or func (field Bool) Or(value bool) Expr { - return Bool{field.or(value)} + return Bool{genericsField[bool]{field.or(value)}} } // Xor ... func (field Bool) Xor(value bool) Expr { - return Bool{field.xor(value)} + return Bool{genericsField[bool]{field.xor(value)}} } // BitXor ... func (field Bool) BitXor(value bool) Expr { - return Bool{field.bitXor(value)} + return Bool{genericsField[bool]{field.bitXor(value)}} } // BitAnd ... func (field Bool) BitAnd(value bool) Expr { - return Bool{field.bitAnd(value)} + return Bool{genericsField[bool]{field.bitAnd(value)}} } // BitOr ... func (field Bool) BitOr(value bool) Expr { - return Bool{field.bitOr(value)} -} - -// Value ... -func (field Bool) Value(value bool) AssignExpr { - return field.value(value) + return Bool{genericsField[bool]{field.bitOr(value)}} } // Zero ... diff --git a/field/export.go b/field/export.go index aef41a75..3d5e9d1b 100644 --- a/field/export.go +++ b/field/export.go @@ -1,9 +1,12 @@ package field import ( + "database/sql/driver" "fmt" "strings" + "time" + "golang.org/x/exp/constraints" "gorm.io/gorm" "gorm.io/gorm/clause" ) @@ -15,6 +18,12 @@ var ( ALL = Star ) +// ScanValuer interface for Field +type ScanValuer interface { + Scan(src interface{}) error // sql.Scanner + Value() (driver.Value, error) // driver.Valuer +} + // Option field option type Option func(clause.Column) clause.Column @@ -29,7 +38,7 @@ var ( // NewField create new field func NewField(table, column string, opts ...Option) Field { - return Field{expr: expr{col: toColumn(table, column, opts...)}} + return Field(genericsField[driver.Valuer]{expr{col: toColumn(table, column, opts...)}}) } // NewSerializer create new field2 @@ -44,92 +53,97 @@ func NewAsterisk(table string, opts ...Option) Asterisk { // ======================== integer ======================= -// NewInt create new Int +// NewNumber build number type field +func NewNumber[T constraints.Integer | constraints.Float](table, column string, opts ...Option) Number[T] { + return newNumber[T](expr{col: toColumn(table, column, opts...)}) +} + +// NewInt create new field for int func NewInt(table, column string, opts ...Option) Int { - return Int{expr: expr{col: toColumn(table, column, opts...)}} + return NewNumber[int](table, column, opts...) } -// NewInt8 create new Int8 +// NewInt8 create new field for int8 func NewInt8(table, column string, opts ...Option) Int8 { - return Int8{expr: expr{col: toColumn(table, column, opts...)}} + return NewNumber[int8](table, column, opts...) } -// NewInt16 ... +// NewInt16 create new field for int16 func NewInt16(table, column string, opts ...Option) Int16 { - return Int16{expr: expr{col: toColumn(table, column, opts...)}} + return NewNumber[int16](table, column, opts...) } -// NewInt32 ... +// NewInt32 create new field for int32 func NewInt32(table, column string, opts ...Option) Int32 { - return Int32{expr: expr{col: toColumn(table, column, opts...)}} + return NewNumber[int32](table, column, opts...) } -// NewInt64 ... +// NewInt64 create new field for int64 func NewInt64(table, column string, opts ...Option) Int64 { - return Int64{expr: expr{col: toColumn(table, column, opts...)}} + return NewNumber[int64](table, column, opts...) } -// NewUint ... +// NewUint create new field for uint func NewUint(table, column string, opts ...Option) Uint { - return Uint{expr: expr{col: toColumn(table, column, opts...)}} + return NewNumber[uint](table, column, opts...) } -// NewUint8 ... +// NewUint8 create new field for uint8 func NewUint8(table, column string, opts ...Option) Uint8 { - return Uint8{expr: expr{col: toColumn(table, column, opts...)}} + return NewNumber[uint8](table, column, opts...) } -// NewUint16 ... +// NewUint16 create new field for uint16 func NewUint16(table, column string, opts ...Option) Uint16 { - return Uint16{expr: expr{col: toColumn(table, column, opts...)}} + return NewNumber[uint16](table, column, opts...) } -// NewUint32 ... +// NewUint32 create new field for uint32 func NewUint32(table, column string, opts ...Option) Uint32 { - return Uint32{expr: expr{col: toColumn(table, column, opts...)}} + return NewNumber[uint32](table, column, opts...) } -// NewUint64 ... +// NewUint64 create new field for uint64 func NewUint64(table, column string, opts ...Option) Uint64 { - return Uint64{expr: expr{col: toColumn(table, column, opts...)}} + return NewNumber[uint64](table, column, opts...) } // ======================== float ======================= -// NewFloat32 ... +// NewFloat32 create new field for float32 func NewFloat32(table, column string, opts ...Option) Float32 { - return Float32{expr: expr{col: toColumn(table, column, opts...)}} + return NewNumber[float32](table, column, opts...) } -// NewFloat64 ... +// NewFloat64 create new field for float64 func NewFloat64(table, column string, opts ...Option) Float64 { - return Float64{expr: expr{col: toColumn(table, column, opts...)}} + return NewNumber[float64](table, column, opts...) } // ======================== string ======================= // NewString ... func NewString(table, column string, opts ...Option) String { - return String{expr: expr{col: toColumn(table, column, opts...)}} + return newChars[string](expr{col: toColumn(table, column, opts...)}) } // NewBytes ... func NewBytes(table, column string, opts ...Option) Bytes { - return Bytes{expr: expr{col: toColumn(table, column, opts...)}} + return newChars[[]byte](expr{col: toColumn(table, column, opts...)}) } // ======================== bool ======================= // NewBool ... func NewBool(table, column string, opts ...Option) Bool { - return Bool{expr: expr{col: toColumn(table, column, opts...)}} + return Bool{genericsField[bool]{expr{col: toColumn(table, column, opts...)}}} } // ======================== time ======================= // NewTime ... func NewTime(table, column string, opts ...Option) Time { - return Time{expr: expr{col: toColumn(table, column, opts...)}} + return Time{genericsField[time.Time]{expr{col: toColumn(table, column, opts...)}}} } func toColumn(table, column string, opts ...Option) clause.Column { diff --git a/field/export_test.go b/field/export_test.go index 30c3d4b6..bc9652c1 100644 --- a/field/export_test.go +++ b/field/export_test.go @@ -315,7 +315,7 @@ func TestExpr_Build(t *testing.T) { Result: "`name` REGEXP ?", }, { - Expr: field.NewString("", "name").NotRegxp(".*"), + Expr: field.NewString("", "name").NotRegexp(".*"), ExpectedVars: []interface{}{".*"}, Result: "NOT `name` REGEXP ?", }, diff --git a/field/expr.go b/field/expr.go index 17175a49..86489210 100644 --- a/field/expr.go +++ b/field/expr.go @@ -1,6 +1,7 @@ package field import ( + "database/sql/driver" "fmt" "strings" "time" @@ -171,32 +172,32 @@ func (e expr) IsNotNull() Expr { return e.setE(clause.Expr{SQL: "? IS NOT NULL", Vars: []interface{}{e.RawExpr()}}) } -func (e expr) Count() Int { - return Int{e.setE(clause.Expr{SQL: "COUNT(?)", Vars: []interface{}{e.RawExpr()}})} +func (e expr) Count() Number[int] { + return newNumber[int](e.setE(clause.Expr{SQL: "COUNT(?)", Vars: []interface{}{e.RawExpr()}})) } -func (e expr) Distinct() Int { - return Int{e.setE(clause.Expr{SQL: "DISTINCT ?", Vars: []interface{}{e.RawExpr()}})} +func (e expr) Distinct() Number[int] { + return newNumber[int](e.setE(clause.Expr{SQL: "DISTINCT ?", Vars: []interface{}{e.RawExpr()}})) } -func (e expr) Length() Int { - return Int{e.setE(clause.Expr{SQL: "LENGTH(?)", Vars: []interface{}{e.RawExpr()}})} +func (e expr) Length() Number[int] { + return newNumber[int](e.setE(clause.Expr{SQL: "LENGTH(?)", Vars: []interface{}{e.RawExpr()}})) } -func (e expr) Max() Float64 { - return Float64{e.setE(clause.Expr{SQL: "MAX(?)", Vars: []interface{}{e.RawExpr()}})} +func (e expr) Max() Number[float64] { + return newNumber[float64](e.setE(clause.Expr{SQL: "MAX(?)", Vars: []interface{}{e.RawExpr()}})) } -func (e expr) Min() Float64 { - return Float64{e.setE(clause.Expr{SQL: "MIN(?)", Vars: []interface{}{e.RawExpr()}})} +func (e expr) Min() Number[float64] { + return newNumber[float64](e.setE(clause.Expr{SQL: "MIN(?)", Vars: []interface{}{e.RawExpr()}})) } -func (e expr) Avg() Float64 { - return Float64{e.setE(clause.Expr{SQL: "AVG(?)", Vars: []interface{}{e.RawExpr()}})} +func (e expr) Avg() Number[float64] { + return newNumber[float64](e.setE(clause.Expr{SQL: "AVG(?)", Vars: []interface{}{e.RawExpr()}})) } -func (e expr) Abs() Float64 { - return Float64{e.setE(clause.Expr{SQL: "ABS(?)", Vars: []interface{}{e.RawExpr()}})} +func (e expr) Abs() Number[float64] { + return newNumber[float64](e.setE(clause.Expr{SQL: "ABS(?)", Vars: []interface{}{e.RawExpr()}})) } func (e expr) Null() AssignExpr { @@ -238,19 +239,19 @@ func (e expr) SetCol(col Expr) AssignExpr { // ======================== operate columns ======================== func (e expr) AddCol(col Expr) Expr { - return Field{e.setE(clause.Expr{SQL: "? + ?", Vars: []interface{}{e.RawExpr(), col.RawExpr()}})} + return Field(genericsField[driver.Valuer]{e.setE(clause.Expr{SQL: "? + ?", Vars: []interface{}{e.RawExpr(), col.RawExpr()}})}) } func (e expr) SubCol(col Expr) Expr { - return Field{e.setE(clause.Expr{SQL: "? - ?", Vars: []interface{}{e.RawExpr(), col.RawExpr()}})} + return Field(genericsField[driver.Valuer]{e.setE(clause.Expr{SQL: "? - ?", Vars: []interface{}{e.RawExpr(), col.RawExpr()}})}) } func (e expr) MulCol(col Expr) Expr { - return Field{e.setE(clause.Expr{SQL: "(?) * (?)", Vars: []interface{}{e.RawExpr(), col.RawExpr()}})} + return Field(genericsField[driver.Valuer]{e.setE(clause.Expr{SQL: "(?) * (?)", Vars: []interface{}{e.RawExpr(), col.RawExpr()}})}) } func (e expr) DivCol(col Expr) Expr { - return Field{e.setE(clause.Expr{SQL: "(?) / (?)", Vars: []interface{}{e.RawExpr(), col.RawExpr()}})} + return Field(genericsField[driver.Valuer]{e.setE(clause.Expr{SQL: "(?) / (?)", Vars: []interface{}{e.RawExpr(), col.RawExpr()}})}) } func (e expr) ConcatCol(cols ...Expr) Expr { @@ -260,10 +261,10 @@ func (e expr) ConcatCol(cols ...Expr) Expr { placeholders = append(placeholders, "?") vars = append(vars, col.RawExpr()) } - return Field{e.setE(clause.Expr{ + return Field(genericsField[driver.Valuer]{e.setE(clause.Expr{ SQL: fmt.Sprintf("CONCAT(%s)", strings.Join(placeholders, ",")), Vars: vars, - })} + })}) } // ======================== keyword ======================== diff --git a/field/field.go b/field/field.go index 1fc42d65..aa8be782 100644 --- a/field/field.go +++ b/field/field.go @@ -1,89 +1,6 @@ package field -import ( - "database/sql/driver" - - "gorm.io/gorm/clause" -) - -// ScanValuer interface for Field -type ScanValuer interface { - Scan(src interface{}) error // sql.Scanner - Value() (driver.Value, error) // driver.Valuer -} +import "database/sql/driver" // Field a standard field struct -type Field struct{ expr } - -// Eq judge equal -func (field Field) Eq(value driver.Valuer) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq judge not equal -func (field Field) Neq(value driver.Valuer) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// In ... -func (field Field) In(values ...driver.Valuer) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} -} - -// NotIn ... -func (field Field) NotIn(values ...driver.Valuer) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Gt ... -func (field Field) Gt(value driver.Valuer) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte ... -func (field Field) Gte(value driver.Valuer) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt ... -func (field Field) Lt(value driver.Valuer) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte ... -func (field Field) Lte(value driver.Valuer) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// Like ... -func (field Field) Like(value driver.Valuer) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// Value ... -func (field Field) Value(value driver.Valuer) AssignExpr { - return field.value(value) -} - -// Sum ... -func (field Field) Sum() Field { - return Field{field.sum()} -} - -// IfNull ... -func (field Field) IfNull(value driver.Valuer) Expr { - return field.ifNull(value) -} - -// Field ... -func (field Field) Field(value []interface{}) Expr { - return field.field(value) -} - -func (field Field) toSlice(values ...driver.Valuer) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} +type Field = genericsField[driver.Valuer] diff --git a/field/float.go b/field/float.go deleted file mode 100644 index a7e26781..00000000 --- a/field/float.go +++ /dev/null @@ -1,255 +0,0 @@ -package field - -import "gorm.io/gorm/clause" - -// Float64 float64 type field -type Float64 Field - -// Eq equal to -func (field Float64) Eq(value float64) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field Float64) Neq(value float64) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field Float64) Gt(value float64) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte greater or equal to -func (field Float64) Gte(value float64) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field Float64) Lt(value float64) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field Float64) Lte(value float64) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// In ... -func (field Float64) In(values ...float64) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} -} - -// NotIn ... -func (field Float64) NotIn(values ...float64) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Between ... -func (field Float64) Between(left float64, right float64) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field Float64) NotBetween(left float64, right float64) Expr { - return Not(field.Between(left, right)) -} - -// Like ... -func (field Float64) Like(value float64) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// NotLike ... -func (field Float64) NotLike(value float64) Expr { - return expr{e: clause.Not(field.Like(value).expression())} -} - -// Add ... -func (field Float64) Add(value float64) Float64 { - return Float64{field.add(value)} -} - -// Sub ... -func (field Float64) Sub(value float64) Float64 { - return Float64{field.sub(value)} -} - -// Mul ... -func (field Float64) Mul(value float64) Float64 { - return Float64{field.mul(value)} -} - -// Div ... -func (field Float64) Div(value float64) Float64 { - return Float64{field.div(value)} -} - -// FloorDiv ... -func (field Float64) FloorDiv(value float64) Int { - return Int{field.floorDiv(value)} -} - -// Floor ... -func (field Float64) Floor() Int { - return Int{field.floor()} -} - -// Value set value -func (field Float64) Value(value float64) AssignExpr { - return field.value(value) -} - -// Zero set zero value -func (field Float64) Zero() AssignExpr { - return field.value(0) -} - -// Sum ... -func (field Float64) Sum() Float64 { - return Float64{field.sum()} -} - -// IfNull ... -func (field Float64) IfNull(value float64) Expr { - return field.ifNull(value) -} - -// Field ... -func (field Float64) Field(values ...float64) Float64 { - return Float64{field.field(values)} -} - -func (field Float64) toSlice(values ...float64) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} - -// Float32 float32 type field -type Float32 Float64 - -// Eq equal to -func (field Float32) Eq(value float32) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field Float32) Neq(value float32) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field Float32) Gt(value float32) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte greater or equal to -func (field Float32) Gte(value float32) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field Float32) Lt(value float32) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field Float32) Lte(value float32) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// In ... -func (field Float32) In(values ...float32) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} -} - -// NotIn ... -func (field Float32) NotIn(values ...float32) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Between ... -func (field Float32) Between(left float32, right float32) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field Float32) NotBetween(left float32, right float32) Expr { - return Not(field.Between(left, right)) -} - -// Like ... -func (field Float32) Like(value float32) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// NotLike ... -func (field Float32) NotLike(value float32) Expr { - return expr{e: clause.Not(field.Like(value).expression())} -} - -// Add ... -func (field Float32) Add(value float32) Float32 { - return Float32{field.add(value)} -} - -// Sub ... -func (field Float32) Sub(value float32) Float32 { - return Float32{field.sub(value)} -} - -// Mul ... -func (field Float32) Mul(value float32) Float32 { - return Float32{field.mul(value)} -} - -// Div ... -func (field Float32) Div(value float32) Float32 { - return Float32{field.div(value)} -} - -// FloorDiv ... -func (field Float32) FloorDiv(value float32) Int { - return Int{field.floorDiv(value)} -} - -// Floor ... -func (field Float32) Floor() Int { - return Int{field.floor()} -} - -// Value set value -func (field Float32) Value(value float32) AssignExpr { - return field.value(value) -} - -// Zero set zero value -func (field Float32) Zero() AssignExpr { - return field.value(0) -} - -// Sum ... -func (field Float32) Sum() Float32 { - return Float32{field.sum()} -} - -// IfNull ... -func (field Float32) IfNull(value float32) Expr { - return field.ifNull(value) -} - -// Field ... -func (field Float32) Field(values ...float32) Float32 { - return Float32{field.field(values)} -} - -func (field Float32) toSlice(values ...float32) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} diff --git a/field/function.go b/field/function.go index 4d901259..01d6ccc5 100644 --- a/field/function.go +++ b/field/function.go @@ -12,21 +12,21 @@ var Func = new(function) type function struct{} // UnixTimestamp same as UNIX_TIMESTAMP([date]) -func (f *function) UnixTimestamp(date ...string) Uint64 { +func (f *function) UnixTimestamp(date ...string) Number[uint64] { if len(date) > 0 { - return Uint64{expr{e: clause.Expr{SQL: "UNIX_TIMESTAMP(?)", Vars: []interface{}{date[0]}}}} + return newNumber[uint64](expr{e: clause.Expr{SQL: "UNIX_TIMESTAMP(?)", Vars: []interface{}{date[0]}}}) } - return Uint64{expr{e: clause.Expr{SQL: "UNIX_TIMESTAMP()"}}} + return newNumber[uint64](expr{e: clause.Expr{SQL: "UNIX_TIMESTAMP()"}}) } // FromUnixTime FROM_UNIXTIME(unix_timestamp[,format]) func (f *function) FromUnixTime(date uint64, format string) String { if strings.TrimSpace(format) != "" { - return String{expr{e: clause.Expr{SQL: "FROM_UNIXTIME(?, ?)", Vars: []interface{}{date, format}}}} + return String{genericsField[string]{expr{e: clause.Expr{SQL: "FROM_UNIXTIME(?, ?)", Vars: []interface{}{date, format}}}}} } - return String{expr{e: clause.Expr{SQL: "FROM_UNIXTIME(?)", Vars: []interface{}{date}}}} + return String{genericsField[string]{expr{e: clause.Expr{SQL: "FROM_UNIXTIME(?)", Vars: []interface{}{date}}}}} } func (f *function) Rand() String { - return String{expr{e: clause.Expr{SQL: "RAND()"}}} + return String{genericsField[string]{expr{e: clause.Expr{SQL: "RAND()"}}}} } diff --git a/field/generics.go b/field/generics.go new file mode 100644 index 00000000..80698fe3 --- /dev/null +++ b/field/generics.go @@ -0,0 +1,92 @@ +package field + +import ( + "gorm.io/gorm/clause" +) + +// newGenerics create new generic field type +func newGenerics[T any](e expr) genericsField[T] { + return genericsField[T]{e} +} + +// genericsField a generics field struct +// serving as a base field type, offers a suite of fundamental methods/functions for database operations." +type genericsField[T any] struct{ expr } + +// Eq judge equal +func (field genericsField[T]) Eq(value T) Expr { + return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} +} + +// Neq judge not equal +func (field genericsField[T]) Neq(value T) Expr { + return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} +} + +// In ... +func (field genericsField[T]) In(values ...T) Expr { + return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} +} + +// NotIn ... +func (field genericsField[T]) NotIn(values ...T) Expr { + return expr{e: clause.Not(field.In(values...).expression())} +} + +// Gt ... +func (field genericsField[T]) Gt(value T) Expr { + return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} +} + +// Gte ... +func (field genericsField[T]) Gte(value T) Expr { + return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} +} + +// Lt ... +func (field genericsField[T]) Lt(value T) Expr { + return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} +} + +// Lte ... +func (field genericsField[T]) Lte(value T) Expr { + return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} +} + +// Like ... +func (field genericsField[T]) Like(value string) Expr { + return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} +} + +// NotLike ... +func (field genericsField[T]) NotLike(value string) Expr { + return expr{e: clause.Not(field.Like(value).expression())} +} + +// Value ... +func (field genericsField[T]) Value(value T) AssignExpr { + return field.value(value) +} + +// Sum ... +func (field genericsField[T]) Sum() genericsField[T] { + return genericsField[T]{field.sum()} +} + +// IfNull ... +func (field genericsField[T]) IfNull(value T) Expr { + return field.ifNull(value) +} + +// Field ... +func (field genericsField[T]) Field(value []interface{}) Expr { + return field.field(value) +} + +func (field genericsField[T]) toSlice(values ...T) []interface{} { + slice := make([]interface{}, len(values)) + for i, v := range values { + slice[i] = v + } + return slice +} diff --git a/field/int.go b/field/int.go deleted file mode 100644 index 3ff2bf67..00000000 --- a/field/int.go +++ /dev/null @@ -1,1565 +0,0 @@ -package field - -import ( - "gorm.io/gorm/clause" -) - -// Int int type field -type Int Field - -// Eq equal to -func (field Int) Eq(value int) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field Int) Neq(value int) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field Int) Gt(value int) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte greater or equal to -func (field Int) Gte(value int) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field Int) Lt(value int) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field Int) Lte(value int) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// In ... -func (field Int) In(values ...int) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} -} - -// NotIn ... -func (field Int) NotIn(values ...int) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Between ... -func (field Int) Between(left int, right int) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field Int) NotBetween(left int, right int) Expr { - return Not(field.Between(left, right)) -} - -// Like ... -func (field Int) Like(value int) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// NotLike ... -func (field Int) NotLike(value int) Expr { - return expr{e: clause.Not(field.Like(value).expression())} -} - -// Add ... -func (field Int) Add(value int) Int { - return Int{field.add(value)} -} - -// Sub ... -func (field Int) Sub(value int) Int { - return Int{field.sub(value)} -} - -// Mul ... -func (field Int) Mul(value int) Int { - return Int{field.mul(value)} -} - -// Div ... -func (field Int) Div(value int) Int { - return Int{field.div(value)} -} - -// Mod ... -func (field Int) Mod(value int) Int { - return Int{field.mod(value)} -} - -// FloorDiv ... -func (field Int) FloorDiv(value int) Int { - return Int{field.floorDiv(value)} -} - -// RightShift ... -func (field Int) RightShift(value int) Int { - return Int{field.rightShift(value)} -} - -// LeftShift ... -func (field Int) LeftShift(value int) Int { - return Int{field.leftShift(value)} -} - -// BitXor ... -func (field Int) BitXor(value int) Int { - return Int{field.bitXor(value)} -} - -// BitAnd ... -func (field Int) BitAnd(value int) Int { - return Int{field.bitAnd(value)} -} - -// BitOr ... -func (field Int) BitOr(value int) Int { - return Int{field.bitOr(value)} -} - -// BitFlip ... -func (field Int) BitFlip() Int { - return Int{field.bitFlip()} -} - -// Value set value -func (field Int) Value(value int) AssignExpr { - return field.value(value) -} - -// Zero set zero value -func (field Int) Zero() AssignExpr { - return field.value(0) -} - -// Sum ... -func (field Int) Sum() Int { - return Int{field.sum()} -} - -// IfNull ... -func (field Int) IfNull(value int) Expr { - return field.ifNull(value) -} - -// Field ... -func (field Int) Field(values ...int) Int { - return Int{field.field(values)} -} - -func (field Int) toSlice(values ...int) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} - -// Int8 int8 type field -type Int8 Int - -// Eq equal to -func (field Int8) Eq(value int8) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field Int8) Neq(value int8) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field Int8) Gt(value int8) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte greater or equal to -func (field Int8) Gte(value int8) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field Int8) Lt(value int8) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field Int8) Lte(value int8) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// In ... -func (field Int8) In(values ...int8) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} -} - -// NotIn ... -func (field Int8) NotIn(values ...int8) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Between ... -func (field Int8) Between(left int8, right int8) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field Int8) NotBetween(left int8, right int8) Expr { - return Not(field.Between(left, right)) -} - -// Like ... -func (field Int8) Like(value int8) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// NotLike ... -func (field Int8) NotLike(value int8) Expr { - return expr{e: clause.Not(field.Like(value).expression())} -} - -// Add ... -func (field Int8) Add(value int8) Int8 { - return Int8{field.add(value)} -} - -// Sub ... -func (field Int8) Sub(value int8) Int8 { - return Int8{field.sub(value)} -} - -// Mul ... -func (field Int8) Mul(value int8) Int8 { - return Int8{field.mul(value)} -} - -// Div ... -func (field Int8) Div(value int8) Int8 { - return Int8{field.div(value)} -} - -// Mod ... -func (field Int8) Mod(value int8) Int8 { - return Int8{field.mod(value)} -} - -// FloorDiv ... -func (field Int8) FloorDiv(value int8) Int8 { - return Int8{field.floorDiv(value)} -} - -// RightShift ... -func (field Int8) RightShift(value int8) Int8 { - return Int8{field.rightShift(value)} -} - -// LeftShift ... -func (field Int8) LeftShift(value int8) Int8 { - return Int8{field.leftShift(value)} -} - -// BitXor ... -func (field Int8) BitXor(value int8) Int8 { - return Int8{field.bitXor(value)} -} - -// BitAnd ... -func (field Int8) BitAnd(value int8) Int8 { - return Int8{field.bitAnd(value)} -} - -// BitOr ... -func (field Int8) BitOr(value int8) Int8 { - return Int8{field.bitOr(value)} -} - -// BitFlip ... -func (field Int8) BitFlip() Int8 { - return Int8{field.bitFlip()} -} - -// Value set value -func (field Int8) Value(value int8) AssignExpr { - return field.value(value) -} - -// Zero set zero value -func (field Int8) Zero() AssignExpr { - return field.value(0) -} - -// Sum ... -func (field Int8) Sum() Int8 { - return Int8{field.sum()} -} - -// IfNull ... -func (field Int8) IfNull(value int8) Expr { - return field.ifNull(value) -} - -// Field ... -func (field Int8) Field(values ...int8) Int8 { - return Int8{field.field(values)} -} - -func (field Int8) toSlice(values ...int8) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} - -// Int16 int16 type field -type Int16 Int - -// Eq equal to -func (field Int16) Eq(value int16) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field Int16) Neq(value int16) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field Int16) Gt(value int16) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte greater or equal to -func (field Int16) Gte(value int16) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field Int16) Lt(value int16) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field Int16) Lte(value int16) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// In ... -func (field Int16) In(values ...int16) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} -} - -// NotIn ... -func (field Int16) NotIn(values ...int16) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Between ... -func (field Int16) Between(left int16, right int16) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field Int16) NotBetween(left int16, right int16) Expr { - return Not(field.Between(left, right)) -} - -// Like ... -func (field Int16) Like(value int16) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// NotLike ... -func (field Int16) NotLike(value int16) Expr { - return expr{e: clause.Not(field.Like(value).expression())} -} - -// Add ... -func (field Int16) Add(value int16) Int16 { - return Int16{field.add(value)} -} - -// Sub ... -func (field Int16) Sub(value int16) Int16 { - return Int16{field.sub(value)} -} - -// Mul ... -func (field Int16) Mul(value int16) Int16 { - return Int16{field.mul(value)} -} - -// Div ... -func (field Int16) Div(value int16) Int16 { - return Int16{field.div(value)} -} - -// Mod ... -func (field Int16) Mod(value int16) Int16 { - return Int16{field.mod(value)} -} - -// FloorDiv ... -func (field Int16) FloorDiv(value int16) Int16 { - return Int16{field.floorDiv(value)} -} - -// RightShift ... -func (field Int16) RightShift(value int16) Int16 { - return Int16{field.rightShift(value)} -} - -// LeftShift ... -func (field Int16) LeftShift(value int16) Int16 { - return Int16{field.leftShift(value)} -} - -// BitXor ... -func (field Int16) BitXor(value int16) Int16 { - return Int16{field.bitXor(value)} -} - -// BitAnd ... -func (field Int16) BitAnd(value int16) Int16 { - return Int16{field.bitAnd(value)} -} - -// BitOr ... -func (field Int16) BitOr(value int16) Int16 { - return Int16{field.bitOr(value)} -} - -// BitFlip ... -func (field Int16) BitFlip() Int16 { - return Int16{field.bitFlip()} -} - -// Value set value -func (field Int16) Value(value int16) AssignExpr { - return field.value(value) -} - -// Zero set zero value -func (field Int16) Zero() AssignExpr { - return field.value(0) -} - -// Sum ... -func (field Int16) Sum() Int16 { - return Int16{field.sum()} -} - -// IfNull ... -func (field Int16) IfNull(value int16) Expr { - return field.ifNull(value) -} - -// Field ... -func (field Int16) Field(values ...int16) Int16 { - return Int16{field.field(values)} -} - -func (field Int16) toSlice(values ...int16) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} - -// Int32 int32 type field -type Int32 Int - -// Eq equal to -func (field Int32) Eq(value int32) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field Int32) Neq(value int32) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field Int32) Gt(value int32) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte greater or equal to -func (field Int32) Gte(value int32) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field Int32) Lt(value int32) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field Int32) Lte(value int32) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// In ... -func (field Int32) In(values ...int32) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} -} - -// NotIn ... -func (field Int32) NotIn(values ...int32) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Between ... -func (field Int32) Between(left int32, right int32) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field Int32) NotBetween(left int32, right int32) Expr { - return Not(field.Between(left, right)) -} - -// Like ... -func (field Int32) Like(value int32) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// NotLike ... -func (field Int32) NotLike(value int32) Expr { - return expr{e: clause.Not(field.Like(value).expression())} -} - -// Add ... -func (field Int32) Add(value int32) Int32 { - return Int32{field.add(value)} -} - -// Sub ... -func (field Int32) Sub(value int32) Int32 { - return Int32{field.sub(value)} -} - -// Mul ... -func (field Int32) Mul(value int32) Int32 { - return Int32{field.mul(value)} -} - -// Div ... -func (field Int32) Div(value int32) Int32 { - return Int32{field.div(value)} -} - -// Mod ... -func (field Int32) Mod(value int32) Int32 { - return Int32{field.mod(value)} -} - -// FloorDiv ... -func (field Int32) FloorDiv(value int32) Int32 { - return Int32{field.floorDiv(value)} -} - -// RightShift ... -func (field Int32) RightShift(value int32) Int32 { - return Int32{field.rightShift(value)} -} - -// LeftShift ... -func (field Int32) LeftShift(value int32) Int32 { - return Int32{field.leftShift(value)} -} - -// BitXor ... -func (field Int32) BitXor(value int32) Int32 { - return Int32{field.bitXor(value)} -} - -// BitAnd ... -func (field Int32) BitAnd(value int32) Int32 { - return Int32{field.bitAnd(value)} -} - -// BitOr ... -func (field Int32) BitOr(value int32) Int32 { - return Int32{field.bitOr(value)} -} - -// BitFlip ... -func (field Int32) BitFlip() Int32 { - return Int32{field.bitFlip()} -} - -// Value set value -func (field Int32) Value(value int32) AssignExpr { - return field.value(value) -} - -// Zero set zero value -func (field Int32) Zero() AssignExpr { - return field.value(0) -} - -// Sum ... -func (field Int32) Sum() Int32 { - return Int32{field.sum()} -} - -// IfNull ... -func (field Int32) IfNull(value int32) Expr { - return field.ifNull(value) -} - -// Field ... -func (field Int32) Field(values ...int32) Int32 { - return Int32{field.field(values)} -} - -func (field Int32) toSlice(values ...int32) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} - -// Int64 int64 type field -type Int64 Int - -// Eq equal to -func (field Int64) Eq(value int64) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field Int64) Neq(value int64) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field Int64) Gt(value int64) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte greater or equal to -func (field Int64) Gte(value int64) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field Int64) Lt(value int64) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field Int64) Lte(value int64) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// In ... -func (field Int64) In(values ...int64) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} -} - -// NotIn ... -func (field Int64) NotIn(values ...int64) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Between ... -func (field Int64) Between(left int64, right int64) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field Int64) NotBetween(left int64, right int64) Expr { - return Not(field.Between(left, right)) -} - -// Like ... -func (field Int64) Like(value int64) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// NotLike ... -func (field Int64) NotLike(value int64) Expr { - return expr{e: clause.Not(field.Like(value).expression())} -} - -// Add ... -func (field Int64) Add(value int64) Int64 { - return Int64{field.add(value)} -} - -// Sub ... -func (field Int64) Sub(value int64) Int64 { - return Int64{field.sub(value)} -} - -// Mul ... -func (field Int64) Mul(value int64) Int64 { - return Int64{field.mul(value)} -} - -// Div ... -func (field Int64) Div(value int64) Int64 { - return Int64{field.div(value)} -} - -// Mod ... -func (field Int64) Mod(value int64) Int64 { - return Int64{field.mod(value)} -} - -// FloorDiv ... -func (field Int64) FloorDiv(value int64) Int64 { - return Int64{field.floorDiv(value)} -} - -// RightShift ... -func (field Int64) RightShift(value int64) Int64 { - return Int64{field.rightShift(value)} -} - -// LeftShift ... -func (field Int64) LeftShift(value int64) Int64 { - return Int64{field.leftShift(value)} -} - -// BitXor ... -func (field Int64) BitXor(value int64) Int64 { - return Int64{field.bitXor(value)} -} - -// BitAnd ... -func (field Int64) BitAnd(value int64) Int64 { - return Int64{field.bitAnd(value)} -} - -// BitOr ... -func (field Int64) BitOr(value int64) Int64 { - return Int64{field.bitOr(value)} -} - -// BitFlip ... -func (field Int64) BitFlip() Int64 { - return Int64{field.bitFlip()} -} - -// Value set value -func (field Int64) Value(value int64) AssignExpr { - return field.value(value) -} - -// Zero set zero value -func (field Int64) Zero() AssignExpr { - return field.value(0) -} - -// Sum ... -func (field Int64) Sum() Int64 { - return Int64{field.sum()} -} - -// IfNull ... -func (field Int64) IfNull(value int64) Expr { - return field.ifNull(value) -} - -// Field ... -func (field Int64) Field(values ...int64) Int64 { - return Int64{field.field(values)} -} - -func (field Int64) toSlice(values ...int64) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} - -// Uint uint type field -type Uint Int - -// Eq equal to -func (field Uint) Eq(value uint) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field Uint) Neq(value uint) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field Uint) Gt(value uint) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte greater or equal to -func (field Uint) Gte(value uint) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field Uint) Lt(value uint) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field Uint) Lte(value uint) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// In ... -func (field Uint) In(values ...uint) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} -} - -// NotIn ... -func (field Uint) NotIn(values ...uint) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Between ... -func (field Uint) Between(left uint, right uint) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field Uint) NotBetween(left uint, right uint) Expr { - return Not(field.Between(left, right)) -} - -// Like ... -func (field Uint) Like(value uint) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// NotLike ... -func (field Uint) NotLike(value uint) Expr { - return expr{e: clause.Not(field.Like(value).expression())} -} - -// Add ... -func (field Uint) Add(value uint) Uint { - return Uint{field.add(value)} -} - -// Sub ... -func (field Uint) Sub(value uint) Uint { - return Uint{field.sub(value)} -} - -// Mul ... -func (field Uint) Mul(value uint) Uint { - return Uint{field.mul(value)} -} - -// Div ... -func (field Uint) Div(value uint) Uint { - return Uint{field.mul(value)} -} - -// Mod ... -func (field Uint) Mod(value uint) Uint { - return Uint{field.mod(value)} -} - -// FloorDiv ... -func (field Uint) FloorDiv(value uint) Uint { - return Uint{field.floorDiv(value)} -} - -// RightShift ... -func (field Uint) RightShift(value uint) Uint { - return Uint{field.rightShift(value)} -} - -// LeftShift ... -func (field Uint) LeftShift(value uint) Uint { - return Uint{field.leftShift(value)} -} - -// BitXor ... -func (field Uint) BitXor(value uint) Uint { - return Uint{field.bitXor(value)} -} - -// BitAnd ... -func (field Uint) BitAnd(value uint) Uint { - return Uint{field.bitAnd(value)} -} - -// BitOr ... -func (field Uint) BitOr(value uint) Uint { - return Uint{field.bitOr(value)} -} - -// BitFlip ... -func (field Uint) BitFlip() Uint { - return Uint{field.bitFlip()} -} - -// Value set value -func (field Uint) Value(value uint) AssignExpr { - return field.value(value) -} - -// Zero set zero value -func (field Uint) Zero() AssignExpr { - return field.value(0) -} - -// Sum ... -func (field Uint) Sum() Uint { - return Uint{field.sum()} -} - -// IfNull ... -func (field Uint) IfNull(value uint) Expr { - return field.ifNull(value) -} - -// Field ... -func (field Uint) Field(values ...uint) Uint { - return Uint{field.field(values)} -} - -func (field Uint) toSlice(values ...uint) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} - -// Uint8 uint8 type field -type Uint8 Int - -// Eq equal to -func (field Uint8) Eq(value uint8) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field Uint8) Neq(value uint8) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field Uint8) Gt(value uint8) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte greater or equal to -func (field Uint8) Gte(value uint8) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field Uint8) Lt(value uint8) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field Uint8) Lte(value uint8) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// In ... -func (field Uint8) In(values ...uint8) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} -} - -// NotIn ... -func (field Uint8) NotIn(values ...uint8) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Between ... -func (field Uint8) Between(left uint8, right uint8) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field Uint8) NotBetween(left uint8, right uint8) Expr { - return Not(field.Between(left, right)) -} - -// Like ... -func (field Uint8) Like(value uint8) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// NotLike ... -func (field Uint8) NotLike(value uint8) Expr { - return expr{e: clause.Not(field.Like(value).expression())} -} - -// Add ... -func (field Uint8) Add(value uint8) Uint8 { - return Uint8{field.add(value)} -} - -// Sub ... -func (field Uint8) Sub(value uint8) Uint8 { - return Uint8{field.sub(value)} -} - -// Mul ... -func (field Uint8) Mul(value uint8) Uint8 { - return Uint8{field.mul(value)} -} - -// Div ... -func (field Uint8) Div(value uint8) Uint8 { - return Uint8{field.mul(value)} -} - -// Mod ... -func (field Uint8) Mod(value uint8) Uint8 { - return Uint8{field.mod(value)} -} - -// FloorDiv ... -func (field Uint8) FloorDiv(value uint8) Uint8 { - return Uint8{field.floorDiv(value)} -} - -// RightShift ... -func (field Uint8) RightShift(value uint8) Uint8 { - return Uint8{field.rightShift(value)} -} - -// LeftShift ... -func (field Uint8) LeftShift(value uint8) Uint8 { - return Uint8{field.leftShift(value)} -} - -// BitXor ... -func (field Uint8) BitXor(value uint8) Uint8 { - return Uint8{field.bitXor(value)} -} - -// BitAnd ... -func (field Uint8) BitAnd(value uint8) Uint8 { - return Uint8{field.bitAnd(value)} -} - -// BitOr ... -func (field Uint8) BitOr(value uint8) Uint8 { - return Uint8{field.bitOr(value)} -} - -// BitFlip ... -func (field Uint8) BitFlip() Uint8 { - return Uint8{field.bitFlip()} -} - -// Value set value -func (field Uint8) Value(value uint8) AssignExpr { - return field.value(value) -} - -// Zero set zero value -func (field Uint8) Zero() AssignExpr { - return field.value(0) -} - -// Sum ... -func (field Uint8) Sum() Uint8 { - return Uint8{field.sum()} -} - -// IfNull ... -func (field Uint8) IfNull(value uint8) Expr { - return field.ifNull(value) -} - -// Field ... -func (field Uint8) Field(values ...uint8) Uint8 { - return Uint8{field.field(values)} -} - -func (field Uint8) toSlice(values ...uint8) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} - -// Uint16 uint16 type field -type Uint16 Int - -// Eq equal to -func (field Uint16) Eq(value uint16) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field Uint16) Neq(value uint16) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field Uint16) Gt(value uint16) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte greater or equal to -func (field Uint16) Gte(value uint16) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field Uint16) Lt(value uint16) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field Uint16) Lte(value uint16) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// In ... -func (field Uint16) In(values ...uint16) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} -} - -// NotIn ... -func (field Uint16) NotIn(values ...uint16) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Between ... -func (field Uint16) Between(left uint16, right uint16) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field Uint16) NotBetween(left uint16, right uint16) Expr { - return Not(field.Between(left, right)) -} - -// Like ... -func (field Uint16) Like(value uint16) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// NotLike ... -func (field Uint16) NotLike(value uint16) Expr { - return expr{e: clause.Not(field.Like(value).expression())} -} - -// Add ... -func (field Uint16) Add(value uint16) Uint16 { - return Uint16{field.add(value)} -} - -// Sub ... -func (field Uint16) Sub(value uint16) Uint16 { - return Uint16{field.sub(value)} -} - -// Mul ... -func (field Uint16) Mul(value uint16) Uint16 { - return Uint16{field.mul(value)} -} - -// Div ... -func (field Uint16) Div(value uint16) Uint16 { - return Uint16{field.mul(value)} -} - -// Mod ... -func (field Uint16) Mod(value uint16) Uint16 { - return Uint16{field.mod(value)} -} - -// FloorDiv ... -func (field Uint16) FloorDiv(value uint16) Uint16 { - return Uint16{field.floorDiv(value)} -} - -// RightShift ... -func (field Uint16) RightShift(value uint16) Uint16 { - return Uint16{field.rightShift(value)} -} - -// LeftShift ... -func (field Uint16) LeftShift(value uint16) Uint16 { - return Uint16{field.leftShift(value)} -} - -// BitXor ... -func (field Uint16) BitXor(value uint16) Uint16 { - return Uint16{field.bitXor(value)} -} - -// BitAnd ... -func (field Uint16) BitAnd(value uint16) Uint16 { - return Uint16{field.bitAnd(value)} -} - -// BitOr ... -func (field Uint16) BitOr(value uint16) Uint16 { - return Uint16{field.bitOr(value)} -} - -// BitFlip ... -func (field Uint16) BitFlip() Uint16 { - return Uint16{field.bitFlip()} -} - -// Value set value -func (field Uint16) Value(value uint16) AssignExpr { - return field.value(value) -} - -// Zero set zero value -func (field Uint16) Zero() AssignExpr { - return field.value(0) -} - -// Sum ... -func (field Uint16) Sum() Uint16 { - return Uint16{field.sum()} -} - -// IfNull ... -func (field Uint16) IfNull(value uint16) Expr { - return field.ifNull(value) -} - -// Field ... -func (field Uint16) Field(values ...uint16) Uint16 { - return Uint16{field.field(values)} -} - -func (field Uint16) toSlice(values ...uint16) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} - -// Uint32 uint32 type field -type Uint32 Int - -// Eq equal to -func (field Uint32) Eq(value uint32) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field Uint32) Neq(value uint32) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field Uint32) Gt(value uint32) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte greater or equal to -func (field Uint32) Gte(value uint32) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field Uint32) Lt(value uint32) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field Uint32) Lte(value uint32) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// In ... -func (field Uint32) In(values ...uint32) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} -} - -// NotIn ... -func (field Uint32) NotIn(values ...uint32) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Between ... -func (field Uint32) Between(left uint32, right uint32) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field Uint32) NotBetween(left uint32, right uint32) Expr { - return Not(field.Between(left, right)) -} - -// Like ... -func (field Uint32) Like(value uint32) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// NotLike ... -func (field Uint32) NotLike(value uint32) Expr { - return expr{e: clause.Not(field.Like(value).expression())} -} - -// Add ... -func (field Uint32) Add(value uint32) Uint32 { - return Uint32{field.add(value)} -} - -// Sub ... -func (field Uint32) Sub(value uint32) Uint32 { - return Uint32{field.sub(value)} -} - -// Mul ... -func (field Uint32) Mul(value uint32) Uint32 { - return Uint32{field.mul(value)} -} - -// Div ... -func (field Uint32) Div(value uint32) Uint32 { - return Uint32{field.mul(value)} -} - -// Mod ... -func (field Uint32) Mod(value uint32) Uint32 { - return Uint32{field.mod(value)} -} - -// FloorDiv ... -func (field Uint32) FloorDiv(value uint32) Uint32 { - return Uint32{field.floorDiv(value)} -} - -// RightShift ... -func (field Uint32) RightShift(value uint32) Uint32 { - return Uint32{field.rightShift(value)} -} - -// LeftShift ... -func (field Uint32) LeftShift(value uint32) Uint32 { - return Uint32{field.leftShift(value)} -} - -// BitXor ... -func (field Uint32) BitXor(value uint32) Uint32 { - return Uint32{field.bitXor(value)} -} - -// BitAnd ... -func (field Uint32) BitAnd(value uint32) Uint32 { - return Uint32{field.bitAnd(value)} -} - -// BitOr ... -func (field Uint32) BitOr(value uint32) Uint32 { - return Uint32{field.bitOr(value)} -} - -// BitFlip ... -func (field Uint32) BitFlip() Uint32 { - return Uint32{field.bitFlip()} -} - -// Value set value -func (field Uint32) Value(value uint32) AssignExpr { - return field.value(value) -} - -// Zero set zero value -func (field Uint32) Zero() AssignExpr { - return field.value(0) -} - -// Sum ... -func (field Uint32) Sum() Uint32 { - return Uint32{field.sum()} -} - -// IfNull ... -func (field Uint32) IfNull(value uint32) Expr { - return field.ifNull(value) -} - -// Field ... -func (field Uint32) Field(values ...uint32) Uint32 { - return Uint32{field.field(values)} -} - -func (field Uint32) toSlice(values ...uint32) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} - -// Uint64 uint64 type field -type Uint64 Int - -// Eq equal to -func (field Uint64) Eq(value uint64) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field Uint64) Neq(value uint64) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field Uint64) Gt(value uint64) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte greater or equal to -func (field Uint64) Gte(value uint64) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field Uint64) Lt(value uint64) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field Uint64) Lte(value uint64) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// In ... -func (field Uint64) In(values ...uint64) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} -} - -// NotIn ... -func (field Uint64) NotIn(values ...uint64) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Between ... -func (field Uint64) Between(left uint64, right uint64) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field Uint64) NotBetween(left uint64, right uint64) Expr { - return Not(field.Between(left, right)) -} - -// Like ... -func (field Uint64) Like(value uint64) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// NotLike ... -func (field Uint64) NotLike(value uint64) Expr { - return expr{e: clause.Not(field.Like(value).expression())} -} - -// Add ... -func (field Uint64) Add(value uint64) Uint64 { - return Uint64{field.add(value)} -} - -// Sub ... -func (field Uint64) Sub(value uint64) Uint64 { - return Uint64{field.sub(value)} -} - -// Mul ... -func (field Uint64) Mul(value uint64) Uint64 { - return Uint64{field.mul(value)} -} - -// Div ... -func (field Uint64) Div(value uint64) Uint64 { - return Uint64{field.mul(value)} -} - -// Mod ... -func (field Uint64) Mod(value uint64) Uint64 { - return Uint64{field.mod(value)} -} - -// FloorDiv ... -func (field Uint64) FloorDiv(value uint64) Uint64 { - return Uint64{field.floorDiv(value)} -} - -// RightShift ... -func (field Uint64) RightShift(value uint64) Uint64 { - return Uint64{field.rightShift(value)} -} - -// LeftShift ... -func (field Uint64) LeftShift(value uint64) Uint64 { - return Uint64{field.leftShift(value)} -} - -// BitXor ... -func (field Uint64) BitXor(value uint64) Uint64 { - return Uint64{field.bitXor(value)} -} - -// BitAnd ... -func (field Uint64) BitAnd(value uint64) Uint64 { - return Uint64{field.bitAnd(value)} -} - -// BitOr ... -func (field Uint64) BitOr(value uint64) Uint64 { - return Uint64{field.bitOr(value)} -} - -// BitFlip ... -func (field Uint64) BitFlip() Uint64 { - return Uint64{field.bitFlip()} -} - -// Value set value -func (field Uint64) Value(value uint64) AssignExpr { - return field.value(value) -} - -// Zero set zero value -func (field Uint64) Zero() AssignExpr { - return field.value(0) -} - -// Sum ... -func (field Uint64) Sum() Uint64 { - return Uint64{field.sum()} -} - -// IfNull ... -func (field Uint64) IfNull(value uint64) Expr { - return field.ifNull(value) -} - -// Field ... -func (field Uint64) Field(values ...uint64) Uint64 { - return Uint64{field.field(values)} -} - -func (field Uint64) toSlice(values ...uint64) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} diff --git a/field/number.go b/field/number.go new file mode 100644 index 00000000..83d87d01 --- /dev/null +++ b/field/number.go @@ -0,0 +1,144 @@ +package field + +import ( + "golang.org/x/exp/constraints" + "gorm.io/gorm/clause" +) + +// Int type field +type Int = Number[int] + +// Int8 type field +type Int8 = Number[int8] + +// Int16 type field +type Int16 = Number[int16] + +// Int32 type field +type Int32 = Number[int32] + +// Int64 type field +type Int64 = Number[int64] + +// Uint type field +type Uint = Number[uint] + +// Uint8 type field +type Uint8 = Number[uint8] + +// Uint16 type field +type Uint16 = Number[uint16] + +// Uint32 type field +type Uint32 = Number[uint32] + +// Uint64 type field +type Uint64 = Number[uint64] + +// Float32 type field +type Float32 = Number[float32] + +// Float64 type field +type Float64 = Number[float64] + +// ======================== number ======================= + +// newNumber build number type field +func newNumber[T constraints.Integer | constraints.Float](e expr) Number[T] { + return Number[T]{genericsField: newGenerics[T](e)} +} + +// Number int type field +type Number[T constraints.Integer | constraints.Float] struct { + genericsField[T] +} + +// NotIn ... +func (field Number[T]) NotIn(values ...T) Expr { + return expr{e: clause.Not(field.In(values...).expression())} +} + +// Between ... +func (field Number[T]) Between(left T, right T) Expr { + return field.between([]interface{}{left, right}) +} + +// NotBetween ... +func (field Number[T]) NotBetween(left T, right T) Expr { + return Not(field.Between(left, right)) +} + +// Add ... +func (field Number[T]) Add(value T) Number[T] { + return newNumber[T](field.add(value)) +} + +// Sub ... +func (field Number[T]) Sub(value T) Number[T] { + return newNumber[T](field.sub(value)) +} + +// Mul ... +func (field Number[T]) Mul(value T) Number[T] { + return newNumber[T](field.mul(value)) +} + +// Div ... +func (field Number[T]) Div(value T) Number[T] { + return newNumber[T](field.div(value)) +} + +// Mod ... +func (field Number[T]) Mod(value T) Number[T] { + return newNumber[T](field.mod(value)) +} + +// FloorDiv ... +func (field Number[T]) FloorDiv(value T) Number[T] { + return newNumber[T](field.floorDiv(value)) +} + +// RightShift ... +func (field Number[T]) RightShift(value T) Number[T] { + return newNumber[T](field.rightShift(value)) +} + +// LeftShift ... +func (field Number[T]) LeftShift(value T) Number[T] { + return newNumber[T](field.leftShift(value)) +} + +// BitXor ... +func (field Number[T]) BitXor(value T) Number[T] { + return newNumber[T](field.bitXor(value)) +} + +// BitAnd ... +func (field Number[T]) BitAnd(value T) Number[T] { + return newNumber[T](field.bitAnd(value)) +} + +// BitOr ... +func (field Number[T]) BitOr(value T) Number[T] { + return newNumber[T](field.bitOr(value)) +} + +// BitFlip ... +func (field Number[T]) BitFlip() Number[T] { + return newNumber[T](field.bitFlip()) +} + +// Floor ... +func (field Number[T]) Floor() Number[T] { + return newNumber[T](field.floor()) +} + +// Zero set zero value +func (field Number[T]) Zero() AssignExpr { + return field.value(0) +} + +// Field ... +func (field Number[T]) Field(values ...T) Number[T] { + return newNumber[T](field.field(values)) +} diff --git a/field/serializer.go b/field/serializer.go index 8727bad8..64cb1ddd 100644 --- a/field/serializer.go +++ b/field/serializer.go @@ -2,20 +2,20 @@ package field import ( "context" - "gorm.io/gorm/clause" - "gorm.io/gorm/schema" "reflect" "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" ) -type ValuerType struct { +type valuerType struct { Column string Value schema.SerializerValuerInterface FucName string } -func (v ValuerType) GormValue(ctx context.Context, db *gorm.DB) (expr clause.Expr) { +func (v valuerType) GormValue(ctx context.Context, db *gorm.DB) (expr clause.Expr) { stmt := db.Statement.Schema field := stmt.LookUpField(v.Column) newValue, err := v.Value.Value(context.WithValue(ctx, "func_name", v.FucName), field, reflect.ValueOf(v.Value), v.Value) @@ -23,68 +23,68 @@ func (v ValuerType) GormValue(ctx context.Context, db *gorm.DB) (expr clause.Exp return clause.Expr{SQL: "?", Vars: []interface{}{newValue}} } -// Field2 a standard field struct +// Serializer a standard field struct type Serializer struct{ expr } // Eq judge equal -func (field Serializer) Eq(value schema.SerializerValuerInterface) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: ValuerType{Column: field.ColumnName().String(), Value: value, FucName: "Eq"}}} +func (s Serializer) Eq(value schema.SerializerValuerInterface) Expr { + return expr{e: clause.Eq{Column: s.RawExpr(), Value: valuerType{Column: s.ColumnName().String(), Value: value, FucName: "Eq"}}} } // Neq judge not equal -func (field Serializer) Neq(value schema.SerializerValuerInterface) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: ValuerType{Column: field.ColumnName().String(), Value: value, FucName: "Neq"}}} +func (s Serializer) Neq(value schema.SerializerValuerInterface) Expr { + return expr{e: clause.Neq{Column: s.RawExpr(), Value: valuerType{Column: s.ColumnName().String(), Value: value, FucName: "Neq"}}} } // In ... -func (field Serializer) In(values ...schema.SerializerValuerInterface) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} +func (s Serializer) In(values ...schema.SerializerValuerInterface) Expr { + return expr{e: clause.IN{Column: s.RawExpr(), Values: s.toSlice(values...)}} } // Gt ... -func (field Serializer) Gt(value schema.SerializerValuerInterface) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: ValuerType{Column: field.ColumnName().String(), Value: value, FucName: "Gt"}}} +func (s Serializer) Gt(value schema.SerializerValuerInterface) Expr { + return expr{e: clause.Gt{Column: s.RawExpr(), Value: valuerType{Column: s.ColumnName().String(), Value: value, FucName: "Gt"}}} } // Gte ... -func (field Serializer) Gte(value schema.SerializerValuerInterface) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: ValuerType{Column: field.ColumnName().String(), Value: value, FucName: "Gte"}}} +func (s Serializer) Gte(value schema.SerializerValuerInterface) Expr { + return expr{e: clause.Gte{Column: s.RawExpr(), Value: valuerType{Column: s.ColumnName().String(), Value: value, FucName: "Gte"}}} } // Lt ... -func (field Serializer) Lt(value schema.SerializerValuerInterface) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: ValuerType{Column: field.ColumnName().String(), Value: value, FucName: "Lt"}}} +func (s Serializer) Lt(value schema.SerializerValuerInterface) Expr { + return expr{e: clause.Lt{Column: s.RawExpr(), Value: valuerType{Column: s.ColumnName().String(), Value: value, FucName: "Lt"}}} } // Lte ... -func (field Serializer) Lte(value schema.SerializerValuerInterface) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: ValuerType{Column: field.ColumnName().String(), Value: value, FucName: "Lte"}}} +func (s Serializer) Lte(value schema.SerializerValuerInterface) Expr { + return expr{e: clause.Lte{Column: s.RawExpr(), Value: valuerType{Column: s.ColumnName().String(), Value: value, FucName: "Lte"}}} } // Like ... -func (field Serializer) Like(value schema.SerializerValuerInterface) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: ValuerType{Column: field.ColumnName().String(), Value: value, FucName: "Like"}}} +func (s Serializer) Like(value schema.SerializerValuerInterface) Expr { + return expr{e: clause.Like{Column: s.RawExpr(), Value: valuerType{Column: s.ColumnName().String(), Value: value, FucName: "Like"}}} } // Value ... -func (field Serializer) Value(value schema.SerializerValuerInterface) AssignExpr { - return field.value(ValuerType{Column: field.ColumnName().String(), Value: value, FucName: "Value"}) +func (s Serializer) Value(value schema.SerializerValuerInterface) AssignExpr { + return s.value(valuerType{Column: s.ColumnName().String(), Value: value, FucName: "Value"}) } // Sum ... -func (field Serializer) Sum() Field { - return Field{field.sum()} +func (s Serializer) Sum() Number[float64] { + return newNumber[float64](s.sum()) } // IfNull ... -func (field Serializer) IfNull(value schema.SerializerValuerInterface) Expr { - return field.ifNull(ValuerType{Column: field.ColumnName().String(), Value: value, FucName: "IfNull"}) +func (s Serializer) IfNull(value schema.SerializerValuerInterface) Expr { + return s.ifNull(valuerType{Column: s.ColumnName().String(), Value: value, FucName: "IfNull"}) } -func (field Serializer) toSlice(values ...schema.SerializerValuerInterface) []interface{} { +func (s Serializer) toSlice(values ...schema.SerializerValuerInterface) []interface{} { slice := make([]interface{}, len(values)) for i, v := range values { - slice[i] = ValuerType{Column: field.ColumnName().String(), Value: v, FucName: "In"} + slice[i] = valuerType{Column: s.ColumnName().String(), Value: v, FucName: "In"} } return slice } diff --git a/field/string.go b/field/string.go index c587073e..dff04240 100644 --- a/field/string.go +++ b/field/string.go @@ -7,315 +7,137 @@ import ( ) // String string type field -type String Field +type String = Chars[string] -// Eq equal to -func (field String) Eq(value string) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field String) Neq(value string) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field String) Gt(value string) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} +// Bytes []byte type field +type Bytes = Chars[[]byte] -// Gte greater or equal to -func (field String) Gte(value string) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} +// ======================== string ======================= -// Lt less than -func (field String) Lt(value string) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} +// newChars create field for chars +func newChars[T ~string | ~[]byte](e expr) Chars[T] { + return Chars[T]{genericsField: newGenerics[T](e)} } -// Lte less or equal to -func (field String) Lte(value string) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} +// Chars string type field +type Chars[T ~string | ~[]byte] struct { + genericsField[T] } // Between ... -func (field String) Between(left string, right string) Expr { +func (field Chars[T]) Between(left T, right T) Expr { return field.between([]interface{}{left, right}) } // NotBetween ... -func (field String) NotBetween(left string, right string) Expr { +func (field Chars[T]) NotBetween(left T, right T) Expr { return Not(field.Between(left, right)) } -// In ... -func (field String) In(values ...string) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values)}} -} - // NotIn ... -func (field String) NotIn(values ...string) Expr { +func (field Chars[T]) NotIn(values ...T) Expr { return expr{e: clause.Not(field.In(values...).expression())} } -// Like ... -func (field String) Like(value string) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// NotLike ... -func (field String) NotLike(value string) Expr { - return expr{e: clause.Not(field.Like(value).expression())} -} - // Regexp ... -func (field String) Regexp(value string) Expr { +func (field Chars[T]) Regexp(value string) Expr { return field.regexp(value) } -// NotRegxp ... -func (field String) NotRegxp(value string) Expr { +// NotRegexp ... +func (field Chars[T]) NotRegexp(value string) Expr { return expr{e: clause.Not(field.Regexp(value).expression())} } -// Value ... -func (field String) Value(value string) AssignExpr { - return field.value(value) -} - // Zero ... -func (field String) Zero() AssignExpr { +func (field Chars[T]) Zero() AssignExpr { return field.value("") } -// IfNull ... -func (field String) IfNull(value string) Expr { - return field.ifNull(value) -} - // FindInSet equal to FIND_IN_SET(field_name, input_string_list) -func (field String) FindInSet(targetList string) Expr { +func (field Chars[T]) FindInSet(targetList string) Expr { return expr{e: clause.Expr{SQL: "FIND_IN_SET(?,?)", Vars: []interface{}{field.RawExpr(), targetList}}} } // FindInSetWith equal to FIND_IN_SET(input_string, field_name) -func (field String) FindInSetWith(target string) Expr { +func (field Chars[T]) FindInSetWith(target string) Expr { return expr{e: clause.Expr{SQL: "FIND_IN_SET(?,?)", Vars: []interface{}{target, field.RawExpr()}}} } // Replace ... -func (field String) Replace(from, to string) String { - return String{expr{e: clause.Expr{SQL: "REPLACE(?,?,?)", Vars: []interface{}{field.RawExpr(), from, to}}}} +func (field Chars[T]) Replace(from, to string) Chars[T] { + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{SQL: "REPLACE(?,?,?)", Vars: []interface{}{field.RawExpr(), from, to}}}}} } // Concat ... -func (field String) Concat(before, after string) String { +func (field Chars[T]) Concat(before, after string) Chars[T] { switch { case before != "" && after != "": - return String{expr{e: clause.Expr{SQL: "CONCAT(?,?,?)", Vars: []interface{}{before, field.RawExpr(), after}}}} + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{SQL: "CONCAT(?,?,?)", Vars: []interface{}{before, field.RawExpr(), after}}}}} case before != "": - return String{expr{e: clause.Expr{SQL: "CONCAT(?,?)", Vars: []interface{}{before, field.RawExpr()}}}} + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{SQL: "CONCAT(?,?)", Vars: []interface{}{before, field.RawExpr()}}}}} case after != "": - return String{expr{e: clause.Expr{SQL: "CONCAT(?,?)", Vars: []interface{}{field.RawExpr(), after}}}} + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{SQL: "CONCAT(?,?)", Vars: []interface{}{field.RawExpr(), after}}}}} default: return field } } -// Lower converts a string to lower-case. -func (field String) Lower() String { - return String{expr{e: clause.Expr{SQL: "LOWER(?)", Vars: []interface{}{field.RawExpr()}}}} -} - -// Upper converts a string to upper-case. -func (field String) Upper() String { - return String{expr{e: clause.Expr{SQL: "UPPER(?)", Vars: []interface{}{field.RawExpr()}}}} -} - -// Field ... -func (field String) Field(values ...string) String { - return String{field.field(values)} -} - -// SubstringIndex SUBSTRING_INDEX -// https://dev.mysql.com/doc/refman/8.0/en/functions.html#function_substring-index -func (field String) SubstringIndex(delim string, count int) String { - return String{expr{e: clause.Expr{ - SQL: fmt.Sprintf("SUBSTRING_INDEX(?,%q,%d)", delim, count), - Vars: []interface{}{field.RawExpr()}, - }}} -} - // Substring https://dev.mysql.com/doc/refman/8.4/en/string-functions.html#function_substring -func (field String) Substring(params ...int) String { +func (field Chars[T]) Substring(params ...int) Chars[T] { if len(params) == 0 { return field } if len(params) == 1 { - return String{expr{e: clause.Expr{ + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{ SQL: fmt.Sprintf("SUBSTRING(?,%d)", params[0]), Vars: []interface{}{field.RawExpr()}, - }}} + }}}} } - return String{expr{e: clause.Expr{ + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{ SQL: fmt.Sprintf("SUBSTRING(?,%d,%d)", params[0], params[1]), Vars: []interface{}{field.RawExpr()}, - }}} + }}}} } -// Substr SUBSTR is a synonym for SUBSTRING +// Substr SUBSTR is a synonym for SUBSTRING // https://dev.mysql.com/doc/refman/8.4/en/string-functions.html#function_substring -func (field String) Substr(params ...int) String { +func (field Chars[T]) Substr(params ...int) Chars[T] { if len(params) == 0 { return field } if len(params) == 1 { - return String{expr{e: clause.Expr{ + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{ SQL: fmt.Sprintf("SUBSTR(?,%d)", params[0]), Vars: []interface{}{field.RawExpr()}, - }}} + }}}} } - return String{expr{e: clause.Expr{ + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{ SQL: fmt.Sprintf("SUBSTR(?,%d,%d)", params[0], params[1]), Vars: []interface{}{field.RawExpr()}, - }}} + }}}} } -func (field String) toSlice(values []string) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} - -// Bytes []byte type field -type Bytes String - -// Eq equal to -func (field Bytes) Eq(value []byte) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field Bytes) Neq(value []byte) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field Bytes) Gt(value []byte) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte greater or equal to -func (field Bytes) Gte(value []byte) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field Bytes) Lt(value []byte) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field Bytes) Lte(value []byte) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// Between ... -func (field Bytes) Between(left []byte, right []byte) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field Bytes) NotBetween(left []byte, right []byte) Expr { - return Not(field.Between(left, right)) -} - -// In ... -func (field Bytes) In(values ...[]byte) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values)}} -} - -// NotIn ... -func (field Bytes) NotIn(values ...[]byte) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Like ... -func (field Bytes) Like(value string) Expr { - return expr{e: clause.Like{Column: field.RawExpr(), Value: value}} -} - -// NotLike ... -func (field Bytes) NotLike(value string) Expr { - return expr{e: clause.Not(field.Like(value).expression())} -} - -// Regexp ... -func (field Bytes) Regexp(value string) Expr { - return field.regexp(value) -} - -// NotRegxp ... -func (field Bytes) NotRegxp(value string) Expr { - return Not(field.Regexp(value)) -} - -// Value ... -func (field Bytes) Value(value []byte) AssignExpr { - return field.value(value) -} - -// Zero ... -func (field Bytes) Zero() AssignExpr { - return field.value([]byte{}) -} - -// IfNull ... -func (field Bytes) IfNull(value []byte) Expr { - return field.ifNull(value) -} - -// FindInSet FIND_IN_SET(field_name, input_string_list) -func (field Bytes) FindInSet(targetList string) Expr { - return expr{e: clause.Expr{SQL: "FIND_IN_SET(?,?)", Vars: []interface{}{field.RawExpr(), targetList}}} +// SubstringIndex SUBSTRING_INDEX +// https://dev.mysql.com/doc/refman/8.0/en/functions.html#function_substring-index +func (field Chars[T]) SubstringIndex(delim string, count int) Chars[T] { + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{ + SQL: fmt.Sprintf("SUBSTRING_INDEX(?,%q,%d)", delim, count), + Vars: []interface{}{field.RawExpr()}, + }}}} } -// FindInSetWith FIND_IN_SET(input_string, field_name) -func (field Bytes) FindInSetWith(target string) Expr { - return expr{e: clause.Expr{SQL: "FIND_IN_SET(?,?)", Vars: []interface{}{target, field.RawExpr()}}} +// Field ... +func (field Chars[T]) Field(values ...T) Chars[T] { + return newChars[T](field.field(values)) } // Lower converts a string to lower-case. -func (field Bytes) Lower() String { - return String{expr{e: clause.Expr{SQL: "LOWER(?)", Vars: []interface{}{field.RawExpr()}}}} +func (field Chars[T]) Lower() Chars[T] { + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{SQL: "LOWER(?)", Vars: []interface{}{field.RawExpr()}}}}} } // Upper converts a string to upper-case. -func (field Bytes) Upper() String { - return String{expr{e: clause.Expr{SQL: "UPPER(?)", Vars: []interface{}{field.RawExpr()}}}} -} - -// Field ... -func (field Bytes) Field(values ...[]byte) Bytes { - return Bytes{field.field(values)} -} - -// SubstringIndex SUBSTRING_INDEX -// https://dev.mysql.com/doc/refman/8.0/en/functions.html#function_substring-index -func (field Bytes) SubstringIndex(delim string, count int) Bytes { - return Bytes{expr{e: clause.Expr{ - SQL: fmt.Sprintf("SUBSTRING_INDEX(?,%q,%d)", delim, count), - Vars: []interface{}{field.RawExpr()}, - }}} -} - -func (field Bytes) toSlice(values [][]byte) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice +func (field Chars[T]) Upper() Chars[T] { + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{SQL: "UPPER(?)", Vars: []interface{}{field.RawExpr()}}}}} } diff --git a/field/tag.go b/field/tag.go index 703929e8..b8a66bf4 100644 --- a/field/tag.go +++ b/field/tag.go @@ -5,6 +5,8 @@ import ( "strings" ) +// TODO implement unit tests for tags + const ( TagKeyGorm = "gorm" TagKeyJson = "json" @@ -60,7 +62,7 @@ func (tag Tag) Build() string { } tags := make([]string, 0, len(tag)) - for _, k := range tagKeys(tag) { + for _, k := range tag.keys() { v := tag[k] if k == "" { continue @@ -70,6 +72,18 @@ func (tag Tag) Build() string { return strings.Join(tags, " ") } +func (tag Tag) keys() []string { + if len(tag) == 0 { + return nil + } + + keys := make([]string, 0, len(tag)) + for k := range tag { + keys = append(keys, k) + } + return keySort(keys) +} + type GormTag map[string][]string func (tag GormTag) Append(key string, values ...string) GormTag { @@ -95,8 +109,9 @@ func (tag GormTag) Build() string { if len(tag) == 0 { return "" } + tags := make([]string, 0, len(tag)) - for _, k := range gormKeys(tag) { + for _, k := range tag.keys() { vs := tag[k] if len(vs) == 0 && k == "" { continue @@ -123,22 +138,12 @@ func (tag GormTag) Build() string { return strings.Join(tags, ";") } -func tagKeys(tag Tag) []string { - keys := make([]string, 0, len(tag)) +func (tag GormTag) keys() []string { if len(tag) == 0 { - return keys - } - for k := range tag { - keys = append(keys, k) + return nil } - return keySort(keys) -} -func gormKeys(tag GormTag) []string { keys := make([]string, 0, len(tag)) - if len(tag) == 0 { - return keys - } for k := range tag { keys = append(keys, k) } @@ -149,6 +154,7 @@ func keySort(keys []string) []string { if len(keys) == 0 { return keys } + sort.Slice(keys, func(i, j int) bool { if tagKeyPriorities[keys[i]] == tagKeyPriorities[keys[j]] { return keys[i] <= keys[j] diff --git a/field/time.go b/field/time.go index ec86f0cd..9198d841 100644 --- a/field/time.go +++ b/field/time.go @@ -8,36 +8,8 @@ import ( ) // Time time type field -type Time Field - -// Eq equal to -func (field Time) Eq(value time.Time) Expr { - return expr{e: clause.Eq{Column: field.RawExpr(), Value: value}} -} - -// Neq not equal to -func (field Time) Neq(value time.Time) Expr { - return expr{e: clause.Neq{Column: field.RawExpr(), Value: value}} -} - -// Gt greater than -func (field Time) Gt(value time.Time) Expr { - return expr{e: clause.Gt{Column: field.RawExpr(), Value: value}} -} - -// Gte greater or equal to -func (field Time) Gte(value time.Time) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field Time) Lt(value time.Time) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field Time) Lte(value time.Time) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} +type Time struct { + genericsField[time.Time] } // Between ... @@ -50,11 +22,6 @@ func (field Time) NotBetween(left time.Time, right time.Time) Expr { return Not(field.Between(left, right)) } -// In ... -func (field Time) In(values ...time.Time) Expr { - return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} -} - // NotIn ... func (field Time) NotIn(values ...time.Time) Expr { return expr{e: clause.Not(field.In(values...).expression())} @@ -62,137 +29,116 @@ func (field Time) NotIn(values ...time.Time) Expr { // Add ... func (field Time) Add(value time.Duration) Time { - return Time{field.add(value)} + return Time{genericsField[time.Time]{field.add(value)}} } // Sub ... func (field Time) Sub(value time.Duration) Time { - return Time{field.sub(value)} + return Time{genericsField[time.Time]{field.sub(value)}} } // Date convert to data, equal to "DATE(time_expr)" func (field Time) Date() Time { - return Time{expr{e: clause.Expr{SQL: "DATE(?)", Vars: []interface{}{field.RawExpr()}}}} + return Time{genericsField[time.Time]{expr{e: clause.Expr{SQL: "DATE(?)", Vars: []interface{}{field.RawExpr()}}}}} } // DateDiff equal to DATADIFF(self, value) -func (field Time) DateDiff(value time.Time) Int { - return Int{expr{e: clause.Expr{SQL: "DATEDIFF(?,?)", Vars: []interface{}{field.RawExpr(), value}}}} +func (field Time) DateDiff(value time.Time) Number[int] { + return newNumber[int](expr{e: clause.Expr{SQL: "DATEDIFF(?,?)", Vars: []interface{}{field.RawExpr(), value}}}) } // DateFormat equal to DATE_FORMAT(self, value) func (field Time) DateFormat(value string) String { - return String{expr{e: clause.Expr{SQL: "DATE_FORMAT(?,?)", Vars: []interface{}{field.RawExpr(), value}}}} + return newChars[string](expr{e: clause.Expr{SQL: "DATE_FORMAT(?,?)", Vars: []interface{}{field.RawExpr(), value}}}) } // Now return result of NOW() func (field Time) Now() Time { - return Time{expr{e: clause.Expr{SQL: "NOW()"}}} + return Time{genericsField[time.Time]{expr{e: clause.Expr{SQL: "NOW()"}}}} } // CurDate return result of CURDATE() func (field Time) CurDate() Time { - return Time{expr{e: clause.Expr{SQL: "CURDATE()"}}} + return Time{genericsField[time.Time]{expr{e: clause.Expr{SQL: "CURDATE()"}}}} } // CurTime return result of CURTIME() func (field Time) CurTime() Time { - return Time{expr{e: clause.Expr{SQL: "CURTIME()"}}} + return Time{genericsField[time.Time]{expr{e: clause.Expr{SQL: "CURTIME()"}}}} } // DayName equal to DAYNAME(self) func (field Time) DayName() String { - return String{expr{e: clause.Expr{SQL: "DAYNAME(?)", Vars: []interface{}{field.RawExpr()}}}} + return newChars[string](expr{e: clause.Expr{SQL: "DAYNAME(?)", Vars: []interface{}{field.RawExpr()}}}) + } // MonthName equal to MONTHNAME(self) func (field Time) MonthName() String { - return String{expr{e: clause.Expr{SQL: "MONTHNAME(?)", Vars: []interface{}{field.RawExpr()}}}} + return newChars[string](expr{e: clause.Expr{SQL: "MONTHNAME(?)", Vars: []interface{}{field.RawExpr()}}}) } -func (field Time) Year() Int { - return Int{expr{e: clause.Expr{SQL: "YEAR(?)", Vars: []interface{}{field.RawExpr()}}}} +// Year equal to YEAR(self) +func (field Time) Year() Number[int] { + return newNumber[int](expr{e: clause.Expr{SQL: "YEAR(?)", Vars: []interface{}{field.RawExpr()}}}) } // Month equal to MONTH(self) -func (field Time) Month() Int { - return Int{expr{e: clause.Expr{SQL: "MONTH(?)", Vars: []interface{}{field.RawExpr()}}}} +func (field Time) Month() Number[int] { + return newNumber[int](expr{e: clause.Expr{SQL: "MONTH(?)", Vars: []interface{}{field.RawExpr()}}}) } // Day equal to DAY(self) -func (field Time) Day() Int { - return Int{expr{e: clause.Expr{SQL: "DAY(?)", Vars: []interface{}{field.RawExpr()}}}} +func (field Time) Day() Number[int] { + return newNumber[int](expr{e: clause.Expr{SQL: "DAY(?)", Vars: []interface{}{field.RawExpr()}}}) } // Hour equal to HOUR(self) -func (field Time) Hour() Int { - return Int{expr{e: clause.Expr{SQL: "HOUR(?)", Vars: []interface{}{field.RawExpr()}}}} +func (field Time) Hour() Number[int] { + return newNumber[int](expr{e: clause.Expr{SQL: "HOUR(?)", Vars: []interface{}{field.RawExpr()}}}) } // Minute equal to MINUTE(self) -func (field Time) Minute() Int { - return Int{expr{e: clause.Expr{SQL: "MINUTE(?)", Vars: []interface{}{field.RawExpr()}}}} +func (field Time) Minute() Number[int] { + return newNumber[int](expr{e: clause.Expr{SQL: "MINUTE(?)", Vars: []interface{}{field.RawExpr()}}}) } // Second equal to SECOND(self) -func (field Time) Second() Int { - return Int{expr{e: clause.Expr{SQL: "SECOND(?)", Vars: []interface{}{field.RawExpr()}}}} +func (field Time) Second() Number[int] { + return newNumber[int](expr{e: clause.Expr{SQL: "SECOND(?)", Vars: []interface{}{field.RawExpr()}}}) } // MicroSecond equal to MICROSECOND(self) -func (field Time) MicroSecond() Int { - return Int{expr{e: clause.Expr{SQL: "MICROSECOND(?)", Vars: []interface{}{field.RawExpr()}}}} +func (field Time) MicroSecond() Number[int] { + return newNumber[int](expr{e: clause.Expr{SQL: "MICROSECOND(?)", Vars: []interface{}{field.RawExpr()}}}) } // DayOfWeek equal to DAYOFWEEK(self) -func (field Time) DayOfWeek() Int { - return Int{expr{e: clause.Expr{SQL: "DAYOFWEEK(?)", Vars: []interface{}{field.RawExpr()}}}} +func (field Time) DayOfWeek() Number[int] { + return newNumber[int](expr{e: clause.Expr{SQL: "DAYOFWEEK(?)", Vars: []interface{}{field.RawExpr()}}}) } // DayOfMonth equal to DAYOFMONTH(self) -func (field Time) DayOfMonth() Int { - return Int{expr{e: clause.Expr{SQL: "DAYOFMONTH(?)", Vars: []interface{}{field.RawExpr()}}}} +func (field Time) DayOfMonth() Number[int] { + return newNumber[int](expr{e: clause.Expr{SQL: "DAYOFMONTH(?)", Vars: []interface{}{field.RawExpr()}}}) } // DayOfYear equal to DAYOFYEAR(self) -func (field Time) DayOfYear() Int { - return Int{expr{e: clause.Expr{SQL: "DAYOFYEAR(?)", Vars: []interface{}{field.RawExpr()}}}} +func (field Time) DayOfYear() Number[int] { + return newNumber[int](expr{e: clause.Expr{SQL: "DAYOFYEAR(?)", Vars: []interface{}{field.RawExpr()}}}) } // FromDays equal to FROM_DAYS(self) func (field Time) FromDays(value int) Time { - return Time{expr{e: clause.Expr{SQL: fmt.Sprintf("FROM_DAYS(%d)", value)}}} + return Time{genericsField[time.Time]{expr{e: clause.Expr{SQL: fmt.Sprintf("FROM_DAYS(%d)", value)}}}} } // FromUnixtime equal to FROM_UNIXTIME(self) func (field Time) FromUnixtime(value int) Time { - return Time{expr{e: clause.Expr{SQL: fmt.Sprintf("FROM_UNIXTIME(%d)", value)}}} -} - -// Value set value -func (field Time) Value(value time.Time) AssignExpr { - return field.value(value) + return Time{genericsField[time.Time]{expr{e: clause.Expr{SQL: fmt.Sprintf("FROM_UNIXTIME(%d)", value)}}}} } // Zero set zero value func (field Time) Zero() AssignExpr { return field.value(time.Time{}) } - -// Sum calc sum -func (field Time) Sum() Time { - return Time{field.sum()} -} - -// IfNull ... -func (field Time) IfNull(value time.Time) Expr { - return field.ifNull(value) -} - -func (field Time) toSlice(values ...time.Time) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice -} diff --git a/generator.go b/generator.go index 1635ab0d..5fa4c285 100644 --- a/generator.go +++ b/generator.go @@ -394,22 +394,37 @@ func (g *Generator) generateSingleQueryFile(data *genInfo) (err error) { return err } - data.QueryStructMeta = data.QueryStructMeta.IfaceMode(g.judgeMode(WithQueryInterface)) + data.QueryStructMeta = data.QueryStructMeta.IfaceMode(g.judgeMode(WithQueryInterface) || g.judgeMode(WithGeneric)) + data.QueryStructMeta = data.QueryStructMeta.GenericMode(g.judgeMode(WithGeneric)) structTmpl := tmpl.TableQueryStructWithContext + crudTmpl := tmpl.CRUDMethod + ifaceTmpl := "" + + if g.judgeMode(WithQueryInterface) { + ifaceTmpl = tmpl.TableQueryIface + } if g.judgeMode(WithoutContext) { structTmpl = tmpl.TableQueryStruct } + if g.judgeMode(WithGeneric) { + structTmpl += tmpl.DefineGenericsMethodStruct + crudTmpl = tmpl.CRUDGenericMethod + ifaceTmpl = tmpl.TableGenericQueryIface + } else { + structTmpl += tmpl.DefineMethodStruct + } err = render(structTmpl, &buf, data.QueryStructMeta) if err != nil { return err } - - if g.judgeMode(WithQueryInterface) { - err = render(tmpl.TableQueryIface, &buf, data) - if err != nil { - return err - } + err = render(ifaceTmpl, &buf, data) + if err != nil { + return err + } + err = render(crudTmpl, &buf, data.QueryStructMeta) + if err != nil { + return err } for _, method := range data.Interfaces { @@ -419,11 +434,6 @@ func (g *Generator) generateSingleQueryFile(data *genInfo) (err error) { } } - err = render(tmpl.CRUDMethod, &buf, data.QueryStructMeta) - if err != nil { - return err - } - defer g.info(fmt.Sprintf("generate query file: %s%s%s.gen.go", g.OutPath, string(os.PathSeparator), data.FileName)) return g.output(fmt.Sprintf("%s%s%s.gen.go", g.OutPath, string(os.PathSeparator), data.FileName), buf.Bytes()) } @@ -582,6 +592,9 @@ func (g *Generator) pushQueryStructMeta(meta *generate.QueryStructMeta) (*genInf } func render(tmpl string, wr io.Writer, data interface{}) error { + if tmpl == "" { + return nil + } t, err := template.New(tmpl).Parse(tmpl) if err != nil { return err diff --git a/generator_test.go b/generator_test.go index 1ab13f2c..85955989 100644 --- a/generator_test.go +++ b/generator_test.go @@ -273,10 +273,10 @@ type Student struct { DO ALL field.Asterisk - ID field.Int64 - Name field.String - Age field.Int - Instructor field.Int64 + ID field.Number[int64] + Name field.Chars[string] + Age field.Number[int] + Instructor field.Number[int64] } var student = func() *Student { @@ -296,8 +296,8 @@ type Teacher struct { DO ALL field.Asterisk - ID field.Int64 - Name field.String + ID field.Number[int64] + Name field.Chars[string] } var teacher = func() Teacher { diff --git a/generics.go b/generics.go new file mode 100644 index 00000000..7a236150 --- /dev/null +++ b/generics.go @@ -0,0 +1,368 @@ +package gen + +import ( + "context" + "database/sql" + "gorm.io/gen/field" + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + "gorm.io/plugin/dbresolver" +) + +// IGenericsDo generic query interface +type IGenericsDo[T any, E any] interface { + SubQuery + Debug() T + WithContext(ctx context.Context) T + WithResult(fc func(tx Dao)) ResultInfo + ReplaceDB(db *gorm.DB) + ReadDB() T + WriteDB() T + As(alias string) Dao + Session(config *gorm.Session) T + Columns(cols ...field.Expr) Columns + Clauses(conds ...clause.Expression) T + Not(conds ...Condition) T + Or(conds ...Condition) T + Select(conds ...field.Expr) T + Where(conds ...Condition) T + Order(conds ...field.Expr) T + Distinct(cols ...field.Expr) T + Omit(cols ...field.Expr) T + Join(table schema.Tabler, on ...field.Expr) T + LeftJoin(table schema.Tabler, on ...field.Expr) T + RightJoin(table schema.Tabler, on ...field.Expr) T + Group(cols ...field.Expr) T + Having(conds ...Condition) T + Limit(limit int) T + Offset(offset int) T + Count() (count int64, err error) + Scopes(funcs ...func(Dao) Dao) T + Unscoped() T + Create(values ...E) error + CreateInBatches(values []E, batchSize int) error + Save(values ...E) error + First() (E, error) + Take() (E, error) + Last() (E, error) + Find() ([]E, error) + FindInBatch(batchSize int, fc func(tx Dao, batch int) error) (results []E, err error) + FindInBatches(result *[]E, batchSize int, fc func(tx Dao, batch int) error) error + Pluck(column field.Expr, dest interface{}) error + Delete(...E) (info ResultInfo, err error) + Update(column field.Expr, value interface{}) (info ResultInfo, err error) + UpdateSimple(columns ...field.AssignExpr) (info ResultInfo, err error) + Updates(value interface{}) (info ResultInfo, err error) + UpdateColumn(column field.Expr, value interface{}) (info ResultInfo, err error) + UpdateColumnSimple(columns ...field.AssignExpr) (info ResultInfo, err error) + UpdateColumns(value interface{}) (info ResultInfo, err error) + UpdateFrom(q SubQuery) Dao + Attrs(attrs ...field.AssignExpr) T + Assign(attrs ...field.AssignExpr) T + Joins(fields ...field.RelationField) T + Preload(fields ...field.RelationField) T + FirstOrInit() (E, error) + FirstOrCreate() (E, error) + FindByPage(offset int, limit int) (result []E, count int64, err error) + ScanByPage(result interface{}, offset int, limit int) (count int64, err error) + Rows() (*sql.Rows, error) + Row() *sql.Row + Scan(result interface{}) (err error) + Returning(value interface{}, columns ...string) T + UnderlyingDB() *gorm.DB + schema.Tabler + GetInstance(do Dao) T + ToSQL(queryFn func(T) T) string +} + +// GenericsDo base impl of IGenericsDo +type GenericsDo[T IGenericsDo[T, E], E any] struct { + DO + RealDO T +} + +// Debug ... +func (b GenericsDo[T, E]) Debug() T { + return b.withDO(b.DO.Debug()) +} + +// WithContext ... +func (b GenericsDo[T, E]) WithContext(ctx context.Context) T { + return b.withDO(b.DO.WithContext(ctx)) +} + +// ReadDB ... +func (b GenericsDo[T, E]) ReadDB() T { + return b.Clauses(dbresolver.Read) +} + +// WriteDB ... +func (b GenericsDo[T, E]) WriteDB() T { + return b.Clauses(dbresolver.Write) +} + +// Session ... +func (b GenericsDo[T, E]) Session(config *gorm.Session) T { + return b.withDO(b.DO.Session(config)) +} + +// Clauses ... +func (b GenericsDo[T, E]) Clauses(conds ...clause.Expression) T { + return b.withDO(b.DO.Clauses(conds...)) +} + +// Returning ... +func (b GenericsDo[T, E]) Returning(value interface{}, columns ...string) T { + return b.withDO(b.DO.Returning(value, columns...)) +} + +// Not ... +func (b GenericsDo[T, E]) Not(conds ...Condition) T { + return b.withDO(b.DO.Not(conds...)) +} + +// Or ... +func (b GenericsDo[T, E]) Or(conds ...Condition) T { + return b.withDO(b.DO.Or(conds...)) +} + +// Select ... +func (b GenericsDo[T, E]) Select(conds ...field.Expr) T { + return b.withDO(b.DO.Select(conds...)) +} + +// Where ... +func (b GenericsDo[T, E]) Where(conds ...Condition) T { + return b.withDO(b.DO.Where(conds...)) +} + +// Order ... +func (b GenericsDo[T, E]) Order(conds ...field.Expr) T { + return b.withDO(b.DO.Order(conds...)) +} + +// Distinct ... +func (b GenericsDo[T, E]) Distinct(cols ...field.Expr) T { + return b.withDO(b.DO.Distinct(cols...)) +} + +// Omit ... +func (b GenericsDo[T, E]) Omit(cols ...field.Expr) T { + return b.withDO(b.DO.Omit(cols...)) +} + +// Join ... +func (b GenericsDo[T, E]) Join(table schema.Tabler, on ...field.Expr) T { + return b.withDO(b.DO.Join(table, on...)) +} + +// LeftJoin ... +func (b GenericsDo[T, E]) LeftJoin(table schema.Tabler, on ...field.Expr) T { + return b.withDO(b.DO.LeftJoin(table, on...)) +} + +// RightJoin ... +func (b GenericsDo[T, E]) RightJoin(table schema.Tabler, on ...field.Expr) T { + return b.withDO(b.DO.RightJoin(table, on...)) +} + +// Group ... +func (b GenericsDo[T, E]) Group(cols ...field.Expr) T { + return b.withDO(b.DO.Group(cols...)) +} + +// Having ... +func (b GenericsDo[T, E]) Having(conds ...Condition) T { + return b.withDO(b.DO.Having(conds...)) +} + +// Limit ... +func (b GenericsDo[T, E]) Limit(limit int) T { + return b.withDO(b.DO.Limit(limit)) +} + +// Offset ... +func (b GenericsDo[T, E]) Offset(offset int) T { + return b.withDO(b.DO.Offset(offset)) +} + +// Scopes ... +func (b GenericsDo[T, E]) Scopes(funcs ...func(Dao) Dao) T { + return b.withDO(b.DO.Scopes(funcs...)) +} + +// Unscoped ... +func (b GenericsDo[T, E]) Unscoped() T { + return b.withDO(b.DO.Unscoped()) +} + +// Create ... +func (b GenericsDo[T, E]) Create(values ...E) error { + if len(values) == 0 { + return nil + } + return b.DO.Create(values) +} + +// CreateInBatches ... +func (b GenericsDo[T, E]) CreateInBatches(values []E, batchSize int) error { + return b.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (b GenericsDo[T, E]) Save(values ...E) error { + if len(values) == 0 { + return nil + } + return b.DO.Save(values) +} + +// First ... +func (b GenericsDo[T, E]) First() (E, error) { + var e E + if result, err := b.DO.First(); err != nil { + return e, err + } else { + return result.(E), nil + } +} + +// Take ... +func (b GenericsDo[T, E]) Take() (E, error) { + var e E + if result, err := b.DO.Take(); err != nil { + return e, err + } else { + return result.(E), nil + } +} + +// Last ... +func (b GenericsDo[T, E]) Last() (E, error) { + var e E + if result, err := b.DO.Last(); err != nil { + return e, err + } else { + return result.(E), nil + } +} + +// Find ... +func (b GenericsDo[T, E]) Find() ([]E, error) { + result, err := b.DO.Find() + return result.([]E), err +} + +// FindInBatch ... +func (b GenericsDo[T, E]) FindInBatch(batchSize int, fc func(tx Dao, batch int) error) (results []E, err error) { + buf := make([]E, 0, batchSize) + err = b.DO.FindInBatches(&buf, batchSize, func(tx Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +// FindInBatches ... +func (b GenericsDo[T, E]) FindInBatches(result *[]E, batchSize int, fc func(tx Dao, batch int) error) error { + return b.DO.FindInBatches(result, batchSize, fc) +} + +// Attrs ... +func (b GenericsDo[T, E]) Attrs(attrs ...field.AssignExpr) T { + return b.withDO(b.DO.Attrs(attrs...)) +} + +// Assign ... +func (b GenericsDo[T, E]) Assign(attrs ...field.AssignExpr) T { + return b.withDO(b.DO.Assign(attrs...)) +} + +// Joins ... +func (b GenericsDo[T, E]) Joins(fields ...field.RelationField) T { + var do Dao = &b.DO + for _, _f := range fields { + do = do.Joins(_f) + } + return b.withDO(do) +} + +// Preload ... +func (b GenericsDo[T, E]) Preload(fields ...field.RelationField) T { + var do Dao = &b.DO + for _, _f := range fields { + do = do.Preload(_f) + } + return b.withDO(do) +} + +// FirstOrInit ... +func (b GenericsDo[T, E]) FirstOrInit() (E, error) { + var e E + if result, err := b.DO.FirstOrInit(); err != nil { + return e, err + } else { + return result.(E), nil + } +} + +// FirstOrCreate ... +func (b GenericsDo[T, E]) FirstOrCreate() (E, error) { + var e E + if result, err := b.DO.FirstOrCreate(); err != nil { + return e, err + } else { + return result.(E), nil + } +} + +// FindByPage ... +func (b GenericsDo[T, E]) FindByPage(offset int, limit int) (result []E, count int64, err error) { + result, err = b.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = b.Offset(-1).Limit(-1).Count() + return +} + +// ScanByPage ... +func (b GenericsDo[T, E]) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = b.Count() + if err != nil { + return + } + err = b.Offset(offset).Limit(limit).Scan(result) + return +} + +// Scan ... +func (b GenericsDo[T, E]) Scan(result interface{}) (err error) { + return b.DO.Scan(result) +} + +// Delete ... +func (b GenericsDo[T, E]) Delete(models ...E) (result ResultInfo, err error) { + return b.DO.Delete(models) +} + +// ToSQL ... +func (b GenericsDo[T, E]) ToSQL(queryFn func(T) T) string { + b.db = b.db.Session(&gorm.Session{DryRun: true, SkipDefaultTransaction: true}) + t := queryFn(b.withDO(&b.DO)) + db := t.underlyingDB() + stmt := db.Statement + return db.Dialector.Explain(stmt.SQL.String(), stmt.Vars...) +} + +func (b *GenericsDo[T, E]) withDO(do Dao) T { + return b.RealDO.GetInstance(do) +} diff --git a/go.mod b/go.mod index bc6eeed6..509fa523 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,8 @@ module gorm.io/gen go 1.18 require ( - golang.org/x/tools v0.17.0 + golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 + golang.org/x/tools v0.20.0 gorm.io/datatypes v1.2.4 gorm.io/gorm v1.25.11 gorm.io/hints v1.1.0 @@ -16,7 +17,8 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - golang.org/x/mod v0.14.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/sync v0.7.0 // indirect golang.org/x/text v0.14.0 // indirect gorm.io/driver/mysql v1.5.6 // indirect ) diff --git a/go.sum b/go.sum index 6b983a2b..eae005fd 100644 --- a/go.sum +++ b/go.sum @@ -27,13 +27,16 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 h1:ESSUROHIBHg7USnszlcdmjBEwdMj9VUvU+OPk4yl2mc= +golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/datatypes v1.2.4 h1:uZmGAcK/QZ0uyfCuVg0VQY1ZmV9h1fuG0tMwKByO1z4= diff --git a/internal/generate/query.go b/internal/generate/query.go index f25835da..4fd51896 100644 --- a/internal/generate/query.go +++ b/internal/generate/query.go @@ -40,6 +40,8 @@ type QueryStructMeta struct { ModelMethods []*parser.Method // user custom method bind to db base struct interfaceMode bool + + UseGenericMode bool // use generic mode } // parseStruct get all elements of struct with gorm's Parse, ignore unexported elements @@ -232,6 +234,12 @@ func (b QueryStructMeta) IfaceMode(on bool) *QueryStructMeta { return &b } +// GenericMode object mode +func (b QueryStructMeta) GenericMode(on bool) *QueryStructMeta { + b.UseGenericMode = on + return &b +} + // ReturnObject return object in generated code func (b *QueryStructMeta) ReturnObject() string { if b.interfaceMode { diff --git a/internal/template/method.go b/internal/template/method.go index 5263166e..0099a738 100644 --- a/internal/template/method.go +++ b/internal/template/method.go @@ -27,6 +27,16 @@ func ({{.S}} {{.TargetStruct}}Do){{.FuncSign}}{ ` +// CRUDGenericMethod generic CRUD method +const CRUDGenericMethod = ` +func ({{.S}} *{{.QueryStructName}}Do) GetInstance(do gen.Dao) {{.ReturnObject}} { + _r := &{{.QueryStructName}}Do{} + _r.DO = *do.(*gen.DO) + _r.RealDO=_r + return _r +} +` + // CRUDMethod CRUD method const CRUDMethod = ` func ({{.S}} {{.QueryStructName}}Do) Debug() {{.ReturnObject}} { diff --git a/internal/template/struct.go b/internal/template/struct.go index d0415cb0..c4f18120 100644 --- a/internal/template/struct.go +++ b/internal/template/struct.go @@ -8,7 +8,7 @@ const ( {{.QueryStructName}}Do ` + fields + ` } - ` + tableMethod + asMethond + updateFieldMethod + getFieldMethod + fillFieldMapMethod + cloneMethod + replaceMethod + relationship + defineMethodStruct + ` + tableMethod + asMethond + updateFieldMethod + getFieldMethod + fillFieldMapMethod + cloneMethod + replaceMethod + relationship // TableQueryStructWithContext table query struct with context TableQueryStructWithContext = createMethod + ` @@ -27,17 +27,28 @@ const ( func ({{.S}} {{.QueryStructName}}) Columns(cols ...field.Expr) gen.Columns { return {{.S}}.{{.QueryStructName}}Do.Columns(cols...) } - ` + getFieldMethod + fillFieldMapMethod + cloneMethod + replaceMethod + relationship + defineMethodStruct + ` + getFieldMethod + fillFieldMapMethod + cloneMethod + replaceMethod + relationship // TableQueryIface table query interface TableQueryIface = defineDoInterface + + // TableGenericQueryIface table generic query interface + TableGenericQueryIface = defineGenericsDoInterface + + //DefineGenericsMethodStruct generics do struct + DefineGenericsMethodStruct = `type {{.QueryStructName}}Do struct {gen.GenericsDo[I{{.ModelStructName}}Do, *{{.StructInfo.Package}}.{{.StructInfo.Type}}]}` + + // DefineMethodStruct do struct + DefineMethodStruct = `type {{.QueryStructName}}Do struct { gen.DO }` ) const ( createMethod = ` func new{{.ModelStructName}}(db *gorm.DB, opts ...gen.DOOption) {{.QueryStructName}} { _{{.QueryStructName}} := {{.QueryStructName}}{} - + {{if .UseGenericMode}} + _{{.QueryStructName}}.{{.QueryStructName}}Do.RealDO = &_{{.QueryStructName}}.{{.QueryStructName}}Do + {{end}} _{{.QueryStructName}}.{{.QueryStructName}}Do.UseDB(db,opts...) _{{.QueryStructName}}.{{.QueryStructName}}Do.UseModel(&{{.StructInfo.Package}}.{{.StructInfo.Type}}{}) @@ -131,7 +142,6 @@ func ({{.S}} *{{.QueryStructName}}) GetFieldByName(fieldName string) (field.Orde `{{- $relation := .Relation }}{{- $relationship := $relation.RelationshipName}}` + relationStruct + relationTx + `{{end}}{{end}}` - defineMethodStruct = `type {{.QueryStructName}}Do struct { gen.DO }` fillFieldMapMethod = ` func ({{.S}} *{{.QueryStructName}}) fillFieldMap() { @@ -143,7 +153,14 @@ func ({{.S}} *{{.QueryStructName}}) fillFieldMap() { {{end -}} } ` - + defineGenericsDoInterface = ` +type I{{.ModelStructName}}Do interface { + gen.IGenericsDo[I{{.ModelStructName}}Do, *{{.StructInfo.Package}}.{{.StructInfo.Type}}] + {{range .Interfaces -}} + {{.FuncSign}} + {{end}} +} +` defineDoInterface = ` type I{{.ModelStructName}}Do interface { diff --git a/tests/.expect/dal_7/model/users.gen.go b/tests/.expect/dal_7/model/users.gen.go new file mode 100644 index 00000000..3382a43d --- /dev/null +++ b/tests/.expect/dal_7/model/users.gen.go @@ -0,0 +1,33 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameUser = "users" + +// User mapped from table +type User struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true" json:"-"` + CreatedAt *time.Time `gorm:"column:created_at" json:"-"` + Name *string `gorm:"column:name;index:idx_name,priority:1;index:idx_name_company_id,priority:1;comment:oneline" json:"-"` // oneline + Address *string `gorm:"column:address" json:"-"` + RegisterTime *time.Time `gorm:"column:register_time" json:"-"` + /* + multiline + line1 + line2 + */ + Alive *bool `gorm:"column:alive;comment:multiline\nline1\nline2" json:"-"` + CompanyID *int64 `gorm:"column:company_id;index:idx_name_company_id,priority:2;default:666" json:"-"` + PrivateURL *string `gorm:"column:private_url;default:https://a.b.c" json:"-"` +} + +// TableName User's table name +func (*User) TableName() string { + return TableNameUser +} diff --git a/tests/.expect/dal_7/query/gen.go b/tests/.expect/dal_7/query/gen.go new file mode 100644 index 00000000..a19d931b --- /dev/null +++ b/tests/.expect/dal_7/query/gen.go @@ -0,0 +1,103 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package query + +import ( + "context" + "database/sql" + + "gorm.io/gorm" + + "gorm.io/gen" + + "gorm.io/plugin/dbresolver" +) + +var ( + Q = new(Query) + User *user +) + +func SetDefault(db *gorm.DB, opts ...gen.DOOption) { + *Q = *Use(db, opts...) + User = &Q.User +} + +func Use(db *gorm.DB, opts ...gen.DOOption) *Query { + return &Query{ + db: db, + User: newUser(db, opts...), + } +} + +type Query struct { + db *gorm.DB + + User user +} + +func (q *Query) Available() bool { return q.db != nil } + +func (q *Query) clone(db *gorm.DB) *Query { + return &Query{ + db: db, + User: q.User.clone(db), + } +} + +func (q *Query) ReadDB() *Query { + return q.ReplaceDB(q.db.Clauses(dbresolver.Read)) +} + +func (q *Query) WriteDB() *Query { + return q.ReplaceDB(q.db.Clauses(dbresolver.Write)) +} + +func (q *Query) ReplaceDB(db *gorm.DB) *Query { + return &Query{ + db: db, + User: q.User.replaceDB(db), + } +} + +type queryCtx struct { + User IUserDo +} + +func (q *Query) WithContext(ctx context.Context) *queryCtx { + return &queryCtx{ + User: q.User.WithContext(ctx), + } +} + +func (q *Query) Transaction(fc func(tx *Query) error, opts ...*sql.TxOptions) error { + return q.db.Transaction(func(tx *gorm.DB) error { return fc(q.clone(tx)) }, opts...) +} + +func (q *Query) Begin(opts ...*sql.TxOptions) *QueryTx { + tx := q.db.Begin(opts...) + return &QueryTx{Query: q.clone(tx), Error: tx.Error} +} + +type QueryTx struct { + *Query + Error error +} + +func (q *QueryTx) Commit() error { + return q.db.Commit().Error +} + +func (q *QueryTx) Rollback() error { + return q.db.Rollback().Error +} + +func (q *QueryTx) SavePoint(name string) error { + return q.db.SavePoint(name).Error +} + +func (q *QueryTx) RollbackTo(name string) error { + return q.db.RollbackTo(name).Error +} diff --git a/tests/.expect/dal_7/query/users.gen.go b/tests/.expect/dal_7/query/users.gen.go new file mode 100644 index 00000000..46f8c75a --- /dev/null +++ b/tests/.expect/dal_7/query/users.gen.go @@ -0,0 +1,907 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package query + +import ( + "context" + "database/sql" + "strings" + + "gorm.io/gen" + "gorm.io/gen/field" + "gorm.io/gen/helper" + "gorm.io/gorm" + + "gorm.io/gen/tests/.gen/dal_7/model" + + "time" +) + +func newUser(db *gorm.DB, opts ...gen.DOOption) user { + _user := user{} + + _user.userDo.RealDO = &_user.userDo + + _user.userDo.UseDB(db, opts...) + _user.userDo.UseModel(&model.User{}) + + tableName := _user.userDo.TableName() + _user.ALL = field.NewAsterisk(tableName) + _user.ID = field.NewInt64(tableName, "id") + _user.CreatedAt = field.NewTime(tableName, "created_at") + _user.Name = field.NewString(tableName, "name") + _user.Address = field.NewString(tableName, "address") + _user.RegisterTime = field.NewTime(tableName, "register_time") + _user.Alive = field.NewBool(tableName, "alive") + _user.CompanyID = field.NewInt64(tableName, "company_id") + _user.PrivateURL = field.NewString(tableName, "private_url") + + _user.fillFieldMap() + + return _user +} + +type user struct { + userDo userDo + + ALL field.Asterisk + ID field.Int64 + CreatedAt field.Time + Name field.String // oneline + Address field.String + RegisterTime field.Time + /* + multiline + line1 + line2 + */ + Alive field.Bool + CompanyID field.Int64 + PrivateURL field.String + + fieldMap map[string]field.Expr +} + +func (u user) Table(newTableName string) *user { + u.userDo.UseTable(newTableName) + return u.updateTableName(newTableName) +} + +func (u user) As(alias string) *user { + u.userDo.DO = *(u.userDo.As(alias).(*gen.DO)) + return u.updateTableName(alias) +} + +func (u *user) updateTableName(table string) *user { + u.ALL = field.NewAsterisk(table) + u.ID = field.NewInt64(table, "id") + u.CreatedAt = field.NewTime(table, "created_at") + u.Name = field.NewString(table, "name") + u.Address = field.NewString(table, "address") + u.RegisterTime = field.NewTime(table, "register_time") + u.Alive = field.NewBool(table, "alive") + u.CompanyID = field.NewInt64(table, "company_id") + u.PrivateURL = field.NewString(table, "private_url") + + u.fillFieldMap() + + return u +} + +func (u *user) WithContext(ctx context.Context) IUserDo { return u.userDo.WithContext(ctx) } + +func (u user) TableName() string { return u.userDo.TableName() } + +func (u user) Alias() string { return u.userDo.Alias() } + +func (u user) Columns(cols ...field.Expr) gen.Columns { return u.userDo.Columns(cols...) } + +func (u *user) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := u.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (u *user) fillFieldMap() { + u.fieldMap = make(map[string]field.Expr, 8) + u.fieldMap["id"] = u.ID + u.fieldMap["created_at"] = u.CreatedAt + u.fieldMap["name"] = u.Name + u.fieldMap["address"] = u.Address + u.fieldMap["register_time"] = u.RegisterTime + u.fieldMap["alive"] = u.Alive + u.fieldMap["company_id"] = u.CompanyID + u.fieldMap["private_url"] = u.PrivateURL +} + +func (u user) clone(db *gorm.DB) user { + u.userDo.ReplaceConnPool(db.Statement.ConnPool) + return u +} + +func (u user) replaceDB(db *gorm.DB) user { + u.userDo.ReplaceDB(db) + return u +} + +type userDo struct { + gen.GenericsDo[IUserDo, *model.User] +} +type IUserDo interface { + gen.IGenericsDo[IUserDo, *model.User] + FindByUsers(user model.User) (result []model.User) + FindByComplexIf(user *model.User) (result []model.User) + FindByIfTime(start time.Time) (result []model.User) + TestFor(names []string) (result model.User, err error) + TestForKey(names []string, name string, value string) (result model.User, err error) + TestForOr(names []string) (result model.User, err error) + TestIfInFor(names []string, name string) (result model.User, err error) + TestForInIf(names []string, name string) (result model.User, err error) + TestForInWhere(names []string, name string, forName string) (result model.User, err error) + TestForUserList(users []*model.User, name string) (result model.User, err error) + TestForMap(param map[string]string, name string) (result model.User, err error) + TestIfInIf(name string) (result model.User) + TestMoreFor(names []string, ids []int) (result []model.User) + TestMoreFor2(names []string, ids []int) (result []model.User) + TestForInSet(users []model.User) (err error) + TestInsertMoreInfo(users []model.User) (err error) + TestIfElseFor(name string, users []model.User) (err error) + TestForLike(names []string) (result []model.User) + AddUser(name string, age int) (result sql.Result, err error) + AddUser1(name string, age int) (rowsAffected int64, err error) + AddUser2(name string, age int) (rowsAffected int64) + AddUser3(name string, age int) (result sql.Result) + AddUser4(name string, age int) (row *sql.Row) + AddUser5(name string, age int) (rows *sql.Rows) + AddUser6(name string, age int) (rows *sql.Rows, err error) + FindByID(id int) (result model.User) + LikeSearch(name string) (result *model.User) + InSearch(names []string) (result []*model.User) + ColumnSearch(name string, names []string) (result []*model.User) +} + +func (u *userDo) GetInstance(do gen.Dao) IUserDo { + _r := &userDo{} + _r.DO = *do.(*gen.DO) + _r.RealDO = _r + return _r +} + +// FindByUsers +// +// select * from @@table +// {{where}} +// {{if user.Name !=""}} +// name=@user.Name +// {{end}} +// {{end}} +func (u userDo) FindByUsers(user model.User) (result []model.User) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users ") + var whereSQL0 strings.Builder + if user.Name != "" { + params = append(params, user.Name) + whereSQL0.WriteString("name=? ") + } + helper.JoinWhereBuilder(&generateSQL, whereSQL0) + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Find(&result) // ignore_security_alert + _ = executeSQL + + return +} + +// FindByComplexIf +// +// select * from @@table +// {{where}} +// {{if user != nil && user.Name !=""}} +// name=@user.Name +// {{end}} +// {{end}} +func (u userDo) FindByComplexIf(user *model.User) (result []model.User) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users ") + var whereSQL0 strings.Builder + if user != nil && user.Name != "" { + params = append(params, user.Name) + whereSQL0.WriteString("name=? ") + } + helper.JoinWhereBuilder(&generateSQL, whereSQL0) + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Find(&result) // ignore_security_alert + _ = executeSQL + + return +} + +// FindByIfTime +// +// select * from @@table +// {{if !start.IsZero()}} +// created_at > start +// {{end}} +func (u userDo) FindByIfTime(start time.Time) (result []model.User) { + var generateSQL strings.Builder + generateSQL.WriteString("select * from users ") + if !start.IsZero() { + generateSQL.WriteString("created_at > start ") + } + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String()).Find(&result) // ignore_security_alert + _ = executeSQL + + return +} + +// TestFor +// +// select * from @@table where +// {{for _,name:=range names}} +// name = @name and +// {{end}} +// 1=1 +func (u userDo) TestFor(names []string) (result model.User, err error) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users where ") + for _, name := range names { + params = append(params, name) + generateSQL.WriteString("name = ? and ") + } + generateSQL.WriteString("1=1 ") + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Take(&result) // ignore_security_alert + err = executeSQL.Error + + return +} + +// TestForKey +// +// select * from @@table where +// {{for _,name:=range names}} +// or @@name = @value +// {{end}} +// and 1=1 +func (u userDo) TestForKey(names []string, name string, value string) (result model.User, err error) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users where ") + for _, name := range names { + params = append(params, value) + generateSQL.WriteString("or " + u.Quote(name) + " = ? ") + } + generateSQL.WriteString("and 1=1 ") + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Take(&result) // ignore_security_alert + err = executeSQL.Error + + return +} + +// TestForOr +// +// select * from @@table +// {{where}} +// ( +// {{for _,name:=range names}} +// name = @name or +// {{end}} +// {{end}} +// ) +func (u userDo) TestForOr(names []string) (result model.User, err error) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users ") + var whereSQL0 strings.Builder + whereSQL0.WriteString("( ") + for _, name := range names { + params = append(params, name) + whereSQL0.WriteString("name = ? or ") + } + helper.JoinWhereBuilder(&generateSQL, whereSQL0) + generateSQL.WriteString(") ") + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Take(&result) // ignore_security_alert + err = executeSQL.Error + + return +} + +// TestIfInFor +// +// select * from @@table where +// {{for _,name:=range names}} +// {{if name !=""}} +// name = @name or +// {{end}} +// {{end}} +// 1=2 +func (u userDo) TestIfInFor(names []string, name string) (result model.User, err error) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users where ") + for _, name := range names { + if name != "" { + params = append(params, name) + generateSQL.WriteString("name = ? or ") + } + } + generateSQL.WriteString("1=2 ") + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Take(&result) // ignore_security_alert + err = executeSQL.Error + + return +} + +// TestForInIf +// +// select * from @@table where +// {{if name !="" }} +// {{for _,forName:=range names}} +// name = @forName or +// {{end}} +// {{end}} +// 1=2 +func (u userDo) TestForInIf(names []string, name string) (result model.User, err error) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users where ") + if name != "" { + for _, forName := range names { + params = append(params, forName) + generateSQL.WriteString("name = ? or ") + } + } + generateSQL.WriteString("1=2 ") + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Take(&result) // ignore_security_alert + err = executeSQL.Error + + return +} + +// TestForInWhere +// +// select * from @@table +// {{where}} +// {{for _,forName:=range names}} +// or name = @forName +// {{end}} +// {{end}} +func (u userDo) TestForInWhere(names []string, name string, forName string) (result model.User, err error) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users ") + var whereSQL0 strings.Builder + for _, forName := range names { + params = append(params, forName) + whereSQL0.WriteString("or name = ? ") + } + helper.JoinWhereBuilder(&generateSQL, whereSQL0) + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Take(&result) // ignore_security_alert + err = executeSQL.Error + + return +} + +// TestForUserList +// +// select * from users +// {{where}} +// {{for _,user :=range users}} +// name=@user.Name +// {{end}} +// {{end}} +func (u userDo) TestForUserList(users []*model.User, name string) (result model.User, err error) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users ") + var whereSQL0 strings.Builder + for _, user := range users { + params = append(params, user.Name) + whereSQL0.WriteString("name=? ") + } + helper.JoinWhereBuilder(&generateSQL, whereSQL0) + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Take(&result) // ignore_security_alert + err = executeSQL.Error + + return +} + +// TestForMap +// +// select * from users +// {{where}} +// {{for key,value :=range param}} +// @@key=@value +// {{end}} +// {{end}} +func (u userDo) TestForMap(param map[string]string, name string) (result model.User, err error) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users ") + var whereSQL0 strings.Builder + for key, value := range param { + params = append(params, value) + whereSQL0.WriteString(u.Quote(key) + "=? ") + } + helper.JoinWhereBuilder(&generateSQL, whereSQL0) + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Take(&result) // ignore_security_alert + err = executeSQL.Error + + return +} + +// TestIfInIf +// +// select * from users +// {{where}} +// {{if name !="xx"}} +// {{if name !="xx"}} +// name=@name +// {{end}} +// {{end}} +// {{end}} +func (u userDo) TestIfInIf(name string) (result model.User) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users ") + var whereSQL0 strings.Builder + if name != "xx" { + if name != "xx" { + params = append(params, name) + whereSQL0.WriteString("name=? ") + } + } + helper.JoinWhereBuilder(&generateSQL, whereSQL0) + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Take(&result) // ignore_security_alert + _ = executeSQL + + return +} + +// TestMoreFor +// +// select * from @@table +// {{where}} +// {{for _,name := range names}} +// and name=@name +// {{end}} +// {{for _,id:=range ids}} +// and id=@id +// {{end}} +// {{end}} +func (u userDo) TestMoreFor(names []string, ids []int) (result []model.User) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users ") + var whereSQL0 strings.Builder + for _, name := range names { + params = append(params, name) + whereSQL0.WriteString("and name=? ") + } + for _, id := range ids { + params = append(params, id) + whereSQL0.WriteString("and id=? ") + } + helper.JoinWhereBuilder(&generateSQL, whereSQL0) + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Find(&result) // ignore_security_alert + _ = executeSQL + + return +} + +// TestMoreFor2 +// +// select * from @@table +// {{where}} +// {{for _,name := range names}} +// OR (name=@name +// {{for _,id:=range ids}} +// and id=@id +// {{end}} +// and title !=@name) +// {{end}} +// {{end}} +func (u userDo) TestMoreFor2(names []string, ids []int) (result []model.User) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users ") + var whereSQL0 strings.Builder + for _, name := range names { + params = append(params, name) + whereSQL0.WriteString("OR (name=? ") + for _, id := range ids { + params = append(params, id) + whereSQL0.WriteString("and id=? ") + } + params = append(params, name) + whereSQL0.WriteString("and title !=?) ") + } + helper.JoinWhereBuilder(&generateSQL, whereSQL0) + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Find(&result) // ignore_security_alert + _ = executeSQL + + return +} + +// TestForInSet +// +// update @@table +// {{set}} +// {{for _,user:=range users}} +// name=@user.Name, +// {{end}} +// {{end}} where +func (u userDo) TestForInSet(users []model.User) (err error) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("update users ") + var setSQL0 strings.Builder + for _, user := range users { + params = append(params, user.Name) + setSQL0.WriteString("name=?, ") + } + helper.JoinSetBuilder(&generateSQL, setSQL0) + generateSQL.WriteString("where ") + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Exec(generateSQL.String(), params...) // ignore_security_alert + err = executeSQL.Error + + return +} + +// TestInsertMoreInfo +// +// insert into @@table(name,age)values +// {{for index ,user:=range users}} +// {{if index >0}} +// , +// {{end}} +// (@user.Name,@user.Age) +// {{end}} +func (u userDo) TestInsertMoreInfo(users []model.User) (err error) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("insert into users(name,age)values ") + for index, user := range users { + if index > 0 { + generateSQL.WriteString(", ") + } + params = append(params, user.Name) + params = append(params, user.Age) + generateSQL.WriteString("(?,?) ") + } + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Exec(generateSQL.String(), params...) // ignore_security_alert + err = executeSQL.Error + + return +} + +// TestIfElseFor +// +// select * from @@table +// {{where}} +// {{if name =="admin"}} +// ( +// {{for index,user:=range users}} +// {{if index !=0}} +// and +// {{end}} +// name like @user.Name +// {{end}} +// ) +// {{else if name !="guest"}} +// {{for index,guser:=range users}} +// {{if index ==0}} +// ( +// {{else}} +// and +// {{end}} +// name = @guser.Name +// {{end}} +// ) +// {{else}} +// name ="guest" +// {{end}} +// {{end}} +func (u userDo) TestIfElseFor(name string, users []model.User) (err error) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users ") + var whereSQL0 strings.Builder + if name == "admin" { + whereSQL0.WriteString("( ") + for index, user := range users { + if index != 0 { + whereSQL0.WriteString("and ") + } + params = append(params, user.Name) + whereSQL0.WriteString("name like ? ") + } + whereSQL0.WriteString(") ") + } else if name != "guest" { + for index, guser := range users { + if index == 0 { + whereSQL0.WriteString("( ") + } else { + whereSQL0.WriteString("and ") + } + params = append(params, guser.Name) + whereSQL0.WriteString("name = ? ") + } + whereSQL0.WriteString(") ") + } else { + whereSQL0.WriteString("name =\"guest\" ") + } + helper.JoinWhereBuilder(&generateSQL, whereSQL0) + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Exec(generateSQL.String(), params...) // ignore_security_alert + err = executeSQL.Error + + return +} + +// TestForLike +// +// select * from @@table +// {{where}} +// {{for _,name:=range names}} +// name like concat("%",@name,"%") or +// {{end}} +// {{end}} +func (u userDo) TestForLike(names []string) (result []model.User) { + var params []interface{} + + var generateSQL strings.Builder + generateSQL.WriteString("select * from users ") + var whereSQL0 strings.Builder + for _, name := range names { + params = append(params, name) + whereSQL0.WriteString("name like concat(\"%\",?,\"%\") or ") + } + helper.JoinWhereBuilder(&generateSQL, whereSQL0) + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Find(&result) // ignore_security_alert + _ = executeSQL + + return +} + +// AddUser +// +// INSERT INTO users (name,age) VALUES (@name,@age) ON DUPLICATE KEY UPDATE age=VALUES(age) +func (u userDo) AddUser(name string, age int) (result sql.Result, err error) { + var params []interface{} + + var generateSQL strings.Builder + params = append(params, name) + params = append(params, age) + generateSQL.WriteString("INSERT INTO users (name,age) VALUES (?,?) ON DUPLICATE KEY UPDATE age=VALUES(age) ") + + stmt := u.UnderlyingDB().Statement + result, err = stmt.ConnPool.ExecContext(stmt.Context, generateSQL.String(), params...) // ignore_security_alert + + return +} + +// AddUser1 +// +// INSERT INTO users (name,age) VALUES (@name,@age) ON DUPLICATE KEY UPDATE age=VALUES(age) +func (u userDo) AddUser1(name string, age int) (rowsAffected int64, err error) { + var params []interface{} + + var generateSQL strings.Builder + params = append(params, name) + params = append(params, age) + generateSQL.WriteString("INSERT INTO users (name,age) VALUES (?,?) ON DUPLICATE KEY UPDATE age=VALUES(age) ") + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Exec(generateSQL.String(), params...) // ignore_security_alert + rowsAffected = executeSQL.RowsAffected + err = executeSQL.Error + + return +} + +// AddUser2 +// +// INSERT INTO users (name,age) VALUES (@name,@age) ON DUPLICATE KEY UPDATE age=VALUES(age) +func (u userDo) AddUser2(name string, age int) (rowsAffected int64) { + var params []interface{} + + var generateSQL strings.Builder + params = append(params, name) + params = append(params, age) + generateSQL.WriteString("INSERT INTO users (name,age) VALUES (?,?) ON DUPLICATE KEY UPDATE age=VALUES(age) ") + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Exec(generateSQL.String(), params...) // ignore_security_alert + rowsAffected = executeSQL.RowsAffected + + return +} + +// AddUser3 +// +// INSERT INTO users (name,age) VALUES (@name,@age) ON DUPLICATE KEY UPDATE age=VALUES(age) +func (u userDo) AddUser3(name string, age int) (result sql.Result) { + var params []interface{} + + var generateSQL strings.Builder + params = append(params, name) + params = append(params, age) + generateSQL.WriteString("INSERT INTO users (name,age) VALUES (?,?) ON DUPLICATE KEY UPDATE age=VALUES(age) ") + + stmt := u.UnderlyingDB().Statement + result, _ = stmt.ConnPool.ExecContext(stmt.Context, generateSQL.String(), params...) // ignore_security_alert + + return +} + +// AddUser4 +// +// INSERT INTO users (name,age) VALUES (@name,@age) ON DUPLICATE KEY UPDATE age=VALUES(age) +func (u userDo) AddUser4(name string, age int) (row *sql.Row) { + var params []interface{} + + var generateSQL strings.Builder + params = append(params, name) + params = append(params, age) + generateSQL.WriteString("INSERT INTO users (name,age) VALUES (?,?) ON DUPLICATE KEY UPDATE age=VALUES(age) ") + + row = u.UnderlyingDB().Raw(generateSQL.String(), params...).Row() // ignore_security_alert + + return +} + +// AddUser5 +// +// INSERT INTO users (name,age) VALUES (@name,@age) ON DUPLICATE KEY UPDATE age=VALUES(age) +func (u userDo) AddUser5(name string, age int) (rows *sql.Rows) { + var params []interface{} + + var generateSQL strings.Builder + params = append(params, name) + params = append(params, age) + generateSQL.WriteString("INSERT INTO users (name,age) VALUES (?,?) ON DUPLICATE KEY UPDATE age=VALUES(age) ") + + rows, _ = u.UnderlyingDB().Raw(generateSQL.String(), params...).Rows() // ignore_security_alert + + return +} + +// AddUser6 +// +// INSERT INTO users (name,age) VALUES (@name,@age) ON DUPLICATE KEY UPDATE age=VALUES(age) +func (u userDo) AddUser6(name string, age int) (rows *sql.Rows, err error) { + var params []interface{} + + var generateSQL strings.Builder + params = append(params, name) + params = append(params, age) + generateSQL.WriteString("INSERT INTO users (name,age) VALUES (?,?) ON DUPLICATE KEY UPDATE age=VALUES(age) ") + + rows, err = u.UnderlyingDB().Raw(generateSQL.String(), params...).Rows() // ignore_security_alert + + return +} + +// FindByID +// +// select * from users where id=@id +func (u userDo) FindByID(id int) (result model.User) { + var params []interface{} + + var generateSQL strings.Builder + params = append(params, id) + generateSQL.WriteString("select * from users where id=? ") + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Take(&result) // ignore_security_alert + _ = executeSQL + + return +} + +// LikeSearch +// +// SELECT * FROM @@table where name LIKE concat('%',@name,'%') +func (u userDo) LikeSearch(name string) (result *model.User) { + var params []interface{} + + var generateSQL strings.Builder + params = append(params, name) + generateSQL.WriteString("SELECT * FROM users where name LIKE concat('%',?,'%') ") + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Take(&result) // ignore_security_alert + _ = executeSQL + + return +} + +// InSearch +// +// select * from @@table where name in @names +func (u userDo) InSearch(names []string) (result []*model.User) { + var params []interface{} + + var generateSQL strings.Builder + params = append(params, names) + generateSQL.WriteString("select * from users where name in ? ") + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Find(&result) // ignore_security_alert + _ = executeSQL + + return +} + +// ColumnSearch +// +// select * from @@table where @@name in @names +func (u userDo) ColumnSearch(name string, names []string) (result []*model.User) { + var params []interface{} + + var generateSQL strings.Builder + params = append(params, names) + generateSQL.WriteString("select * from users where " + u.Quote(name) + " in ? ") + + var executeSQL *gorm.DB + executeSQL = u.UnderlyingDB().Raw(generateSQL.String(), params...).Find(&result) // ignore_security_alert + _ = executeSQL + + return +} diff --git a/tests/generate_test.go b/tests/generate_test.go index 9b1bec22..2309808e 100644 --- a/tests/generate_test.go +++ b/tests/generate_test.go @@ -118,6 +118,21 @@ var generateCase = map[string]func(dir string) *gen.Generator{ g.ApplyBasic(g.GenerateModelAs("users", DB.Config.NamingStrategy.SchemaName("users"), gen.WithMethod(diy_method.TestForWithMethod{}))) return g }, + generateDirPrefix + "dal_7": func(dir string) *gen.Generator { + g := gen.NewGenerator(gen.Config{ + OutPath: dir + "/query", + Mode: gen.WithDefaultQuery | gen.WithGeneric, + + FieldNullable: true, + FieldCoverable: true, + FieldWithIndexTag: true, + }) + g.UseDB(DB) + g.WithJSONTagNameStrategy(func(c string) string { return "-" }) + g.ApplyInterface(func(testIF diy_method.TestIF, testFor diy_method.TestFor, method diy_method.InsertMethod, selectMethod diy_method.SelectMethod) { + }, g.GenerateModel("users")) + return g + }, } func TestGenerate(t *testing.T) {