From 647318905518fef945d719586d4959c32ba03360 Mon Sep 17 00:00:00 2001 From: qqxhb <1252905006@qq.com> Date: Tue, 18 Apr 2023 15:07:17 +0800 Subject: [PATCH 01/18] feat: generics field --- field/bool.go | 23 +- field/export.go | 36 +- field/expr.go | 25 +- field/field.go | 77 +-- field/float.go | 236 +------ field/function.go | 8 +- field/generics.go | 243 +++++++ field/int.go | 1512 +------------------------------------------ field/serializer.go | 6 +- field/string.go | 253 +------- field/time.go | 104 +-- 11 files changed, 354 insertions(+), 2169 deletions(-) create mode 100644 field/generics.go diff --git a/field/bool.go b/field/bool.go index 8fd1206b..40b68918 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..22df37c0 100644 --- a/field/export.go +++ b/field/export.go @@ -1,8 +1,10 @@ package field import ( + "database/sql/driver" "fmt" "strings" + "time" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -29,7 +31,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: GenericsField[driver.Valuer]{expr{col: toColumn(table, column, opts...)}}} } // NewSerializer create new field2 @@ -46,90 +48,90 @@ func NewAsterisk(table string, opts ...Option) Asterisk { // NewInt create new Int func NewInt(table, column string, opts ...Option) Int { - return Int{expr: expr{col: toColumn(table, column, opts...)}} + return Int{GenericsInt[int]{GenericsField: GenericsField[int]{expr{col: toColumn(table, column, opts...)}}}} } // NewInt8 create new Int8 func NewInt8(table, column string, opts ...Option) Int8 { - return Int8{expr: expr{col: toColumn(table, column, opts...)}} + return Int8{GenericsInt[int8]{GenericsField: GenericsField[int8]{expr{col: toColumn(table, column, opts...)}}}} } // NewInt16 ... func NewInt16(table, column string, opts ...Option) Int16 { - return Int16{expr: expr{col: toColumn(table, column, opts...)}} + return Int16{GenericsInt[int16]{GenericsField: GenericsField[int16]{expr{col: toColumn(table, column, opts...)}}}} } // NewInt32 ... func NewInt32(table, column string, opts ...Option) Int32 { - return Int32{expr: expr{col: toColumn(table, column, opts...)}} + return Int32{GenericsInt[int32]{GenericsField: GenericsField[int32]{expr{col: toColumn(table, column, opts...)}}}} } // NewInt64 ... func NewInt64(table, column string, opts ...Option) Int64 { - return Int64{expr: expr{col: toColumn(table, column, opts...)}} + return Int64{GenericsInt[int64]{GenericsField: GenericsField[int64]{expr{col: toColumn(table, column, opts...)}}}} } // NewUint ... func NewUint(table, column string, opts ...Option) Uint { - return Uint{expr: expr{col: toColumn(table, column, opts...)}} + return Uint{GenericsInt[uint]{GenericsField: GenericsField[uint]{expr{col: toColumn(table, column, opts...)}}}} } // NewUint8 ... func NewUint8(table, column string, opts ...Option) Uint8 { - return Uint8{expr: expr{col: toColumn(table, column, opts...)}} + return Uint8{GenericsInt[uint8]{GenericsField: GenericsField[uint8]{expr{col: toColumn(table, column, opts...)}}}} } // NewUint16 ... func NewUint16(table, column string, opts ...Option) Uint16 { - return Uint16{expr: expr{col: toColumn(table, column, opts...)}} + return Uint16{GenericsInt[uint16]{GenericsField: GenericsField[uint16]{expr{col: toColumn(table, column, opts...)}}}} } // NewUint32 ... func NewUint32(table, column string, opts ...Option) Uint32 { - return Uint32{expr: expr{col: toColumn(table, column, opts...)}} + return Uint32{GenericsInt[uint32]{GenericsField: GenericsField[uint32]{expr{col: toColumn(table, column, opts...)}}}} } // NewUint64 ... func NewUint64(table, column string, opts ...Option) Uint64 { - return Uint64{expr: expr{col: toColumn(table, column, opts...)}} + return Uint64{GenericsInt[uint64]{GenericsField: GenericsField[uint64]{expr{col: toColumn(table, column, opts...)}}}} } // ======================== float ======================= // NewFloat32 ... func NewFloat32(table, column string, opts ...Option) Float32 { - return Float32{expr: expr{col: toColumn(table, column, opts...)}} + return Float32{GenericsInt[float32]{GenericsField: GenericsField[float32]{expr{col: toColumn(table, column, opts...)}}}} } // NewFloat64 ... func NewFloat64(table, column string, opts ...Option) Float64 { - return Float64{expr: expr{col: toColumn(table, column, opts...)}} + return Float64{GenericsInt[float64]{GenericsField: GenericsField[float64]{expr{col: toColumn(table, column, opts...)}}}} } // ======================== string ======================= // NewString ... func NewString(table, column string, opts ...Option) String { - return String{expr: expr{col: toColumn(table, column, opts...)}} + return String{GenericsString[string]{GenericsField: GenericsField[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 Bytes{GenericsString[[]byte]{GenericsField: GenericsField[[]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/expr.go b/field/expr.go index 6f54e35a..a75e1be0 100644 --- a/field/expr.go +++ b/field/expr.go @@ -1,6 +1,7 @@ package field import ( + "database/sql/driver" "fmt" "strings" "time" @@ -167,27 +168,27 @@ func (e expr) IsNotNull() Expr { } func (e expr) Count() Int { - return Int{e.setE(clause.Expr{SQL: "COUNT(?)", Vars: []interface{}{e.RawExpr()}})} + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[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()}})} + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[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()}})} + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[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()}})} + return Float64{GenericsInt: GenericsInt[float64]{GenericsField: GenericsField[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()}})} + return Float64{GenericsInt: GenericsInt[float64]{GenericsField: GenericsField[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()}})} + return Float64{GenericsInt: GenericsInt[float64]{GenericsField: GenericsField[float64]{e.setE(clause.Expr{SQL: "AVG(?)", Vars: []interface{}{e.RawExpr()}})}}} } func (e expr) Null() AssignExpr { @@ -229,19 +230,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 { @@ -251,10 +252,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 6b11efb5..8240a913 100644 --- a/field/field.go +++ b/field/field.go @@ -1,79 +1,8 @@ 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...)}} -} - -// 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) -} - -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 struct { + GenericsField[driver.Valuer] } diff --git a/field/float.go b/field/float.go index 34c8a3ab..7cbe2fb2 100644 --- a/field/float.go +++ b/field/float.go @@ -1,245 +1,21 @@ 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)} +type Float64 struct { + GenericsInt[float64] } // 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) -} - -func (field Float64) toSlice(values ...float64) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{field.floor()}}} } // 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)} +type Float32 struct { + GenericsInt[float32] } // 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) -} - -func (field Float32) toSlice(values ...float32) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{field.floor()}}} } diff --git a/field/function.go b/field/function.go index 5905852d..bbf88918 100644 --- a/field/function.go +++ b/field/function.go @@ -14,15 +14,15 @@ type function struct{} // UnixTimestamp same as UNIX_TIMESTAMP([date]) func (f *function) UnixTimestamp(date ...string) Uint64 { if len(date) > 0 { - return Uint64{expr{e: clause.Expr{SQL: "UNIX_TIMESTAMP(?)", Vars: []interface{}{date[0]}}}} + return Uint64{GenericsInt: GenericsInt[uint64]{GenericsField: GenericsField[uint64]{expr{e: clause.Expr{SQL: "UNIX_TIMESTAMP(?)", Vars: []interface{}{date[0]}}}}}} } - return Uint64{expr{e: clause.Expr{SQL: "UNIX_TIMESTAMP()"}}} + return Uint64{GenericsInt: GenericsInt[uint64]{GenericsField: GenericsField[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{GenericsString: GenericsString[string]{GenericsField: 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{GenericsString: GenericsString[string]{GenericsField: GenericsField[string]{expr{e: clause.Expr{SQL: "FROM_UNIXTIME(?)", Vars: []interface{}{date}}}}}} } diff --git a/field/generics.go b/field/generics.go new file mode 100644 index 00000000..3119380b --- /dev/null +++ b/field/generics.go @@ -0,0 +1,243 @@ +package field + +import ( + "database/sql/driver" + "fmt" + + "gorm.io/gorm/clause" +) + +// ScanValuer interface for Field +type ScanValuer interface { + Scan(src interface{}) error // sql.Scanner + Value() (driver.Value, error) // driver.Valuer +} + +// GenericsField a generics field struct +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...)}} +} + +// 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) +} + +func (field GenericsField[T]) toSlice(values ...T) []interface{} { + slice := make([]interface{}, len(values)) + for i, v := range values { + slice[i] = v + } + return slice +} + +// GenericsInt int type field +type GenericsInt[T any] struct { + GenericsField[T] +} + +// NotIn ... +func (field GenericsInt[T]) NotIn(values ...T) Expr { + return expr{e: clause.Not(field.In(values...).expression())} +} + +// Between ... +func (field GenericsInt[T]) Between(left T, right T) Expr { + return field.between([]interface{}{left, right}) +} + +// NotBetween ... +func (field GenericsInt[T]) NotBetween(left T, right T) Expr { + return Not(field.Between(left, right)) +} + +// Add ... +func (field GenericsInt[T]) Add(value T) GenericsInt[T] { + return GenericsInt[T]{GenericsField: GenericsField[T]{field.add(value)}} +} + +// Sub ... +func (field GenericsInt[T]) Sub(value T) GenericsInt[T] { + return GenericsInt[T]{GenericsField: GenericsField[T]{field.sub(value)}} +} + +// Mul ... +func (field GenericsInt[T]) Mul(value T) GenericsInt[T] { + return GenericsInt[T]{GenericsField: GenericsField[T]{field.mul(value)}} +} + +// Div ... +func (field GenericsInt[T]) Div(value T) GenericsInt[T] { + return GenericsInt[T]{GenericsField: GenericsField[T]{field.div(value)}} +} + +// Mod ... +func (field GenericsInt[T]) Mod(value T) GenericsInt[T] { + return GenericsInt[T]{GenericsField: GenericsField[T]{field.mod(value)}} +} + +// FloorDiv ... +func (field GenericsInt[T]) FloorDiv(value T) GenericsInt[T] { + return GenericsInt[T]{GenericsField: GenericsField[T]{field.floorDiv(value)}} +} + +// RightShift ... +func (field GenericsInt[T]) RightShift(value T) GenericsInt[T] { + return GenericsInt[T]{GenericsField: GenericsField[T]{field.rightShift(value)}} +} + +// LeftShift ... +func (field GenericsInt[T]) LeftShift(value T) GenericsInt[T] { + return GenericsInt[T]{GenericsField: GenericsField[T]{field.leftShift(value)}} +} + +// BitXor ... +func (field GenericsInt[T]) BitXor(value T) GenericsInt[T] { + return GenericsInt[T]{GenericsField: GenericsField[T]{field.bitXor(value)}} +} + +// BitAnd ... +func (field GenericsInt[T]) BitAnd(value T) GenericsInt[T] { + return GenericsInt[T]{GenericsField: GenericsField[T]{field.bitAnd(value)}} +} + +// BitOr ... +func (field GenericsInt[T]) BitOr(value T) GenericsInt[T] { + return GenericsInt[T]{GenericsField: GenericsField[T]{field.bitOr(value)}} +} + +// BitFlip ... +func (field GenericsInt[T]) BitFlip() GenericsInt[T] { + return GenericsInt[T]{GenericsField: GenericsField[T]{field.bitFlip()}} +} + +// Zero set zero value +func (field GenericsInt[T]) Zero() AssignExpr { + return field.value(0) +} + +// GenericsString string type field +type GenericsString[T any] struct { + GenericsField[T] +} + +// Between ... +func (field GenericsString[T]) Between(left T, right T) Expr { + return field.between([]interface{}{left, right}) +} + +// NotBetween ... +func (field GenericsString[T]) NotBetween(left T, right T) Expr { + return Not(field.Between(left, right)) +} + +// NotIn ... +func (field GenericsString[T]) NotIn(values ...T) Expr { + return expr{e: clause.Not(field.In(values...).expression())} +} + +// Regexp ... +func (field GenericsString[T]) Regexp(value string) Expr { + return field.regexp(value) +} + +// NotRegxp ... +func (field GenericsString[T]) NotRegxp(value string) Expr { + return expr{e: clause.Not(field.Regexp(value).expression())} +} + +// Zero ... +func (field GenericsString[T]) Zero() AssignExpr { + return field.value("") +} + +// FindInSet equal to FIND_IN_SET(field_name, input_string_list) +func (field GenericsString[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 GenericsString[T]) FindInSetWith(target string) Expr { + return expr{e: clause.Expr{SQL: "FIND_IN_SET(?,?)", Vars: []interface{}{target, field.RawExpr()}}} +} + +// Replace ... +func (field GenericsString[T]) Replace(from, to string) GenericsString[T] { + return GenericsString[T]{GenericsField: GenericsField[T]{expr{e: clause.Expr{SQL: "REPLACE(?,?,?)", Vars: []interface{}{field.RawExpr(), from, to}}}}} +} + +// Concat ... +func (field GenericsString[T]) Concat(before, after string) GenericsString[T] { + switch { + case before != "" && after != "": + return GenericsString[T]{GenericsField: GenericsField[T]{expr{e: clause.Expr{SQL: "CONCAT(?,?,?)", Vars: []interface{}{before, field.RawExpr(), after}}}}} + case before != "": + return GenericsString[T]{GenericsField: GenericsField[T]{expr{e: clause.Expr{SQL: "CONCAT(?,?)", Vars: []interface{}{before, field.RawExpr()}}}}} + case after != "": + return GenericsString[T]{GenericsField: GenericsField[T]{expr{e: clause.Expr{SQL: "CONCAT(?,?)", Vars: []interface{}{field.RawExpr(), after}}}}} + default: + return field + } +} + +// SubstringIndex SUBSTRING_INDEX +// https://dev.mysql.com/doc/refman/8.0/en/functions.html#function_substring-index +func (field GenericsString[T]) SubstringIndex(delim string, count int) GenericsString[T] { + return GenericsString[T]{GenericsField: GenericsField[T]{expr{e: clause.Expr{ + SQL: fmt.Sprintf("SUBSTRING_INDEX(?,%q,%d)", delim, count), + Vars: []interface{}{field.RawExpr()}, + }}}} +} diff --git a/field/int.go b/field/int.go index 8ecf6a29..db2c39be 100644 --- a/field/int.go +++ b/field/int.go @@ -1,1515 +1,51 @@ 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) -} - -func (field Int) toSlice(values ...int) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice +type Int struct { + GenericsInt[int] } // 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) -} - -func (field Int8) toSlice(values ...int8) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice +type Int8 struct { + GenericsInt[int8] } // 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) -} - -func (field Int16) toSlice(values ...int16) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice +type Int16 struct { + GenericsInt[int16] } // 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) -} - -func (field Int32) toSlice(values ...int32) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice +type Int32 struct { + GenericsInt[int32] } // 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}} +type Int64 struct { + GenericsInt[int64] } -// 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)} +// Uint uint type field +type Uint struct { + GenericsInt[uint] } -// Sub ... -func (field Int64) Sub(value int64) Int64 { - return Int64{field.sub(value)} +// Uint8 uint8 type field +type Uint8 struct { + GenericsInt[uint8] } -// Mul ... -func (field Int64) Mul(value int64) Int64 { - return Int64{field.mul(value)} +// Uint16 uint16 type field +type Uint16 struct { + GenericsInt[uint16] } -// 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) -} - -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) -} - -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) -} - -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) -} - -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) -} - -func (field Uint32) toSlice(values ...uint32) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice +// Uint32 uint32 type field +type Uint32 struct { + GenericsInt[uint32] } // 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) -} - -func (field Uint64) toSlice(values ...uint64) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice +type Uint64 struct { + GenericsInt[uint64] } diff --git a/field/serializer.go b/field/serializer.go index 8727bad8..b8c7e424 100644 --- a/field/serializer.go +++ b/field/serializer.go @@ -2,9 +2,11 @@ package field import ( "context" + "database/sql/driver" + "reflect" + "gorm.io/gorm/clause" "gorm.io/gorm/schema" - "reflect" "gorm.io/gorm" ) @@ -73,7 +75,7 @@ func (field Serializer) Value(value schema.SerializerValuerInterface) AssignExpr // Sum ... func (field Serializer) Sum() Field { - return Field{field.sum()} + return Field{GenericsField: GenericsField[driver.Valuer]{field.sum()}} } // IfNull ... diff --git a/field/string.go b/field/string.go index 4dace91e..20f6c859 100644 --- a/field/string.go +++ b/field/string.go @@ -1,256 +1,11 @@ package field -import ( - "fmt" - - "gorm.io/gorm/clause" -) - // String string type field -type String Field - -// 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}} -} - -// Gte greater or equal to -func (field String) Gte(value string) Expr { - return expr{e: clause.Gte{Column: field.RawExpr(), Value: value}} -} - -// Lt less than -func (field String) Lt(value string) Expr { - return expr{e: clause.Lt{Column: field.RawExpr(), Value: value}} -} - -// Lte less or equal to -func (field String) Lte(value string) Expr { - return expr{e: clause.Lte{Column: field.RawExpr(), Value: value}} -} - -// Between ... -func (field String) Between(left string, right string) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field String) NotBetween(left string, right string) 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 { - 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 { - return field.regexp(value) -} - -// NotRegxp ... -func (field String) NotRegxp(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 { - 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 { - 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 { - 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}}}} -} - -// Concat ... -func (field String) Concat(before, after string) String { - switch { - case before != "" && after != "": - return String{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()}}}} - case after != "": - return String{expr{e: clause.Expr{SQL: "CONCAT(?,?)", Vars: []interface{}{field.RawExpr(), after}}}} - default: - return field - } -} - -// 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()}, - }}} -} - -func (field String) toSlice(values []string) []interface{} { - slice := make([]interface{}, len(values)) - for i, v := range values { - slice[i] = v - } - return slice +type String struct { + GenericsString[string] } // 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}}} -} - -// 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()}}} -} - -// 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 +type Bytes struct { + GenericsString[[]byte] } diff --git a/field/time.go b/field/time.go index ec86f0cd..128a59be 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,114 @@ 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}}}} + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[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 String{GenericsString: GenericsString[string]{GenericsField: GenericsField[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 String{GenericsString: GenericsString[string]{GenericsField: GenericsField[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 String{GenericsString: GenericsString[string]{GenericsField: GenericsField[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()}}}} + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[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()}}}} + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[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()}}}} + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[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()}}}} + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[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()}}}} + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[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()}}}} + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[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()}}}} + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[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()}}}} + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[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()}}}} + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[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()}}}} + return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[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 -} From b1d12afe537d24de52ceb1ea757212bdd2c46dfa Mon Sep 17 00:00:00 2001 From: qqxhb <1252905006@qq.com> Date: Wed, 26 Apr 2023 21:35:15 +0800 Subject: [PATCH 02/18] feat: generics dao --- generics.go | 332 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 generics.go diff --git a/generics.go b/generics.go new file mode 100644 index 00000000..053e15d4 --- /dev/null +++ b/generics.go @@ -0,0 +1,332 @@ +package gen + +import ( + "context" + + "gorm.io/gen/field" + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + "gorm.io/plugin/dbresolver" +) + +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) T + 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) + Scan(result interface{}) (err error) + Returning(value interface{}, columns ...string) T + UnderlyingDB() *gorm.DB + schema.Tabler + UseDB(db *gorm.DB, opts ...DOOption) + UseModel(model interface{}) + UseTable(tableName string) + Alias() string + ReplaceConnPool(pool gorm.ConnPool) + SetDo(T IGenericsDo[T, E]) T +} + +func NewGenericsDo[T IGenericsDo[T, E], E any](realDo T) IGenericsDo[T, E] { + return &genericsDo[T, E]{realDo: realDo} +} + +type genericsDo[T IGenericsDo[T, E], E any] struct { + DO + realDo T +} + +func (b genericsDo[T, E]) Debug() T { + return b.withDO(b.DO.Debug()) +} +func (b genericsDo[T, E]) As(alias string) T { + return b.withDO(b.DO.As(alias)) +} + +func (b genericsDo[T, E]) WithContext(ctx context.Context) T { + return b.withDO(b.DO.WithContext(ctx)) +} + +func (b genericsDo[T, E]) ReadDB() T { + return b.Clauses(dbresolver.Read) +} + +func (b genericsDo[T, E]) WriteDB() T { + return b.Clauses(dbresolver.Write) +} + +func (b genericsDo[T, E]) Session(config *gorm.Session) T { + return b.withDO(b.DO.Session(config)) +} + +func (b genericsDo[T, E]) Clauses(conds ...clause.Expression) T { + return b.withDO(b.DO.Clauses(conds...)) +} + +func (b genericsDo[T, E]) Returning(value interface{}, columns ...string) T { + return b.withDO(b.DO.Returning(value, columns...)) +} + +func (b genericsDo[T, E]) Not(conds ...Condition) T { + return b.withDO(b.DO.Not(conds...)) +} + +func (b genericsDo[T, E]) Or(conds ...Condition) T { + return b.withDO(b.DO.Or(conds...)) +} + +func (b genericsDo[T, E]) Select(conds ...field.Expr) T { + return b.withDO(b.DO.Select(conds...)) +} + +func (b genericsDo[T, E]) Where(conds ...Condition) T { + return b.withDO(b.DO.Where(conds...)) +} + +func (b genericsDo[T, E]) Exists(subquery interface{ UnderlyingDB() *gorm.DB }) T { + return b.Where(field.CompareSubQuery(field.ExistsOp, nil, subquery.UnderlyingDB())) +} + +func (b genericsDo[T, E]) Order(conds ...field.Expr) T { + return b.withDO(b.DO.Order(conds...)) +} + +func (b genericsDo[T, E]) Distinct(cols ...field.Expr) T { + return b.withDO(b.DO.Distinct(cols...)) +} + +func (b genericsDo[T, E]) Omit(cols ...field.Expr) T { + return b.withDO(b.DO.Omit(cols...)) +} + +func (b genericsDo[T, E]) Join(table schema.Tabler, on ...field.Expr) T { + return b.withDO(b.DO.Join(table, on...)) +} + +func (b genericsDo[T, E]) LeftJoin(table schema.Tabler, on ...field.Expr) T { + return b.withDO(b.DO.LeftJoin(table, on...)) +} + +func (b genericsDo[T, E]) RightJoin(table schema.Tabler, on ...field.Expr) T { + return b.withDO(b.DO.RightJoin(table, on...)) +} + +func (b genericsDo[T, E]) Group(cols ...field.Expr) T { + return b.withDO(b.DO.Group(cols...)) +} + +func (b genericsDo[T, E]) Having(conds ...Condition) T { + return b.withDO(b.DO.Having(conds...)) +} + +func (b genericsDo[T, E]) Limit(limit int) T { + return b.withDO(b.DO.Limit(limit)) +} + +func (b genericsDo[T, E]) Offset(offset int) T { + return b.withDO(b.DO.Offset(offset)) +} + +func (b genericsDo[T, E]) Scopes(funcs ...func(Dao) Dao) T { + return b.withDO(b.DO.Scopes(funcs...)) +} + +func (b genericsDo[T, E]) Unscoped() T { + return b.withDO(b.DO.Unscoped()) +} + +func (b genericsDo[T, E]) Create(values ...E) error { + if len(values) == 0 { + return nil + } + return b.DO.Create(values) +} + +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) +} + +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 + } +} + +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 + } +} + +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 + } +} + +func (b genericsDo[T, E]) Find() ([]E, error) { + result, err := b.DO.Find() + return result.([]E), err +} + +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 +} + +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) +} + +func (b genericsDo[T, E]) Attrs(attrs ...field.AssignExpr) T { + return b.withDO(b.DO.Attrs(attrs...)) +} + +func (b genericsDo[T, E]) Assign(attrs ...field.AssignExpr) T { + return b.withDO(b.DO.Assign(attrs...)) +} + +func (b genericsDo[T, E]) Joins(fields ...field.RelationField) T { + for _, _f := range fields { + b.realDo = b.withDO(b.DO.Joins(_f)) + } + return b.realDo +} + +func (b genericsDo[T, E]) Preload(fields ...field.RelationField) T { + for _, _f := range fields { + b.realDo = b.withDO(b.DO.Preload(_f)) + } + return b.realDo +} + +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 + } +} + +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 + } +} + +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 +} + +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 +} + +func (b genericsDo[T, E]) Scan(result interface{}) (err error) { + return b.DO.Scan(result) +} + +func (b genericsDo[T, E]) Delete(models ...E) (result ResultInfo, err error) { + return b.DO.Delete(models) +} + +func (b genericsDo[T, E]) SetDo(do IGenericsDo[T, E]) T { + return b.realDo.SetDo(do) +} + +func (b genericsDo[T, E]) withDO(do Dao) T { + b.DO = *do.(*DO) + return b.SetDo(&b) +} From 2b5819fffc83153f7fbd5a238949a01a0b497bcd Mon Sep 17 00:00:00 2001 From: qqxhb <1252905006@qq.com> Date: Sat, 27 Jan 2024 15:46:23 +0800 Subject: [PATCH 03/18] feat: generics --- generics.go | 124 +++++++++++++++++++++++----------------------------- 1 file changed, 54 insertions(+), 70 deletions(-) diff --git a/generics.go b/generics.go index 053e15d4..690f14a3 100644 --- a/generics.go +++ b/generics.go @@ -18,7 +18,6 @@ type IGenericsDo[T any, E any] interface { ReplaceDB(db *gorm.DB) ReadDB() T WriteDB() T - As(alias string) T Session(config *gorm.Session) T Columns(cols ...field.Expr) Columns Clauses(conds ...clause.Expression) T @@ -69,143 +68,131 @@ type IGenericsDo[T any, E any] interface { Returning(value interface{}, columns ...string) T UnderlyingDB() *gorm.DB schema.Tabler - UseDB(db *gorm.DB, opts ...DOOption) - UseModel(model interface{}) - UseTable(tableName string) - Alias() string - ReplaceConnPool(pool gorm.ConnPool) - SetDo(T IGenericsDo[T, E]) T + GetInstance(do Dao) T } -func NewGenericsDo[T IGenericsDo[T, E], E any](realDo T) IGenericsDo[T, E] { - return &genericsDo[T, E]{realDo: realDo} -} - -type genericsDo[T IGenericsDo[T, E], E any] struct { +type GenericsDo[T IGenericsDo[T, E], E any] struct { DO - realDo T + RealDO T } -func (b genericsDo[T, E]) Debug() T { +func (b GenericsDo[T, E]) Debug() T { return b.withDO(b.DO.Debug()) } -func (b genericsDo[T, E]) As(alias string) T { - return b.withDO(b.DO.As(alias)) -} -func (b genericsDo[T, E]) WithContext(ctx context.Context) T { +func (b GenericsDo[T, E]) WithContext(ctx context.Context) T { return b.withDO(b.DO.WithContext(ctx)) } -func (b genericsDo[T, E]) ReadDB() T { +func (b GenericsDo[T, E]) ReadDB() T { return b.Clauses(dbresolver.Read) } -func (b genericsDo[T, E]) WriteDB() T { +func (b GenericsDo[T, E]) WriteDB() T { return b.Clauses(dbresolver.Write) } -func (b genericsDo[T, E]) Session(config *gorm.Session) T { +func (b GenericsDo[T, E]) Session(config *gorm.Session) T { return b.withDO(b.DO.Session(config)) } -func (b genericsDo[T, E]) Clauses(conds ...clause.Expression) T { +func (b GenericsDo[T, E]) Clauses(conds ...clause.Expression) T { return b.withDO(b.DO.Clauses(conds...)) } -func (b genericsDo[T, E]) Returning(value interface{}, columns ...string) T { +func (b GenericsDo[T, E]) Returning(value interface{}, columns ...string) T { return b.withDO(b.DO.Returning(value, columns...)) } -func (b genericsDo[T, E]) Not(conds ...Condition) T { +func (b GenericsDo[T, E]) Not(conds ...Condition) T { return b.withDO(b.DO.Not(conds...)) } -func (b genericsDo[T, E]) Or(conds ...Condition) T { +func (b GenericsDo[T, E]) Or(conds ...Condition) T { return b.withDO(b.DO.Or(conds...)) } -func (b genericsDo[T, E]) Select(conds ...field.Expr) T { +func (b GenericsDo[T, E]) Select(conds ...field.Expr) T { return b.withDO(b.DO.Select(conds...)) } -func (b genericsDo[T, E]) Where(conds ...Condition) T { +func (b GenericsDo[T, E]) Where(conds ...Condition) T { return b.withDO(b.DO.Where(conds...)) } -func (b genericsDo[T, E]) Exists(subquery interface{ UnderlyingDB() *gorm.DB }) T { +func (b GenericsDo[T, E]) Exists(subquery interface{ UnderlyingDB() *gorm.DB }) T { return b.Where(field.CompareSubQuery(field.ExistsOp, nil, subquery.UnderlyingDB())) } -func (b genericsDo[T, E]) Order(conds ...field.Expr) T { +func (b GenericsDo[T, E]) Order(conds ...field.Expr) T { return b.withDO(b.DO.Order(conds...)) } -func (b genericsDo[T, E]) Distinct(cols ...field.Expr) T { +func (b GenericsDo[T, E]) Distinct(cols ...field.Expr) T { return b.withDO(b.DO.Distinct(cols...)) } -func (b genericsDo[T, E]) Omit(cols ...field.Expr) T { +func (b GenericsDo[T, E]) Omit(cols ...field.Expr) T { return b.withDO(b.DO.Omit(cols...)) } -func (b genericsDo[T, E]) Join(table schema.Tabler, on ...field.Expr) T { +func (b GenericsDo[T, E]) Join(table schema.Tabler, on ...field.Expr) T { return b.withDO(b.DO.Join(table, on...)) } -func (b genericsDo[T, E]) LeftJoin(table schema.Tabler, on ...field.Expr) T { +func (b GenericsDo[T, E]) LeftJoin(table schema.Tabler, on ...field.Expr) T { return b.withDO(b.DO.LeftJoin(table, on...)) } -func (b genericsDo[T, E]) RightJoin(table schema.Tabler, on ...field.Expr) T { +func (b GenericsDo[T, E]) RightJoin(table schema.Tabler, on ...field.Expr) T { return b.withDO(b.DO.RightJoin(table, on...)) } -func (b genericsDo[T, E]) Group(cols ...field.Expr) T { +func (b GenericsDo[T, E]) Group(cols ...field.Expr) T { return b.withDO(b.DO.Group(cols...)) } -func (b genericsDo[T, E]) Having(conds ...Condition) T { +func (b GenericsDo[T, E]) Having(conds ...Condition) T { return b.withDO(b.DO.Having(conds...)) } -func (b genericsDo[T, E]) Limit(limit int) T { +func (b GenericsDo[T, E]) Limit(limit int) T { return b.withDO(b.DO.Limit(limit)) } -func (b genericsDo[T, E]) Offset(offset int) T { +func (b GenericsDo[T, E]) Offset(offset int) T { return b.withDO(b.DO.Offset(offset)) } -func (b genericsDo[T, E]) Scopes(funcs ...func(Dao) Dao) T { +func (b GenericsDo[T, E]) Scopes(funcs ...func(Dao) Dao) T { return b.withDO(b.DO.Scopes(funcs...)) } -func (b genericsDo[T, E]) Unscoped() T { +func (b GenericsDo[T, E]) Unscoped() T { return b.withDO(b.DO.Unscoped()) } -func (b genericsDo[T, E]) Create(values ...E) error { +func (b GenericsDo[T, E]) Create(values ...E) error { if len(values) == 0 { return nil } return b.DO.Create(values) } -func (b genericsDo[T, E]) CreateInBatches(values []E, batchSize int) error { +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 { +func (b GenericsDo[T, E]) Save(values ...E) error { if len(values) == 0 { return nil } return b.DO.Save(values) } -func (b genericsDo[T, E]) First() (E, error) { +func (b GenericsDo[T, E]) First() (E, error) { var e E if result, err := b.DO.First(); err != nil { return e, err @@ -214,7 +201,7 @@ func (b genericsDo[T, E]) First() (E, error) { } } -func (b genericsDo[T, E]) Take() (E, error) { +func (b GenericsDo[T, E]) Take() (E, error) { var e E if result, err := b.DO.Take(); err != nil { return e, err @@ -223,7 +210,7 @@ func (b genericsDo[T, E]) Take() (E, error) { } } -func (b genericsDo[T, E]) Last() (E, error) { +func (b GenericsDo[T, E]) Last() (E, error) { var e E if result, err := b.DO.Last(); err != nil { return e, err @@ -232,12 +219,12 @@ func (b genericsDo[T, E]) Last() (E, error) { } } -func (b genericsDo[T, E]) Find() ([]E, error) { +func (b GenericsDo[T, E]) Find() ([]E, error) { result, err := b.DO.Find() return result.([]E), err } -func (b genericsDo[T, E]) FindInBatch(batchSize int, fc func(tx Dao, batch int) error) (results []E, err error) { +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...) }() @@ -246,33 +233,35 @@ func (b genericsDo[T, E]) FindInBatch(batchSize int, fc func(tx Dao, batch int) return results, err } -func (b genericsDo[T, E]) FindInBatches(result *[]E, batchSize int, fc func(tx Dao, batch int) error) error { +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) } -func (b genericsDo[T, E]) Attrs(attrs ...field.AssignExpr) T { +func (b GenericsDo[T, E]) Attrs(attrs ...field.AssignExpr) T { return b.withDO(b.DO.Attrs(attrs...)) } -func (b genericsDo[T, E]) Assign(attrs ...field.AssignExpr) T { +func (b GenericsDo[T, E]) Assign(attrs ...field.AssignExpr) T { return b.withDO(b.DO.Assign(attrs...)) } -func (b genericsDo[T, E]) Joins(fields ...field.RelationField) T { +func (b GenericsDo[T, E]) Joins(fields ...field.RelationField) T { + var do Dao = &b.DO for _, _f := range fields { - b.realDo = b.withDO(b.DO.Joins(_f)) + do = do.Joins(_f) } - return b.realDo + return b.withDO(do) } -func (b genericsDo[T, E]) Preload(fields ...field.RelationField) T { +func (b GenericsDo[T, E]) Preload(fields ...field.RelationField) T { + var do Dao = &b.DO for _, _f := range fields { - b.realDo = b.withDO(b.DO.Preload(_f)) + do = do.Preload(_f) } - return b.realDo + return b.withDO(do) } -func (b genericsDo[T, E]) FirstOrInit() (E, error) { +func (b GenericsDo[T, E]) FirstOrInit() (E, error) { var e E if result, err := b.DO.FirstOrInit(); err != nil { return e, err @@ -281,7 +270,7 @@ func (b genericsDo[T, E]) FirstOrInit() (E, error) { } } -func (b genericsDo[T, E]) FirstOrCreate() (E, error) { +func (b GenericsDo[T, E]) FirstOrCreate() (E, error) { var e E if result, err := b.DO.FirstOrCreate(); err != nil { return e, err @@ -290,7 +279,7 @@ func (b genericsDo[T, E]) FirstOrCreate() (E, error) { } } -func (b genericsDo[T, E]) FindByPage(offset int, limit int) (result []E, count int64, err error) { +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 @@ -305,7 +294,7 @@ func (b genericsDo[T, E]) FindByPage(offset int, limit int) (result []E, count i return } -func (b genericsDo[T, E]) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { +func (b GenericsDo[T, E]) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { count, err = b.Count() if err != nil { return @@ -314,19 +303,14 @@ func (b genericsDo[T, E]) ScanByPage(result interface{}, offset int, limit int) return } -func (b genericsDo[T, E]) Scan(result interface{}) (err error) { +func (b GenericsDo[T, E]) Scan(result interface{}) (err error) { return b.DO.Scan(result) } -func (b genericsDo[T, E]) Delete(models ...E) (result ResultInfo, err error) { +func (b GenericsDo[T, E]) Delete(models ...E) (result ResultInfo, err error) { return b.DO.Delete(models) } -func (b genericsDo[T, E]) SetDo(do IGenericsDo[T, E]) T { - return b.realDo.SetDo(do) -} - -func (b genericsDo[T, E]) withDO(do Dao) T { - b.DO = *do.(*DO) - return b.SetDo(&b) +func (b *GenericsDo[T, E]) withDO(do Dao) T { + return b.RealDO.GetInstance(do) } From 18bbcd71686b8b778cab87ffe73e06372e9bc936 Mon Sep 17 00:00:00 2001 From: qqxhb <1252905006@qq.com> Date: Sat, 27 Jan 2024 16:57:15 +0800 Subject: [PATCH 04/18] feat: generics template --- generator.go | 2 +- internal/template/method.go | 10 ++++++++++ internal/template/struct.go | 23 ++++++++++++++++------- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/generator.go b/generator.go index 6f09bf59..efb842bf 100644 --- a/generator.go +++ b/generator.go @@ -420,7 +420,7 @@ func (g *Generator) generateSingleQueryFile(data *genInfo) (err error) { } } - err = render(tmpl.CRUDMethod, &buf, data.QueryStructMeta) + err = render(tmpl.GetInstanceMethod, &buf, data.QueryStructMeta) if err != nil { return err } diff --git a/internal/template/method.go b/internal/template/method.go index 5263166e..f9cf50fc 100644 --- a/internal/template/method.go +++ b/internal/template/method.go @@ -27,6 +27,16 @@ func ({{.S}} {{.TargetStruct}}Do){{.FuncSign}}{ ` +// GetInstance method +const GetInstanceMethod = ` +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 8b83a12e..0ed61583 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 + defineGenericsMethodStruct // TableQueryStructWithContext table query struct with context TableQueryStructWithContext = createMethod + ` @@ -27,17 +27,18 @@ 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 + defineGenericsMethodStruct // TableQueryIface table query interface - TableQueryIface = defineDoInterface + TableQueryIface = defineGenericsDoInterface ) const ( createMethod = ` func new{{.ModelStructName}}(db *gorm.DB, opts ...gen.DOOption) {{.QueryStructName}} { _{{.QueryStructName}} := {{.QueryStructName}}{} - + _{{.QueryStructName}}.{{.QueryStructName}}Do.RealDO = &_{{.QueryStructName}}.{{.QueryStructName}}Do + _{{.QueryStructName}}.{{.QueryStructName}}Do.UseDB(db,opts...) _{{.QueryStructName}}.{{.QueryStructName}}Do.UseModel(&{{.StructInfo.Package}}.{{.StructInfo.Type}}{}) @@ -131,9 +132,9 @@ 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 = ` + defineMethodStruct = `type {{.QueryStructName}}Do struct { gen.DO }` + defineGenericsMethodStruct = `type {{.QueryStructName}}Do struct {gen.GenericsDo[I{{.ModelStructName}}Do, *{{.StructInfo.Package}}.{{.StructInfo.Type}}]}` + fillFieldMapMethod = ` func ({{.S}} *{{.QueryStructName}}) fillFieldMap() { {{.S}}.fieldMap = make(map[string]field.Expr, {{len .Fields}}) {{range .Fields -}} @@ -143,7 +144,15 @@ 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 { From c5fbbbc6ab27381c8c4377fd98c3bf0775d1bd44 Mon Sep 17 00:00:00 2001 From: qqxhb <1252905006@qq.com> Date: Sat, 27 Jan 2024 17:50:36 +0800 Subject: [PATCH 05/18] feat: test --- field/export.go | 32 +-- field/expr.go | 17 +- field/float.go | 4 +- field/generics.go | 12 + field/time.go | 29 +-- tests/.expect/dal_3/query/banks.gen.go | 305 +------------------------ 6 files changed, 66 insertions(+), 333 deletions(-) diff --git a/field/export.go b/field/export.go index 22df37c0..6f2ea364 100644 --- a/field/export.go +++ b/field/export.go @@ -48,90 +48,90 @@ func NewAsterisk(table string, opts ...Option) Asterisk { // NewInt create new Int func NewInt(table, column string, opts ...Option) Int { - return Int{GenericsInt[int]{GenericsField: GenericsField[int]{expr{col: toColumn(table, column, opts...)}}}} + return Int{NewGenericsInt[int](expr{col: toColumn(table, column, opts...)})} } // NewInt8 create new Int8 func NewInt8(table, column string, opts ...Option) Int8 { - return Int8{GenericsInt[int8]{GenericsField: GenericsField[int8]{expr{col: toColumn(table, column, opts...)}}}} + return Int8{NewGenericsInt[int8](expr{col: toColumn(table, column, opts...)})} } // NewInt16 ... func NewInt16(table, column string, opts ...Option) Int16 { - return Int16{GenericsInt[int16]{GenericsField: GenericsField[int16]{expr{col: toColumn(table, column, opts...)}}}} + return Int16{NewGenericsInt[int16](expr{col: toColumn(table, column, opts...)})} } // NewInt32 ... func NewInt32(table, column string, opts ...Option) Int32 { - return Int32{GenericsInt[int32]{GenericsField: GenericsField[int32]{expr{col: toColumn(table, column, opts...)}}}} + return Int32{NewGenericsInt[int32](expr{col: toColumn(table, column, opts...)})} } // NewInt64 ... func NewInt64(table, column string, opts ...Option) Int64 { - return Int64{GenericsInt[int64]{GenericsField: GenericsField[int64]{expr{col: toColumn(table, column, opts...)}}}} + return Int64{NewGenericsInt[int64](expr{col: toColumn(table, column, opts...)})} } // NewUint ... func NewUint(table, column string, opts ...Option) Uint { - return Uint{GenericsInt[uint]{GenericsField: GenericsField[uint]{expr{col: toColumn(table, column, opts...)}}}} + return Uint{NewGenericsInt[uint](expr{col: toColumn(table, column, opts...)})} } // NewUint8 ... func NewUint8(table, column string, opts ...Option) Uint8 { - return Uint8{GenericsInt[uint8]{GenericsField: GenericsField[uint8]{expr{col: toColumn(table, column, opts...)}}}} + return Uint8{NewGenericsInt[uint8](expr{col: toColumn(table, column, opts...)})} } // NewUint16 ... func NewUint16(table, column string, opts ...Option) Uint16 { - return Uint16{GenericsInt[uint16]{GenericsField: GenericsField[uint16]{expr{col: toColumn(table, column, opts...)}}}} + return Uint16{NewGenericsInt[uint16](expr{col: toColumn(table, column, opts...)})} } // NewUint32 ... func NewUint32(table, column string, opts ...Option) Uint32 { - return Uint32{GenericsInt[uint32]{GenericsField: GenericsField[uint32]{expr{col: toColumn(table, column, opts...)}}}} + return Uint32{NewGenericsInt[uint32](expr{col: toColumn(table, column, opts...)})} } // NewUint64 ... func NewUint64(table, column string, opts ...Option) Uint64 { - return Uint64{GenericsInt[uint64]{GenericsField: GenericsField[uint64]{expr{col: toColumn(table, column, opts...)}}}} + return Uint64{NewGenericsInt[uint64](expr{col: toColumn(table, column, opts...)})} } // ======================== float ======================= // NewFloat32 ... func NewFloat32(table, column string, opts ...Option) Float32 { - return Float32{GenericsInt[float32]{GenericsField: GenericsField[float32]{expr{col: toColumn(table, column, opts...)}}}} + return Float32{NewGenericsInt[float32](expr{col: toColumn(table, column, opts...)})} } // NewFloat64 ... func NewFloat64(table, column string, opts ...Option) Float64 { - return Float64{GenericsInt[float64]{GenericsField: GenericsField[float64]{expr{col: toColumn(table, column, opts...)}}}} + return Float64{NewGenericsInt[float64](expr{col: toColumn(table, column, opts...)})} } // ======================== string ======================= // NewString ... func NewString(table, column string, opts ...Option) String { - return String{GenericsString[string]{GenericsField: GenericsField[string]{expr{col: toColumn(table, column, opts...)}}}} + return String{NewGenericsString[string](expr{col: toColumn(table, column, opts...)})} } // NewBytes ... func NewBytes(table, column string, opts ...Option) Bytes { - return Bytes{GenericsString[[]byte]{GenericsField: GenericsField[[]byte]{expr{col: toColumn(table, column, opts...)}}}} + return Bytes{NewGenericsString[[]byte](expr{col: toColumn(table, column, opts...)})} } // ======================== bool ======================= // NewBool ... func NewBool(table, column string, opts ...Option) Bool { - return Bool{GenericsField[bool]{expr{col: toColumn(table, column, opts...)}}} + return Bool{NewGenerics[bool](expr{col: toColumn(table, column, opts...)})} } // ======================== time ======================= // NewTime ... func NewTime(table, column string, opts ...Option) Time { - return Time{GenericsField[time.Time]{expr{col: toColumn(table, column, opts...)}}} + return Time{NewGenerics[time.Time](expr{col: toColumn(table, column, opts...)})} } func toColumn(table, column string, opts ...Option) clause.Column { diff --git a/field/expr.go b/field/expr.go index 2b38b81c..3d12c774 100644 --- a/field/expr.go +++ b/field/expr.go @@ -173,31 +173,34 @@ func (e expr) IsNotNull() Expr { } func (e expr) Count() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{e.setE(clause.Expr{SQL: "COUNT(?)", Vars: []interface{}{e.RawExpr()}})}}} + return Int{NewGenericsInt[int](e.setE(clause.Expr{SQL: "COUNT(?)", Vars: []interface{}{e.RawExpr()}}))} } func (e expr) Distinct() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{e.setE(clause.Expr{SQL: "DISTINCT ?", Vars: []interface{}{e.RawExpr()}})}}} + return Int{NewGenericsInt[int](e.setE(clause.Expr{SQL: "DISTINCT ?", Vars: []interface{}{e.RawExpr()}}))} + } func (e expr) Length() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{e.setE(clause.Expr{SQL: "LENGTH(?)", Vars: []interface{}{e.RawExpr()}})}}} + return Int{NewGenericsInt[int](e.setE(clause.Expr{SQL: "LENGTH(?)", Vars: []interface{}{e.RawExpr()}}))} } func (e expr) Max() Float64 { - return Float64{GenericsInt: GenericsInt[float64]{GenericsField: GenericsField[float64]{e.setE(clause.Expr{SQL: "MAX(?)", Vars: []interface{}{e.RawExpr()}})}}} + return Float64{NewGenericsInt[float64](e.setE(clause.Expr{SQL: "MAX(?)", Vars: []interface{}{e.RawExpr()}}))} } func (e expr) Min() Float64 { - return Float64{GenericsInt: GenericsInt[float64]{GenericsField: GenericsField[float64]{e.setE(clause.Expr{SQL: "MIN(?)", Vars: []interface{}{e.RawExpr()}})}}} + return Float64{NewGenericsInt[float64](e.setE(clause.Expr{SQL: "MIN(?)", Vars: []interface{}{e.RawExpr()}}))} + } func (e expr) Avg() Float64 { - return Float64{GenericsInt: GenericsInt[float64]{GenericsField: GenericsField[float64]{e.setE(clause.Expr{SQL: "AVG(?)", Vars: []interface{}{e.RawExpr()}})}}} + return Float64{NewGenericsInt[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()}})} + return Float64{NewGenericsInt[float64](e.setE(clause.Expr{SQL: "ABS(?)", Vars: []interface{}{e.RawExpr()}}))} } func (e expr) Null() AssignExpr { diff --git a/field/float.go b/field/float.go index 7cbe2fb2..849b886d 100644 --- a/field/float.go +++ b/field/float.go @@ -7,7 +7,7 @@ type Float64 struct { // Floor ... func (field Float64) Floor() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{field.floor()}}} + return Int{NewGenericsInt[int](field.floor())} } // Float32 float32 type field @@ -17,5 +17,5 @@ type Float32 struct { // Floor ... func (field Float32) Floor() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{field.floor()}}} + return Int{NewGenericsInt[int](field.floor())} } diff --git a/field/generics.go b/field/generics.go index 3119380b..3dba7e51 100644 --- a/field/generics.go +++ b/field/generics.go @@ -13,6 +13,10 @@ type ScanValuer interface { Value() (driver.Value, error) // driver.Valuer } +func NewGenerics[T any](e expr) GenericsField[T] { + return GenericsField[T]{e} +} + // GenericsField a generics field struct type GenericsField[T any] struct{ expr } @@ -84,6 +88,10 @@ func (field GenericsField[T]) toSlice(values ...T) []interface{} { return slice } +func NewGenericsInt[T any](e expr) GenericsInt[T] { + return GenericsInt[T]{GenericsField: NewGenerics[T](e)} +} + // GenericsInt int type field type GenericsInt[T any] struct { GenericsField[T] @@ -169,6 +177,10 @@ func (field GenericsInt[T]) Zero() AssignExpr { return field.value(0) } +func NewGenericsString[T any](e expr) GenericsString[T] { + return GenericsString[T]{GenericsField: NewGenerics[T](e)} +} + // GenericsString string type field type GenericsString[T any] struct { GenericsField[T] diff --git a/field/time.go b/field/time.go index 128a59be..2d6aadde 100644 --- a/field/time.go +++ b/field/time.go @@ -44,12 +44,12 @@ func (field Time) Date() Time { // DateDiff equal to DATADIFF(self, value) func (field Time) DateDiff(value time.Time) Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{expr{e: clause.Expr{SQL: "DATEDIFF(?,?)", Vars: []interface{}{field.RawExpr(), value}}}}}} + return Int{NewGenericsInt[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{GenericsString: GenericsString[string]{GenericsField: GenericsField[string]{expr{e: clause.Expr{SQL: "DATE_FORMAT(?,?)", Vars: []interface{}{field.RawExpr(), value}}}}}} + return String{NewGenericsString[string](expr{e: clause.Expr{SQL: "DATE_FORMAT(?,?)", Vars: []interface{}{field.RawExpr(), value}}})} } // Now return result of NOW() @@ -69,61 +69,62 @@ func (field Time) CurTime() Time { // DayName equal to DAYNAME(self) func (field Time) DayName() String { - return String{GenericsString: GenericsString[string]{GenericsField: GenericsField[string]{expr{e: clause.Expr{SQL: "DAYNAME(?)", Vars: []interface{}{field.RawExpr()}}}}}} + return String{NewGenericsString[string](expr{e: clause.Expr{SQL: "DAYNAME(?)", Vars: []interface{}{field.RawExpr()}}})} + } // MonthName equal to MONTHNAME(self) func (field Time) MonthName() String { - return String{GenericsString: GenericsString[string]{GenericsField: GenericsField[string]{expr{e: clause.Expr{SQL: "MONTHNAME(?)", Vars: []interface{}{field.RawExpr()}}}}}} + return String{NewGenericsString[string](expr{e: clause.Expr{SQL: "MONTHNAME(?)", Vars: []interface{}{field.RawExpr()}}})} } func (field Time) Year() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{expr{e: clause.Expr{SQL: "YEAR(?)", Vars: []interface{}{field.RawExpr()}}}}}} + return Int{NewGenericsInt[int](expr{e: clause.Expr{SQL: "YEAR(?)", Vars: []interface{}{field.RawExpr()}}})} } // Month equal to MONTH(self) func (field Time) Month() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{expr{e: clause.Expr{SQL: "MONTH(?)", Vars: []interface{}{field.RawExpr()}}}}}} + return Int{NewGenericsInt[int](expr{e: clause.Expr{SQL: "MONTH(?)", Vars: []interface{}{field.RawExpr()}}})} } // Day equal to DAY(self) func (field Time) Day() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{expr{e: clause.Expr{SQL: "DAY(?)", Vars: []interface{}{field.RawExpr()}}}}}} + return Int{NewGenericsInt[int](expr{e: clause.Expr{SQL: "DAY(?)", Vars: []interface{}{field.RawExpr()}}})} } // Hour equal to HOUR(self) func (field Time) Hour() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{expr{e: clause.Expr{SQL: "HOUR(?)", Vars: []interface{}{field.RawExpr()}}}}}} + return Int{NewGenericsInt[int](expr{e: clause.Expr{SQL: "HOUR(?)", Vars: []interface{}{field.RawExpr()}}})} } // Minute equal to MINUTE(self) func (field Time) Minute() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{expr{e: clause.Expr{SQL: "MINUTE(?)", Vars: []interface{}{field.RawExpr()}}}}}} + return Int{NewGenericsInt[int](expr{e: clause.Expr{SQL: "MINUTE(?)", Vars: []interface{}{field.RawExpr()}}})} } // Second equal to SECOND(self) func (field Time) Second() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{expr{e: clause.Expr{SQL: "SECOND(?)", Vars: []interface{}{field.RawExpr()}}}}}} + return Int{NewGenericsInt[int](expr{e: clause.Expr{SQL: "SECOND(?)", Vars: []interface{}{field.RawExpr()}}})} } // MicroSecond equal to MICROSECOND(self) func (field Time) MicroSecond() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{expr{e: clause.Expr{SQL: "MICROSECOND(?)", Vars: []interface{}{field.RawExpr()}}}}}} + return Int{NewGenericsInt[int](expr{e: clause.Expr{SQL: "MICROSECOND(?)", Vars: []interface{}{field.RawExpr()}}})} } // DayOfWeek equal to DAYOFWEEK(self) func (field Time) DayOfWeek() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{expr{e: clause.Expr{SQL: "DAYOFWEEK(?)", Vars: []interface{}{field.RawExpr()}}}}}} + return Int{NewGenericsInt[int](expr{e: clause.Expr{SQL: "DAYOFWEEK(?)", Vars: []interface{}{field.RawExpr()}}})} } // DayOfMonth equal to DAYOFMONTH(self) func (field Time) DayOfMonth() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{expr{e: clause.Expr{SQL: "DAYOFMONTH(?)", Vars: []interface{}{field.RawExpr()}}}}}} + return Int{NewGenericsInt[int](expr{e: clause.Expr{SQL: "DAYOFMONTH(?)", Vars: []interface{}{field.RawExpr()}}})} } // DayOfYear equal to DAYOFYEAR(self) func (field Time) DayOfYear() Int { - return Int{GenericsInt: GenericsInt[int]{GenericsField: GenericsField[int]{expr{e: clause.Expr{SQL: "DAYOFYEAR(?)", Vars: []interface{}{field.RawExpr()}}}}}} + return Int{NewGenericsInt[int](expr{e: clause.Expr{SQL: "DAYOFYEAR(?)", Vars: []interface{}{field.RawExpr()}}})} } // FromDays equal to FROM_DAYS(self) diff --git a/tests/.expect/dal_3/query/banks.gen.go b/tests/.expect/dal_3/query/banks.gen.go index 863cd584..a248fad6 100644 --- a/tests/.expect/dal_3/query/banks.gen.go +++ b/tests/.expect/dal_3/query/banks.gen.go @@ -7,20 +7,16 @@ package query import ( "context" - "gorm.io/gorm" - "gorm.io/gorm/clause" - "gorm.io/gorm/schema" - "gorm.io/gen" "gorm.io/gen/field" - - "gorm.io/plugin/dbresolver" + "gorm.io/gorm" "gorm.io/gen/tests/.gen/dal_3/model" ) func newBank(db *gorm.DB, opts ...gen.DOOption) bank { _bank := bank{} + _bank.bankDo.RealDO = &_bank.bankDo _bank.bankDo.UseDB(db, opts...) _bank.bankDo.UseModel(&model.Bank{}) @@ -106,295 +102,16 @@ func (b bank) replaceDB(db *gorm.DB) bank { return b } -type bankDo struct{ gen.DO } - -type IBankDo interface { - gen.SubQuery - Debug() IBankDo - WithContext(ctx context.Context) IBankDo - WithResult(fc func(tx gen.Dao)) gen.ResultInfo - ReplaceDB(db *gorm.DB) - ReadDB() IBankDo - WriteDB() IBankDo - As(alias string) gen.Dao - Session(config *gorm.Session) IBankDo - Columns(cols ...field.Expr) gen.Columns - Clauses(conds ...clause.Expression) IBankDo - Not(conds ...gen.Condition) IBankDo - Or(conds ...gen.Condition) IBankDo - Select(conds ...field.Expr) IBankDo - Where(conds ...gen.Condition) IBankDo - Order(conds ...field.Expr) IBankDo - Distinct(cols ...field.Expr) IBankDo - Omit(cols ...field.Expr) IBankDo - Join(table schema.Tabler, on ...field.Expr) IBankDo - LeftJoin(table schema.Tabler, on ...field.Expr) IBankDo - RightJoin(table schema.Tabler, on ...field.Expr) IBankDo - Group(cols ...field.Expr) IBankDo - Having(conds ...gen.Condition) IBankDo - Limit(limit int) IBankDo - Offset(offset int) IBankDo - Count() (count int64, err error) - Scopes(funcs ...func(gen.Dao) gen.Dao) IBankDo - Unscoped() IBankDo - Create(values ...*model.Bank) error - CreateInBatches(values []*model.Bank, batchSize int) error - Save(values ...*model.Bank) error - First() (*model.Bank, error) - Take() (*model.Bank, error) - Last() (*model.Bank, error) - Find() ([]*model.Bank, error) - FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Bank, err error) - FindInBatches(result *[]*model.Bank, batchSize int, fc func(tx gen.Dao, batch int) error) error - Pluck(column field.Expr, dest interface{}) error - Delete(...*model.Bank) (info gen.ResultInfo, err error) - Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error) - UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error) - Updates(value interface{}) (info gen.ResultInfo, err error) - UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error) - UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error) - UpdateColumns(value interface{}) (info gen.ResultInfo, err error) - UpdateFrom(q gen.SubQuery) gen.Dao - Attrs(attrs ...field.AssignExpr) IBankDo - Assign(attrs ...field.AssignExpr) IBankDo - Joins(fields ...field.RelationField) IBankDo - Preload(fields ...field.RelationField) IBankDo - FirstOrInit() (*model.Bank, error) - FirstOrCreate() (*model.Bank, error) - FindByPage(offset int, limit int) (result []*model.Bank, count int64, err error) - ScanByPage(result interface{}, offset int, limit int) (count int64, err error) - Scan(result interface{}) (err error) - Returning(value interface{}, columns ...string) IBankDo - UnderlyingDB() *gorm.DB - schema.Tabler -} - -func (b bankDo) Debug() IBankDo { - return b.withDO(b.DO.Debug()) -} - -func (b bankDo) WithContext(ctx context.Context) IBankDo { - return b.withDO(b.DO.WithContext(ctx)) -} - -func (b bankDo) ReadDB() IBankDo { - return b.Clauses(dbresolver.Read) -} - -func (b bankDo) WriteDB() IBankDo { - return b.Clauses(dbresolver.Write) -} - -func (b bankDo) Session(config *gorm.Session) IBankDo { - return b.withDO(b.DO.Session(config)) -} - -func (b bankDo) Clauses(conds ...clause.Expression) IBankDo { - return b.withDO(b.DO.Clauses(conds...)) -} - -func (b bankDo) Returning(value interface{}, columns ...string) IBankDo { - return b.withDO(b.DO.Returning(value, columns...)) -} - -func (b bankDo) Not(conds ...gen.Condition) IBankDo { - return b.withDO(b.DO.Not(conds...)) -} - -func (b bankDo) Or(conds ...gen.Condition) IBankDo { - return b.withDO(b.DO.Or(conds...)) -} - -func (b bankDo) Select(conds ...field.Expr) IBankDo { - return b.withDO(b.DO.Select(conds...)) -} - -func (b bankDo) Where(conds ...gen.Condition) IBankDo { - return b.withDO(b.DO.Where(conds...)) -} - -func (b bankDo) Order(conds ...field.Expr) IBankDo { - return b.withDO(b.DO.Order(conds...)) -} - -func (b bankDo) Distinct(cols ...field.Expr) IBankDo { - return b.withDO(b.DO.Distinct(cols...)) -} - -func (b bankDo) Omit(cols ...field.Expr) IBankDo { - return b.withDO(b.DO.Omit(cols...)) -} - -func (b bankDo) Join(table schema.Tabler, on ...field.Expr) IBankDo { - return b.withDO(b.DO.Join(table, on...)) -} - -func (b bankDo) LeftJoin(table schema.Tabler, on ...field.Expr) IBankDo { - return b.withDO(b.DO.LeftJoin(table, on...)) -} - -func (b bankDo) RightJoin(table schema.Tabler, on ...field.Expr) IBankDo { - return b.withDO(b.DO.RightJoin(table, on...)) -} - -func (b bankDo) Group(cols ...field.Expr) IBankDo { - return b.withDO(b.DO.Group(cols...)) -} - -func (b bankDo) Having(conds ...gen.Condition) IBankDo { - return b.withDO(b.DO.Having(conds...)) -} - -func (b bankDo) Limit(limit int) IBankDo { - return b.withDO(b.DO.Limit(limit)) -} - -func (b bankDo) Offset(offset int) IBankDo { - return b.withDO(b.DO.Offset(offset)) -} - -func (b bankDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IBankDo { - return b.withDO(b.DO.Scopes(funcs...)) -} - -func (b bankDo) Unscoped() IBankDo { - return b.withDO(b.DO.Unscoped()) -} - -func (b bankDo) Create(values ...*model.Bank) error { - if len(values) == 0 { - return nil - } - return b.DO.Create(values) -} - -func (b bankDo) CreateInBatches(values []*model.Bank, 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 bankDo) Save(values ...*model.Bank) error { - if len(values) == 0 { - return nil - } - return b.DO.Save(values) -} - -func (b bankDo) First() (*model.Bank, error) { - if result, err := b.DO.First(); err != nil { - return nil, err - } else { - return result.(*model.Bank), nil - } +type bankDo struct { + gen.GenericsDo[IBankDo, *model.Bank] } - -func (b bankDo) Take() (*model.Bank, error) { - if result, err := b.DO.Take(); err != nil { - return nil, err - } else { - return result.(*model.Bank), nil - } -} - -func (b bankDo) Last() (*model.Bank, error) { - if result, err := b.DO.Last(); err != nil { - return nil, err - } else { - return result.(*model.Bank), nil - } -} - -func (b bankDo) Find() ([]*model.Bank, error) { - result, err := b.DO.Find() - return result.([]*model.Bank), err -} - -func (b bankDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Bank, err error) { - buf := make([]*model.Bank, 0, batchSize) - err = b.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { - defer func() { results = append(results, buf...) }() - return fc(tx, batch) - }) - return results, err -} - -func (b bankDo) FindInBatches(result *[]*model.Bank, batchSize int, fc func(tx gen.Dao, batch int) error) error { - return b.DO.FindInBatches(result, batchSize, fc) -} - -func (b bankDo) Attrs(attrs ...field.AssignExpr) IBankDo { - return b.withDO(b.DO.Attrs(attrs...)) -} - -func (b bankDo) Assign(attrs ...field.AssignExpr) IBankDo { - return b.withDO(b.DO.Assign(attrs...)) -} - -func (b bankDo) Joins(fields ...field.RelationField) IBankDo { - for _, _f := range fields { - b = *b.withDO(b.DO.Joins(_f)) - } - return &b -} - -func (b bankDo) Preload(fields ...field.RelationField) IBankDo { - for _, _f := range fields { - b = *b.withDO(b.DO.Preload(_f)) - } - return &b -} - -func (b bankDo) FirstOrInit() (*model.Bank, error) { - if result, err := b.DO.FirstOrInit(); err != nil { - return nil, err - } else { - return result.(*model.Bank), nil - } -} - -func (b bankDo) FirstOrCreate() (*model.Bank, error) { - if result, err := b.DO.FirstOrCreate(); err != nil { - return nil, err - } else { - return result.(*model.Bank), nil - } -} - -func (b bankDo) FindByPage(offset int, limit int) (result []*model.Bank, 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 -} - -func (b bankDo) 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 -} - -func (b bankDo) Scan(result interface{}) (err error) { - return b.DO.Scan(result) -} - -func (b bankDo) Delete(models ...*model.Bank) (result gen.ResultInfo, err error) { - return b.DO.Delete(models) +type IBankDo interface { + gen.IGenericsDo[IBankDo, *model.Bank] } -func (b *bankDo) withDO(do gen.Dao) *bankDo { - b.DO = *do.(*gen.DO) - return b +func (r *bankDo) GetInstance(do gen.Dao) IBankDo { + _r := &bankDo{} + _r.DO = *do.(*gen.DO) + _r.RealDO = _r + return _r } From 0ace647064fd23823a892e9cbca22f927ad09b98 Mon Sep 17 00:00:00 2001 From: tr1v3r Date: Wed, 10 Apr 2024 20:42:07 +0800 Subject: [PATCH 06/18] fix: fix gramma error --- field/function.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/field/function.go b/field/function.go index 4cf68a8c..75577872 100644 --- a/field/function.go +++ b/field/function.go @@ -28,5 +28,5 @@ func (f *function) FromUnixTime(date uint64, format string) String { } func (f *function) Rand() String { - return String{expr{e: clause.Expr{SQL: "RAND()"}}} + return String{GenericsString: GenericsString[string]{GenericsField: GenericsField[string]{expr{e: clause.Expr{SQL: "RAND()"}}}}} } From 1f55da1754f5c3267a84bca41b6697c7d0aaf761 Mon Sep 17 00:00:00 2001 From: tr1v3r Date: Wed, 10 Apr 2024 23:33:21 +0800 Subject: [PATCH 07/18] refactor: optimze generics field types and remove redundant field types --- field/bool.go | 16 ++-- field/export.go | 100 ++++++++++++--------- field/expr.go | 33 ++++--- field/field.go | 4 +- field/float.go | 16 ++-- field/function.go | 12 +-- field/generics.go | 213 +++++--------------------------------------- field/int.go | 51 ----------- field/number.go | 98 ++++++++++++++++++++ field/serializer.go | 58 ++++++------ field/string.go | 92 +++++++++++++++++-- field/time.go | 68 +++++++------- generator_test.go | 22 ++--- go.mod | 6 +- go.sum | 13 +-- 15 files changed, 383 insertions(+), 419 deletions(-) delete mode 100644 field/int.go create mode 100644 field/number.go diff --git a/field/bool.go b/field/bool.go index 40b68918..4c411b74 100644 --- a/field/bool.go +++ b/field/bool.go @@ -2,12 +2,12 @@ package field // Bool boolean type field type Bool struct { - GenericsField[bool] + genericsField[bool] } // Not ... func (field Bool) Not() Bool { - return Bool{GenericsField[bool]{field.not()}} + return Bool{genericsField[bool]{field.not()}} } // Is ... @@ -17,32 +17,32 @@ func (field Bool) Is(value bool) Expr { // And boolean and func (field Bool) And(value bool) Expr { - return Bool{GenericsField[bool]{field.and(value)}} + return Bool{genericsField[bool]{field.and(value)}} } // Or boolean or func (field Bool) Or(value bool) Expr { - return Bool{GenericsField[bool]{field.or(value)}} + return Bool{genericsField[bool]{field.or(value)}} } // Xor ... func (field Bool) Xor(value bool) Expr { - return Bool{GenericsField[bool]{field.xor(value)}} + return Bool{genericsField[bool]{field.xor(value)}} } // BitXor ... func (field Bool) BitXor(value bool) Expr { - return Bool{GenericsField[bool]{field.bitXor(value)}} + return Bool{genericsField[bool]{field.bitXor(value)}} } // BitAnd ... func (field Bool) BitAnd(value bool) Expr { - return Bool{GenericsField[bool]{field.bitAnd(value)}} + return Bool{genericsField[bool]{field.bitAnd(value)}} } // BitOr ... func (field Bool) BitOr(value bool) Expr { - return Bool{GenericsField[bool]{field.bitOr(value)}} + return Bool{genericsField[bool]{field.bitOr(value)}} } // Zero ... diff --git a/field/export.go b/field/export.go index 6f2ea364..cd10b520 100644 --- a/field/export.go +++ b/field/export.go @@ -6,6 +6,7 @@ import ( "strings" "time" + "golang.org/x/exp/constraints" "gorm.io/gorm" "gorm.io/gorm/clause" ) @@ -17,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 @@ -30,8 +37,8 @@ var ( // ======================== generic field ======================= // NewField create new field -func NewField(table, column string, opts ...Option) Field { - return Field{GenericsField: GenericsField[driver.Valuer]{expr{col: toColumn(table, column, opts...)}}} +func NewField(table, column string, opts ...Option) genericsField[driver.Valuer] { + return genericsField[driver.Valuer]{expr{col: toColumn(table, column, opts...)}} } // NewSerializer create new field2 @@ -46,92 +53,97 @@ func NewAsterisk(table string, opts ...Option) Asterisk { // ======================== integer ======================= -// NewInt create new Int -func NewInt(table, column string, opts ...Option) Int { - return Int{NewGenericsInt[int](expr{col: toColumn(table, column, opts...)})} +// 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) Number[int] { + return NewNumber[int](table, column, opts...) } -// NewInt8 create new Int8 -func NewInt8(table, column string, opts ...Option) Int8 { - return Int8{NewGenericsInt[int8](expr{col: toColumn(table, column, opts...)})} +// NewInt8 create new field for int8 +func NewInt8(table, column string, opts ...Option) Number[int8] { + return NewNumber[int8](table, column, opts...) } -// NewInt16 ... -func NewInt16(table, column string, opts ...Option) Int16 { - return Int16{NewGenericsInt[int16](expr{col: toColumn(table, column, opts...)})} +// NewInt16 create new field for int16 +func NewInt16(table, column string, opts ...Option) Number[int16] { + return NewNumber[int16](table, column, opts...) } -// NewInt32 ... -func NewInt32(table, column string, opts ...Option) Int32 { - return Int32{NewGenericsInt[int32](expr{col: toColumn(table, column, opts...)})} +// NewInt32 create new field for int32 +func NewInt32(table, column string, opts ...Option) Number[int32] { + return NewNumber[int32](table, column, opts...) } -// NewInt64 ... -func NewInt64(table, column string, opts ...Option) Int64 { - return Int64{NewGenericsInt[int64](expr{col: toColumn(table, column, opts...)})} +// NewInt64 create new field for int64 +func NewInt64(table, column string, opts ...Option) Number[int64] { + return NewNumber[int64](table, column, opts...) } -// NewUint ... -func NewUint(table, column string, opts ...Option) Uint { - return Uint{NewGenericsInt[uint](expr{col: toColumn(table, column, opts...)})} +// NewUint create new field for uint +func NewUint(table, column string, opts ...Option) Number[uint] { + return NewNumber[uint](table, column, opts...) } -// NewUint8 ... -func NewUint8(table, column string, opts ...Option) Uint8 { - return Uint8{NewGenericsInt[uint8](expr{col: toColumn(table, column, opts...)})} +// NewUint8 create new field for uint8 +func NewUint8(table, column string, opts ...Option) Number[uint8] { + return NewNumber[uint8](table, column, opts...) } -// NewUint16 ... -func NewUint16(table, column string, opts ...Option) Uint16 { - return Uint16{NewGenericsInt[uint16](expr{col: toColumn(table, column, opts...)})} +// NewUint16 create new field for uint16 +func NewUint16(table, column string, opts ...Option) Number[uint16] { + return NewNumber[uint16](table, column, opts...) } -// NewUint32 ... -func NewUint32(table, column string, opts ...Option) Uint32 { - return Uint32{NewGenericsInt[uint32](expr{col: toColumn(table, column, opts...)})} +// NewUint32 create new field for uint32 +func NewUint32(table, column string, opts ...Option) Number[uint32] { + return NewNumber[uint32](table, column, opts...) } -// NewUint64 ... -func NewUint64(table, column string, opts ...Option) Uint64 { - return Uint64{NewGenericsInt[uint64](expr{col: toColumn(table, column, opts...)})} +// NewUint64 create new field for uint64 +func NewUint64(table, column string, opts ...Option) Number[uint64] { + return NewNumber[uint64](table, column, opts...) } // ======================== float ======================= -// NewFloat32 ... -func NewFloat32(table, column string, opts ...Option) Float32 { - return Float32{NewGenericsInt[float32](expr{col: toColumn(table, column, opts...)})} +// NewFloat32 create new field for float32 +func NewFloat32(table, column string, opts ...Option) Number[float32] { + return NewNumber[float32](table, column, opts...) } -// NewFloat64 ... -func NewFloat64(table, column string, opts ...Option) Float64 { - return Float64{NewGenericsInt[float64](expr{col: toColumn(table, column, opts...)})} +// NewFloat64 create new field for float64 +func NewFloat64(table, column string, opts ...Option) Number[float64] { + return NewNumber[float64](table, column, opts...) } // ======================== string ======================= // NewString ... -func NewString(table, column string, opts ...Option) String { - return String{NewGenericsString[string](expr{col: toColumn(table, column, opts...)})} +func NewString(table, column string, opts ...Option) Chars[string] { + return newChars[string](expr{col: toColumn(table, column, opts...)}) } // NewBytes ... -func NewBytes(table, column string, opts ...Option) Bytes { - return Bytes{NewGenericsString[[]byte](expr{col: toColumn(table, column, opts...)})} +func NewBytes(table, column string, opts ...Option) Chars[[]byte] { + return newChars[[]byte](expr{col: toColumn(table, column, opts...)}) } // ======================== bool ======================= // NewBool ... func NewBool(table, column string, opts ...Option) Bool { - return Bool{NewGenerics[bool](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{NewGenerics[time.Time](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/expr.go b/field/expr.go index 3d12c774..d688e21f 100644 --- a/field/expr.go +++ b/field/expr.go @@ -172,35 +172,34 @@ 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{NewGenericsInt[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{NewGenericsInt[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{NewGenericsInt[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{NewGenericsInt[float64](e.setE(clause.Expr{SQL: "MAX(?)", Vars: []interface{}{e.RawExpr()}}))} + return Float64{newNumber[float64](e.setE(clause.Expr{SQL: "MAX(?)", Vars: []interface{}{e.RawExpr()}}))} } func (e expr) Min() Float64 { - return Float64{NewGenericsInt[float64](e.setE(clause.Expr{SQL: "MIN(?)", Vars: []interface{}{e.RawExpr()}}))} + return Float64{newNumber[float64](e.setE(clause.Expr{SQL: "MIN(?)", Vars: []interface{}{e.RawExpr()}}))} } func (e expr) Avg() Float64 { - return Float64{NewGenericsInt[float64](e.setE(clause.Expr{SQL: "AVG(?)", Vars: []interface{}{e.RawExpr()}}))} + return Float64{newNumber[float64](e.setE(clause.Expr{SQL: "AVG(?)", Vars: []interface{}{e.RawExpr()}}))} } func (e expr) Abs() Float64 { - return Float64{NewGenericsInt[float64](e.setE(clause.Expr{SQL: "ABS(?)", Vars: []interface{}{e.RawExpr()}}))} + return Float64{newNumber[float64](e.setE(clause.Expr{SQL: "ABS(?)", Vars: []interface{}{e.RawExpr()}}))} } func (e expr) Null() AssignExpr { @@ -242,19 +241,19 @@ func (e expr) SetCol(col Expr) AssignExpr { // ======================== operate columns ======================== func (e expr) AddCol(col Expr) Expr { - return Field{GenericsField[driver.Valuer]{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{GenericsField[driver.Valuer]{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{GenericsField[driver.Valuer]{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{GenericsField[driver.Valuer]{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 { @@ -264,10 +263,10 @@ func (e expr) ConcatCol(cols ...Expr) Expr { placeholders = append(placeholders, "?") vars = append(vars, col.RawExpr()) } - return Field{GenericsField[driver.Valuer]{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 8240a913..0c5c073c 100644 --- a/field/field.go +++ b/field/field.go @@ -3,6 +3,4 @@ package field import "database/sql/driver" // Field a standard field struct -type Field struct { - GenericsField[driver.Valuer] -} +type Field genericsField[driver.Valuer] diff --git a/field/float.go b/field/float.go index 849b886d..a9e44151 100644 --- a/field/float.go +++ b/field/float.go @@ -2,20 +2,16 @@ package field // Float64 float64 type field type Float64 struct { - GenericsInt[float64] + Number[float64] } -// Floor ... -func (field Float64) Floor() Int { - return Int{NewGenericsInt[int](field.floor())} -} +// Floor implement floor method +func (field Float64) Floor() Number[int] { return newNumber[int](field.floor()) } // Float32 float32 type field type Float32 struct { - GenericsInt[float32] + Number[float32] } -// Floor ... -func (field Float32) Floor() Int { - return Int{NewGenericsInt[int](field.floor())} -} +// Floor implement floor method +func (field Float32) Floor() Number[int] { return newNumber[int](field.floor()) } diff --git a/field/function.go b/field/function.go index 75577872..a3c2e4cd 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{GenericsInt: GenericsInt[uint64]{GenericsField: GenericsField[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{GenericsInt: GenericsInt[uint64]{GenericsField: GenericsField[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{GenericsString: GenericsString[string]{GenericsField: GenericsField[string]{expr{e: clause.Expr{SQL: "FROM_UNIXTIME(?, ?)", Vars: []interface{}{date, format}}}}}} + return String{Chars: Chars[string]{genericsField: genericsField[string]{expr{e: clause.Expr{SQL: "FROM_UNIXTIME(?, ?)", Vars: []interface{}{date, format}}}}}} } - return String{GenericsString: GenericsString[string]{GenericsField: GenericsField[string]{expr{e: clause.Expr{SQL: "FROM_UNIXTIME(?)", Vars: []interface{}{date}}}}}} + return String{Chars: Chars[string]{genericsField: genericsField[string]{expr{e: clause.Expr{SQL: "FROM_UNIXTIME(?)", Vars: []interface{}{date}}}}}} } func (f *function) Rand() String { - return String{GenericsString: GenericsString[string]{GenericsField: GenericsField[string]{expr{e: clause.Expr{SQL: "RAND()"}}}}} + return String{Chars: Chars[string]{genericsField: genericsField[string]{expr{e: clause.Expr{SQL: "RAND()"}}}}} } diff --git a/field/generics.go b/field/generics.go index 3dba7e51..adbbc06f 100644 --- a/field/generics.go +++ b/field/generics.go @@ -1,255 +1,82 @@ package field import ( - "database/sql/driver" - "fmt" - "gorm.io/gorm/clause" ) -// ScanValuer interface for Field -type ScanValuer interface { - Scan(src interface{}) error // sql.Scanner - Value() (driver.Value, error) // driver.Valuer -} - -func NewGenerics[T any](e expr) GenericsField[T] { - return GenericsField[T]{e} +// newGenerics create new generic field type +func newGenerics[T any](e expr) genericsField[T] { + return genericsField[T]{e} } -// GenericsField a generics field struct -type GenericsField[T any] struct{ expr } +// 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 { +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 { +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 { +func (field genericsField[T]) In(values ...T) Expr { return expr{e: clause.IN{Column: field.RawExpr(), Values: field.toSlice(values...)}} } // Gt ... -func (field GenericsField[T]) Gt(value T) Expr { +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 { +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 { +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 { +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 { +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 { +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 { +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()} +func (field genericsField[T]) Sum() genericsField[T] { + return genericsField[T]{field.sum()} } // IfNull ... -func (field GenericsField[T]) IfNull(value T) Expr { +func (field genericsField[T]) IfNull(value T) Expr { return field.ifNull(value) } -func (field GenericsField[T]) toSlice(values ...T) []interface{} { +func (field genericsField[T]) toSlice(values ...T) []interface{} { slice := make([]interface{}, len(values)) for i, v := range values { slice[i] = v } return slice } - -func NewGenericsInt[T any](e expr) GenericsInt[T] { - return GenericsInt[T]{GenericsField: NewGenerics[T](e)} -} - -// GenericsInt int type field -type GenericsInt[T any] struct { - GenericsField[T] -} - -// NotIn ... -func (field GenericsInt[T]) NotIn(values ...T) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Between ... -func (field GenericsInt[T]) Between(left T, right T) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field GenericsInt[T]) NotBetween(left T, right T) Expr { - return Not(field.Between(left, right)) -} - -// Add ... -func (field GenericsInt[T]) Add(value T) GenericsInt[T] { - return GenericsInt[T]{GenericsField: GenericsField[T]{field.add(value)}} -} - -// Sub ... -func (field GenericsInt[T]) Sub(value T) GenericsInt[T] { - return GenericsInt[T]{GenericsField: GenericsField[T]{field.sub(value)}} -} - -// Mul ... -func (field GenericsInt[T]) Mul(value T) GenericsInt[T] { - return GenericsInt[T]{GenericsField: GenericsField[T]{field.mul(value)}} -} - -// Div ... -func (field GenericsInt[T]) Div(value T) GenericsInt[T] { - return GenericsInt[T]{GenericsField: GenericsField[T]{field.div(value)}} -} - -// Mod ... -func (field GenericsInt[T]) Mod(value T) GenericsInt[T] { - return GenericsInt[T]{GenericsField: GenericsField[T]{field.mod(value)}} -} - -// FloorDiv ... -func (field GenericsInt[T]) FloorDiv(value T) GenericsInt[T] { - return GenericsInt[T]{GenericsField: GenericsField[T]{field.floorDiv(value)}} -} - -// RightShift ... -func (field GenericsInt[T]) RightShift(value T) GenericsInt[T] { - return GenericsInt[T]{GenericsField: GenericsField[T]{field.rightShift(value)}} -} - -// LeftShift ... -func (field GenericsInt[T]) LeftShift(value T) GenericsInt[T] { - return GenericsInt[T]{GenericsField: GenericsField[T]{field.leftShift(value)}} -} - -// BitXor ... -func (field GenericsInt[T]) BitXor(value T) GenericsInt[T] { - return GenericsInt[T]{GenericsField: GenericsField[T]{field.bitXor(value)}} -} - -// BitAnd ... -func (field GenericsInt[T]) BitAnd(value T) GenericsInt[T] { - return GenericsInt[T]{GenericsField: GenericsField[T]{field.bitAnd(value)}} -} - -// BitOr ... -func (field GenericsInt[T]) BitOr(value T) GenericsInt[T] { - return GenericsInt[T]{GenericsField: GenericsField[T]{field.bitOr(value)}} -} - -// BitFlip ... -func (field GenericsInt[T]) BitFlip() GenericsInt[T] { - return GenericsInt[T]{GenericsField: GenericsField[T]{field.bitFlip()}} -} - -// Zero set zero value -func (field GenericsInt[T]) Zero() AssignExpr { - return field.value(0) -} - -func NewGenericsString[T any](e expr) GenericsString[T] { - return GenericsString[T]{GenericsField: NewGenerics[T](e)} -} - -// GenericsString string type field -type GenericsString[T any] struct { - GenericsField[T] -} - -// Between ... -func (field GenericsString[T]) Between(left T, right T) Expr { - return field.between([]interface{}{left, right}) -} - -// NotBetween ... -func (field GenericsString[T]) NotBetween(left T, right T) Expr { - return Not(field.Between(left, right)) -} - -// NotIn ... -func (field GenericsString[T]) NotIn(values ...T) Expr { - return expr{e: clause.Not(field.In(values...).expression())} -} - -// Regexp ... -func (field GenericsString[T]) Regexp(value string) Expr { - return field.regexp(value) -} - -// NotRegxp ... -func (field GenericsString[T]) NotRegxp(value string) Expr { - return expr{e: clause.Not(field.Regexp(value).expression())} -} - -// Zero ... -func (field GenericsString[T]) Zero() AssignExpr { - return field.value("") -} - -// FindInSet equal to FIND_IN_SET(field_name, input_string_list) -func (field GenericsString[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 GenericsString[T]) FindInSetWith(target string) Expr { - return expr{e: clause.Expr{SQL: "FIND_IN_SET(?,?)", Vars: []interface{}{target, field.RawExpr()}}} -} - -// Replace ... -func (field GenericsString[T]) Replace(from, to string) GenericsString[T] { - return GenericsString[T]{GenericsField: GenericsField[T]{expr{e: clause.Expr{SQL: "REPLACE(?,?,?)", Vars: []interface{}{field.RawExpr(), from, to}}}}} -} - -// Concat ... -func (field GenericsString[T]) Concat(before, after string) GenericsString[T] { - switch { - case before != "" && after != "": - return GenericsString[T]{GenericsField: GenericsField[T]{expr{e: clause.Expr{SQL: "CONCAT(?,?,?)", Vars: []interface{}{before, field.RawExpr(), after}}}}} - case before != "": - return GenericsString[T]{GenericsField: GenericsField[T]{expr{e: clause.Expr{SQL: "CONCAT(?,?)", Vars: []interface{}{before, field.RawExpr()}}}}} - case after != "": - return GenericsString[T]{GenericsField: GenericsField[T]{expr{e: clause.Expr{SQL: "CONCAT(?,?)", Vars: []interface{}{field.RawExpr(), after}}}}} - default: - return field - } -} - -// SubstringIndex SUBSTRING_INDEX -// https://dev.mysql.com/doc/refman/8.0/en/functions.html#function_substring-index -func (field GenericsString[T]) SubstringIndex(delim string, count int) GenericsString[T] { - return GenericsString[T]{GenericsField: GenericsField[T]{expr{e: clause.Expr{ - SQL: fmt.Sprintf("SUBSTRING_INDEX(?,%q,%d)", delim, count), - Vars: []interface{}{field.RawExpr()}, - }}}} -} diff --git a/field/int.go b/field/int.go deleted file mode 100644 index db2c39be..00000000 --- a/field/int.go +++ /dev/null @@ -1,51 +0,0 @@ -package field - -// Int int type field -type Int struct { - GenericsInt[int] -} - -// Int8 int8 type field -type Int8 struct { - GenericsInt[int8] -} - -// Int16 int16 type field -type Int16 struct { - GenericsInt[int16] -} - -// Int32 int32 type field -type Int32 struct { - GenericsInt[int32] -} - -// Int64 int64 type field -type Int64 struct { - GenericsInt[int64] -} - -// Uint uint type field -type Uint struct { - GenericsInt[uint] -} - -// Uint8 uint8 type field -type Uint8 struct { - GenericsInt[uint8] -} - -// Uint16 uint16 type field -type Uint16 struct { - GenericsInt[uint16] -} - -// Uint32 uint32 type field -type Uint32 struct { - GenericsInt[uint32] -} - -// Uint64 uint64 type field -type Uint64 struct { - GenericsInt[uint64] -} diff --git a/field/number.go b/field/number.go new file mode 100644 index 00000000..b8fbc64d --- /dev/null +++ b/field/number.go @@ -0,0 +1,98 @@ +package field + +import ( + "golang.org/x/exp/constraints" + "gorm.io/gorm/clause" +) + +// ======================== 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 Number[T]{genericsField: genericsField[T]{field.add(value)}} +} + +// Sub ... +func (field Number[T]) Sub(value T) Number[T] { + return Number[T]{genericsField: genericsField[T]{field.sub(value)}} +} + +// Mul ... +func (field Number[T]) Mul(value T) Number[T] { + return Number[T]{genericsField: genericsField[T]{field.mul(value)}} +} + +// Div ... +func (field Number[T]) Div(value T) Number[T] { + return Number[T]{genericsField: genericsField[T]{field.div(value)}} +} + +// Mod ... +func (field Number[T]) Mod(value T) Number[T] { + return Number[T]{genericsField: genericsField[T]{field.mod(value)}} +} + +// FloorDiv ... +func (field Number[T]) FloorDiv(value T) Number[T] { + return Number[T]{genericsField: genericsField[T]{field.floorDiv(value)}} +} + +// RightShift ... +func (field Number[T]) RightShift(value T) Number[T] { + return Number[T]{genericsField: genericsField[T]{field.rightShift(value)}} +} + +// LeftShift ... +func (field Number[T]) LeftShift(value T) Number[T] { + return Number[T]{genericsField: genericsField[T]{field.leftShift(value)}} +} + +// BitXor ... +func (field Number[T]) BitXor(value T) Number[T] { + return Number[T]{genericsField: genericsField[T]{field.bitXor(value)}} +} + +// BitAnd ... +func (field Number[T]) BitAnd(value T) Number[T] { + return Number[T]{genericsField: genericsField[T]{field.bitAnd(value)}} +} + +// BitOr ... +func (field Number[T]) BitOr(value T) Number[T] { + return Number[T]{genericsField: genericsField[T]{field.bitOr(value)}} +} + +// BitFlip ... +func (field Number[T]) BitFlip() Number[T] { + return Number[T]{genericsField: genericsField[T]{field.bitFlip()}} +} + +// Zero set zero value +func (field Number[T]) Zero() AssignExpr { + return field.value(0) +} diff --git a/field/serializer.go b/field/serializer.go index b8c7e424..64cb1ddd 100644 --- a/field/serializer.go +++ b/field/serializer.go @@ -2,22 +2,20 @@ package field import ( "context" - "database/sql/driver" "reflect" + "gorm.io/gorm" "gorm.io/gorm/clause" "gorm.io/gorm/schema" - - "gorm.io/gorm" ) -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) @@ -25,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{GenericsField: GenericsField[driver.Valuer]{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 20f6c859..5f093586 100644 --- a/field/string.go +++ b/field/string.go @@ -1,11 +1,93 @@ package field +import ( + "fmt" + + "gorm.io/gorm/clause" +) + // String string type field -type String struct { - GenericsString[string] -} +type String struct{ Chars[string] } // Bytes []byte type field -type Bytes struct { - GenericsString[[]byte] +type Bytes struct{ Chars[[]byte] } + +// ======================== string ======================= + +// newChars create field for chars +func newChars[T ~string | ~[]byte](e expr) Chars[T] { + return Chars[T]{genericsField: newGenerics[T](e)} +} + +// Chars string type field +type Chars[T ~string | ~[]byte] struct { + genericsField[T] +} + +// Between ... +func (field Chars[T]) Between(left T, right T) Expr { + return field.between([]interface{}{left, right}) +} + +// NotBetween ... +func (field Chars[T]) NotBetween(left T, right T) Expr { + return Not(field.Between(left, right)) +} + +// NotIn ... +func (field Chars[T]) NotIn(values ...T) Expr { + return expr{e: clause.Not(field.In(values...).expression())} +} + +// Regexp ... +func (field Chars[T]) Regexp(value string) Expr { + return field.regexp(value) +} + +// NotRegxp ... +func (field Chars[T]) NotRegxp(value string) Expr { + return expr{e: clause.Not(field.Regexp(value).expression())} +} + +// Zero ... +func (field Chars[T]) Zero() AssignExpr { + return field.value("") +} + +// FindInSet equal to FIND_IN_SET(field_name, input_string_list) +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 Chars[T]) FindInSetWith(target string) Expr { + return expr{e: clause.Expr{SQL: "FIND_IN_SET(?,?)", Vars: []interface{}{target, field.RawExpr()}}} +} + +// Replace ... +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 Chars[T]) Concat(before, after string) Chars[T] { + switch { + case before != "" && after != "": + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{SQL: "CONCAT(?,?,?)", Vars: []interface{}{before, field.RawExpr(), after}}}}} + case before != "": + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{SQL: "CONCAT(?,?)", Vars: []interface{}{before, field.RawExpr()}}}}} + case after != "": + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{SQL: "CONCAT(?,?)", Vars: []interface{}{field.RawExpr(), after}}}}} + default: + return field + } +} + +// 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()}, + }}}} } diff --git a/field/time.go b/field/time.go index 2d6aadde..e995e598 100644 --- a/field/time.go +++ b/field/time.go @@ -9,7 +9,7 @@ import ( // Time time type field type Time struct { - GenericsField[time.Time] + genericsField[time.Time] } // Between ... @@ -29,112 +29,112 @@ func (field Time) NotIn(values ...time.Time) Expr { // Add ... func (field Time) Add(value time.Duration) Time { - return Time{GenericsField[time.Time]{field.add(value)}} + return Time{genericsField[time.Time]{field.add(value)}} } // Sub ... func (field Time) Sub(value time.Duration) Time { - return Time{GenericsField[time.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{GenericsField[time.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{NewGenericsInt[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{NewGenericsString[string](expr{e: clause.Expr{SQL: "DATE_FORMAT(?,?)", Vars: []interface{}{field.RawExpr(), value}}})} + return String{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{GenericsField[time.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{GenericsField[time.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{GenericsField[time.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{NewGenericsString[string](expr{e: clause.Expr{SQL: "DAYNAME(?)", Vars: []interface{}{field.RawExpr()}}})} + return String{newChars[string](expr{e: clause.Expr{SQL: "DAYNAME(?)", Vars: []interface{}{field.RawExpr()}}})} } // MonthName equal to MONTHNAME(self) func (field Time) MonthName() String { - return String{NewGenericsString[string](expr{e: clause.Expr{SQL: "MONTHNAME(?)", Vars: []interface{}{field.RawExpr()}}})} + return String{newChars[string](expr{e: clause.Expr{SQL: "MONTHNAME(?)", Vars: []interface{}{field.RawExpr()}}})} } -func (field Time) Year() Int { - return Int{NewGenericsInt[int](expr{e: clause.Expr{SQL: "YEAR(?)", Vars: []interface{}{field.RawExpr()}}})} +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{NewGenericsInt[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{NewGenericsInt[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{NewGenericsInt[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{NewGenericsInt[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{NewGenericsInt[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{NewGenericsInt[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{NewGenericsInt[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{NewGenericsInt[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{NewGenericsInt[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{GenericsField[time.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{GenericsField[time.Time]{expr{e: clause.Expr{SQL: fmt.Sprintf("FROM_UNIXTIME(%d)", value)}}}} + return Time{genericsField[time.Time]{expr{e: clause.Expr{SQL: fmt.Sprintf("FROM_UNIXTIME(%d)", value)}}}} } // Zero set zero value diff --git a/generator_test.go b/generator_test.go index 1ab13f2c..b99f805d 100644 --- a/generator_test.go +++ b/generator_test.go @@ -86,11 +86,11 @@ type user struct { userDo ALL field.Asterisk - ID field.Uint - Name field.String - Age field.Int - Score field.Float64 - Address field.String + ID field.Number[uint] + Name field.Chars[string] + Age field.Number[int] + Score field.Number[float64] + Address field.Chars[string] Famous field.Bool RegisterAt field.Time } @@ -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/go.mod b/go.mod index adcdee35..134e7cb9 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.1.1-0.20230130040222-c43177d3cf8c gorm.io/gorm v1.25.9 gorm.io/hints v1.1.0 @@ -15,6 +16,7 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect golang.org/x/crypto v0.14.0 // 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 gorm.io/driver/mysql v1.4.4 // indirect ) diff --git a/go.sum b/go.sum index 8e7d4d18..021c36d2 100644 --- a/go.sum +++ b/go.sum @@ -27,12 +27,15 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -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.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -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.1.1-0.20230130040222-c43177d3cf8c h1:jWdr7cHgl8c/ua5vYbR2WhSp+NQmzhsj0xoY3foTzW8= From b589b712414ae0bd805e769741eee307d9018f73 Mon Sep 17 00:00:00 2001 From: tr1v3r Date: Thu, 11 Apr 2024 00:27:41 +0800 Subject: [PATCH 08/18] feat: remove float64 field type --- field/expr.go | 18 ++++++++---------- field/float.go | 17 ----------------- field/number.go | 29 +++++++++++++++++------------ 3 files changed, 25 insertions(+), 39 deletions(-) delete mode 100644 field/float.go diff --git a/field/expr.go b/field/expr.go index d688e21f..86489210 100644 --- a/field/expr.go +++ b/field/expr.go @@ -184,22 +184,20 @@ 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{newNumber[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{newNumber[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{newNumber[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{newNumber[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 { diff --git a/field/float.go b/field/float.go deleted file mode 100644 index a9e44151..00000000 --- a/field/float.go +++ /dev/null @@ -1,17 +0,0 @@ -package field - -// Float64 float64 type field -type Float64 struct { - Number[float64] -} - -// Floor implement floor method -func (field Float64) Floor() Number[int] { return newNumber[int](field.floor()) } - -// Float32 float32 type field -type Float32 struct { - Number[float32] -} - -// Floor implement floor method -func (field Float32) Floor() Number[int] { return newNumber[int](field.floor()) } diff --git a/field/number.go b/field/number.go index b8fbc64d..7ef5bb14 100644 --- a/field/number.go +++ b/field/number.go @@ -34,62 +34,67 @@ func (field Number[T]) NotBetween(left T, right T) Expr { // Add ... func (field Number[T]) Add(value T) Number[T] { - return Number[T]{genericsField: genericsField[T]{field.add(value)}} + return newNumber[T](field.add(value)) } // Sub ... func (field Number[T]) Sub(value T) Number[T] { - return Number[T]{genericsField: genericsField[T]{field.sub(value)}} + return newNumber[T](field.sub(value)) } // Mul ... func (field Number[T]) Mul(value T) Number[T] { - return Number[T]{genericsField: genericsField[T]{field.mul(value)}} + return newNumber[T](field.mul(value)) } // Div ... func (field Number[T]) Div(value T) Number[T] { - return Number[T]{genericsField: genericsField[T]{field.div(value)}} + return newNumber[T](field.div(value)) } // Mod ... func (field Number[T]) Mod(value T) Number[T] { - return Number[T]{genericsField: genericsField[T]{field.mod(value)}} + return newNumber[T](field.mod(value)) } // FloorDiv ... func (field Number[T]) FloorDiv(value T) Number[T] { - return Number[T]{genericsField: genericsField[T]{field.floorDiv(value)}} + return newNumber[T](field.floorDiv(value)) } // RightShift ... func (field Number[T]) RightShift(value T) Number[T] { - return Number[T]{genericsField: genericsField[T]{field.rightShift(value)}} + return newNumber[T](field.rightShift(value)) } // LeftShift ... func (field Number[T]) LeftShift(value T) Number[T] { - return Number[T]{genericsField: genericsField[T]{field.leftShift(value)}} + return newNumber[T](field.leftShift(value)) } // BitXor ... func (field Number[T]) BitXor(value T) Number[T] { - return Number[T]{genericsField: genericsField[T]{field.bitXor(value)}} + return newNumber[T](field.bitXor(value)) } // BitAnd ... func (field Number[T]) BitAnd(value T) Number[T] { - return Number[T]{genericsField: genericsField[T]{field.bitAnd(value)}} + return newNumber[T](field.bitAnd(value)) } // BitOr ... func (field Number[T]) BitOr(value T) Number[T] { - return Number[T]{genericsField: genericsField[T]{field.bitOr(value)}} + return newNumber[T](field.bitOr(value)) } // BitFlip ... func (field Number[T]) BitFlip() Number[T] { - return Number[T]{genericsField: genericsField[T]{field.bitFlip()}} + return newNumber[T](field.bitFlip()) +} + +// Floor ... +func (field Number[T]) Floor() Number[T] { + return newNumber[T](field.floor()) } // Zero set zero value From 15b921963ce9c2724f48e880e0f541c93b1aa8dc Mon Sep 17 00:00:00 2001 From: tr1v3r Date: Thu, 11 Apr 2024 00:35:22 +0800 Subject: [PATCH 09/18] style: optimize tags --- field/tag.go | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) 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] From 821a7e77fdb6fa35b569fb747698fa353c572a5f Mon Sep 17 00:00:00 2001 From: qqxhb <1252905006@qq.com> Date: Mon, 6 May 2024 12:18:51 +0800 Subject: [PATCH 10/18] feat: field alias --- field/export.go | 28 ++++++++++++++-------------- field/function.go | 6 +++--- field/number.go | 24 ++++++++++++++++++++++++ field/string.go | 4 ++-- field/time.go | 6 +++--- 5 files changed, 46 insertions(+), 22 deletions(-) diff --git a/field/export.go b/field/export.go index cd10b520..c9b08fb9 100644 --- a/field/export.go +++ b/field/export.go @@ -59,76 +59,76 @@ func NewNumber[T constraints.Integer | constraints.Float](table, column string, } // NewInt create new field for int -func NewInt(table, column string, opts ...Option) Number[int] { +func NewInt(table, column string, opts ...Option) Int { return NewNumber[int](table, column, opts...) } // NewInt8 create new field for int8 -func NewInt8(table, column string, opts ...Option) Number[int8] { +func NewInt8(table, column string, opts ...Option) Int8 { return NewNumber[int8](table, column, opts...) } // NewInt16 create new field for int16 -func NewInt16(table, column string, opts ...Option) Number[int16] { +func NewInt16(table, column string, opts ...Option) Int16 { return NewNumber[int16](table, column, opts...) } // NewInt32 create new field for int32 -func NewInt32(table, column string, opts ...Option) Number[int32] { +func NewInt32(table, column string, opts ...Option) Int32 { return NewNumber[int32](table, column, opts...) } // NewInt64 create new field for int64 -func NewInt64(table, column string, opts ...Option) Number[int64] { +func NewInt64(table, column string, opts ...Option) Int64 { return NewNumber[int64](table, column, opts...) } // NewUint create new field for uint -func NewUint(table, column string, opts ...Option) Number[uint] { +func NewUint(table, column string, opts ...Option) Uint { return NewNumber[uint](table, column, opts...) } // NewUint8 create new field for uint8 -func NewUint8(table, column string, opts ...Option) Number[uint8] { +func NewUint8(table, column string, opts ...Option) Uint8 { return NewNumber[uint8](table, column, opts...) } // NewUint16 create new field for uint16 -func NewUint16(table, column string, opts ...Option) Number[uint16] { +func NewUint16(table, column string, opts ...Option) Uint16 { return NewNumber[uint16](table, column, opts...) } // NewUint32 create new field for uint32 -func NewUint32(table, column string, opts ...Option) Number[uint32] { +func NewUint32(table, column string, opts ...Option) Uint32 { return NewNumber[uint32](table, column, opts...) } // NewUint64 create new field for uint64 -func NewUint64(table, column string, opts ...Option) Number[uint64] { +func NewUint64(table, column string, opts ...Option) Uint64 { return NewNumber[uint64](table, column, opts...) } // ======================== float ======================= // NewFloat32 create new field for float32 -func NewFloat32(table, column string, opts ...Option) Number[float32] { +func NewFloat32(table, column string, opts ...Option) Float32 { return NewNumber[float32](table, column, opts...) } // NewFloat64 create new field for float64 -func NewFloat64(table, column string, opts ...Option) Number[float64] { +func NewFloat64(table, column string, opts ...Option) Float64 { return NewNumber[float64](table, column, opts...) } // ======================== string ======================= // NewString ... -func NewString(table, column string, opts ...Option) Chars[string] { +func NewString(table, column string, opts ...Option) String { return newChars[string](expr{col: toColumn(table, column, opts...)}) } // NewBytes ... -func NewBytes(table, column string, opts ...Option) Chars[[]byte] { +func NewBytes(table, column string, opts ...Option) Bytes { return newChars[[]byte](expr{col: toColumn(table, column, opts...)}) } diff --git a/field/function.go b/field/function.go index a3c2e4cd..01d6ccc5 100644 --- a/field/function.go +++ b/field/function.go @@ -22,11 +22,11 @@ func (f *function) UnixTimestamp(date ...string) Number[uint64] { // FromUnixTime FROM_UNIXTIME(unix_timestamp[,format]) func (f *function) FromUnixTime(date uint64, format string) String { if strings.TrimSpace(format) != "" { - return String{Chars: Chars[string]{genericsField: genericsField[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{Chars: Chars[string]{genericsField: genericsField[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{Chars: Chars[string]{genericsField: genericsField[string]{expr{e: clause.Expr{SQL: "RAND()"}}}}} + return String{genericsField[string]{expr{e: clause.Expr{SQL: "RAND()"}}}} } diff --git a/field/number.go b/field/number.go index 7ef5bb14..216d92ae 100644 --- a/field/number.go +++ b/field/number.go @@ -5,6 +5,30 @@ import ( "gorm.io/gorm/clause" ) +type Int = Number[int] + +type Int8 = Number[int8] + +type Int16 = Number[int16] + +type Int32 = Number[int32] + +type Int64 = Number[int64] + +type Uint = Number[uint] + +type Uint8 = Number[uint8] + +type Uint16 = Number[uint16] + +type Uint32 = Number[uint32] + +type Uint64 = Number[uint64] + +type Float32 = Number[float32] + +type Float64 = Number[float64] + // ======================== number ======================= // newNumber build number type field diff --git a/field/string.go b/field/string.go index 5f093586..cdb56a3c 100644 --- a/field/string.go +++ b/field/string.go @@ -7,10 +7,10 @@ import ( ) // String string type field -type String struct{ Chars[string] } +type String = Chars[string] // Bytes []byte type field -type Bytes struct{ Chars[[]byte] } +type Bytes = Chars[[]byte] // ======================== string ======================= diff --git a/field/time.go b/field/time.go index e995e598..5e44303f 100644 --- a/field/time.go +++ b/field/time.go @@ -49,7 +49,7 @@ func (field Time) DateDiff(value time.Time) Number[int] { // DateFormat equal to DATE_FORMAT(self, value) func (field Time) DateFormat(value string) String { - return String{newChars[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() @@ -69,13 +69,13 @@ func (field Time) CurTime() Time { // DayName equal to DAYNAME(self) func (field Time) DayName() String { - return String{newChars[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{newChars[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() Number[int] { From 23f5151a33cbdb41951678d0eb47c0cc8486a3e0 Mon Sep 17 00:00:00 2001 From: qqxhb <1252905006@qq.com> Date: Mon, 6 May 2024 12:19:54 +0800 Subject: [PATCH 11/18] feat: tosql --- generics.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/generics.go b/generics.go index 690f14a3..b989329b 100644 --- a/generics.go +++ b/generics.go @@ -69,6 +69,7 @@ type IGenericsDo[T any, E any] interface { UnderlyingDB() *gorm.DB schema.Tabler GetInstance(do Dao) T + ToSQL(queryFn func(T) T) string } type GenericsDo[T IGenericsDo[T, E], E any] struct { @@ -311,6 +312,14 @@ func (b GenericsDo[T, E]) Delete(models ...E) (result ResultInfo, err error) { return b.DO.Delete(models) } +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.Debug())) + 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) } From f7cc47bf43ab1ad947ea3ecd0ad404b774cd475e Mon Sep 17 00:00:00 2001 From: qqxhb <1252905006@qq.com> Date: Wed, 15 Jan 2025 20:03:47 +0800 Subject: [PATCH 12/18] feat: add generic mode --- config.go | 3 + field/export.go | 4 +- field/number.go | 12 + field/time.go | 1 + generator.go | 37 +- generator_test.go | 10 +- generics.go | 13 +- internal/generate/query.go | 8 + internal/template/method.go | 4 +- internal/template/struct.go | 24 +- tests/.expect/dal_3/query/banks.gen.go | 308 ++++++- tests/.expect/dal_7/model/users.gen.go | 33 + tests/.expect/dal_7/query/gen.go | 103 +++ tests/.expect/dal_7/query/gen_test.go | 122 +++ tests/.expect/dal_7/query/users.gen.go | 912 ++++++++++++++++++++ tests/.expect/dal_7/query/users.gen_test.go | 564 ++++++++++++ tests/generate_test.go | 17 + 17 files changed, 2129 insertions(+), 46 deletions(-) create mode 100644 tests/.expect/dal_7/model/users.gen.go create mode 100644 tests/.expect/dal_7/query/gen.go create mode 100644 tests/.expect/dal_7/query/gen_test.go create mode 100644 tests/.expect/dal_7/query/users.gen.go create mode 100644 tests/.expect/dal_7/query/users.gen_test.go diff --git a/config.go b/config.go index f2161b8f..81a00e9c 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/export.go b/field/export.go index c9b08fb9..3d5e9d1b 100644 --- a/field/export.go +++ b/field/export.go @@ -37,8 +37,8 @@ var ( // ======================== generic field ======================= // NewField create new field -func NewField(table, column string, opts ...Option) genericsField[driver.Valuer] { - return genericsField[driver.Valuer]{expr{col: toColumn(table, column, opts...)}} +func NewField(table, column string, opts ...Option) Field { + return Field(genericsField[driver.Valuer]{expr{col: toColumn(table, column, opts...)}}) } // NewSerializer create new field2 diff --git a/field/number.go b/field/number.go index 216d92ae..ac78a17e 100644 --- a/field/number.go +++ b/field/number.go @@ -5,28 +5,40 @@ import ( "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 ======================= diff --git a/field/time.go b/field/time.go index 5e44303f..9198d841 100644 --- a/field/time.go +++ b/field/time.go @@ -78,6 +78,7 @@ func (field Time) MonthName() String { return newChars[string](expr{e: clause.Expr{SQL: "MONTHNAME(?)", 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()}}}) } diff --git a/generator.go b/generator.go index efb842bf..fc005a15 100644 --- a/generator.go +++ b/generator.go @@ -395,22 +395,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 { @@ -420,11 +435,6 @@ func (g *Generator) generateSingleQueryFile(data *genInfo) (err error) { } } - err = render(tmpl.GetInstanceMethod, &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()) } @@ -583,6 +593,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 b99f805d..85955989 100644 --- a/generator_test.go +++ b/generator_test.go @@ -86,11 +86,11 @@ type user struct { userDo ALL field.Asterisk - ID field.Number[uint] - Name field.Chars[string] - Age field.Number[int] - Score field.Number[float64] - Address field.Chars[string] + ID field.Uint + Name field.String + Age field.Int + Score field.Float64 + Address field.String Famous field.Bool RegisterAt field.Time } diff --git a/generics.go b/generics.go index b989329b..e9c9fbb8 100644 --- a/generics.go +++ b/generics.go @@ -2,7 +2,7 @@ package gen import ( "context" - + "database/sql" "gorm.io/gen/field" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -10,6 +10,7 @@ import ( "gorm.io/plugin/dbresolver" ) +// IGenericsDo generic query interface type IGenericsDo[T any, E any] interface { SubQuery Debug() T @@ -18,6 +19,7 @@ type IGenericsDo[T any, E any] interface { 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 @@ -64,6 +66,8 @@ type IGenericsDo[T any, E any] interface { 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 @@ -72,6 +76,7 @@ type IGenericsDo[T any, E any] interface { ToSQL(queryFn func(T) T) string } +// GenericsDo base impl of IGenericsDo type GenericsDo[T IGenericsDo[T, E], E any] struct { DO RealDO T @@ -121,10 +126,6 @@ func (b GenericsDo[T, E]) Where(conds ...Condition) T { return b.withDO(b.DO.Where(conds...)) } -func (b GenericsDo[T, E]) Exists(subquery interface{ UnderlyingDB() *gorm.DB }) T { - return b.Where(field.CompareSubQuery(field.ExistsOp, nil, subquery.UnderlyingDB())) -} - func (b GenericsDo[T, E]) Order(conds ...field.Expr) T { return b.withDO(b.DO.Order(conds...)) } @@ -314,7 +315,7 @@ func (b GenericsDo[T, E]) Delete(models ...E) (result ResultInfo, err error) { 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.Debug())) + t := queryFn(b.withDO(&b.DO)) db := t.underlyingDB() stmt := db.Statement return db.Dialector.Explain(stmt.SQL.String(), stmt.Vars...) diff --git a/internal/generate/query.go b/internal/generate/query.go index c9e27e10..f2d6a004 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 @@ -227,6 +229,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 f9cf50fc..0099a738 100644 --- a/internal/template/method.go +++ b/internal/template/method.go @@ -27,8 +27,8 @@ func ({{.S}} {{.TargetStruct}}Do){{.FuncSign}}{ ` -// GetInstance method -const GetInstanceMethod = ` +// CRUDGenericMethod generic CRUD method +const CRUDGenericMethod = ` func ({{.S}} *{{.QueryStructName}}Do) GetInstance(do gen.Dao) {{.ReturnObject}} { _r := &{{.QueryStructName}}Do{} _r.DO = *do.(*gen.DO) diff --git a/internal/template/struct.go b/internal/template/struct.go index 0ed61583..6475bf99 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 + defineGenericsMethodStruct + ` + tableMethod + asMethond + updateFieldMethod + getFieldMethod + fillFieldMapMethod + cloneMethod + replaceMethod + relationship // TableQueryStructWithContext table query struct with context TableQueryStructWithContext = createMethod + ` @@ -27,18 +27,26 @@ const ( func ({{.S}} {{.QueryStructName}}) Columns(cols ...field.Expr) gen.Columns { return {{.S}}.{{.QueryStructName}}Do.Columns(cols...) } - ` + getFieldMethod + fillFieldMapMethod + cloneMethod + replaceMethod + relationship + defineGenericsMethodStruct + ` + getFieldMethod + fillFieldMapMethod + cloneMethod + replaceMethod + relationship // TableQueryIface table query interface - TableQueryIface = defineGenericsDoInterface + TableQueryIface = defineDoInterface + 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}}{}) @@ -132,9 +140,8 @@ func ({{.S}} *{{.QueryStructName}}) GetFieldByName(fieldName string) (field.Orde `{{- $relation := .Relation }}{{- $relationship := $relation.RelationshipName}}` + relationStruct + relationTx + `{{end}}{{end}}` - defineMethodStruct = `type {{.QueryStructName}}Do struct { gen.DO }` - defineGenericsMethodStruct = `type {{.QueryStructName}}Do struct {gen.GenericsDo[I{{.ModelStructName}}Do, *{{.StructInfo.Package}}.{{.StructInfo.Type}}]}` - fillFieldMapMethod = ` + + fillFieldMapMethod = ` func ({{.S}} *{{.QueryStructName}}) fillFieldMap() { {{.S}}.fieldMap = make(map[string]field.Expr, {{len .Fields}}) {{range .Fields -}} @@ -147,7 +154,6 @@ func ({{.S}} *{{.QueryStructName}}) fillFieldMap() { defineGenericsDoInterface = ` type I{{.ModelStructName}}Do interface { gen.IGenericsDo[I{{.ModelStructName}}Do, *{{.StructInfo.Package}}.{{.StructInfo.Type}}] - {{range .Interfaces -}} {{.FuncSign}} {{end}} @@ -210,6 +216,8 @@ type I{{.ModelStructName}}Do interface { FirstOrCreate() (*{{.StructInfo.Package}}.{{.StructInfo.Type}}, error) FindByPage(offset int, limit int) (result []*{{.StructInfo.Package}}.{{.StructInfo.Type}}, 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) I{{.ModelStructName}}Do UnderlyingDB() *gorm.DB diff --git a/tests/.expect/dal_3/query/banks.gen.go b/tests/.expect/dal_3/query/banks.gen.go index a248fad6..1265fefb 100644 --- a/tests/.expect/dal_3/query/banks.gen.go +++ b/tests/.expect/dal_3/query/banks.gen.go @@ -6,17 +6,22 @@ package query import ( "context" + "database/sql" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" "gorm.io/gen" "gorm.io/gen/field" - "gorm.io/gorm" + + "gorm.io/plugin/dbresolver" "gorm.io/gen/tests/.gen/dal_3/model" ) func newBank(db *gorm.DB, opts ...gen.DOOption) bank { _bank := bank{} - _bank.bankDo.RealDO = &_bank.bankDo _bank.bankDo.UseDB(db, opts...) _bank.bankDo.UseModel(&model.Bank{}) @@ -102,16 +107,297 @@ func (b bank) replaceDB(db *gorm.DB) bank { return b } -type bankDo struct { - gen.GenericsDo[IBankDo, *model.Bank] -} +type bankDo struct{ gen.DO } + type IBankDo interface { - gen.IGenericsDo[IBankDo, *model.Bank] + gen.SubQuery + Debug() IBankDo + WithContext(ctx context.Context) IBankDo + WithResult(fc func(tx gen.Dao)) gen.ResultInfo + ReplaceDB(db *gorm.DB) + ReadDB() IBankDo + WriteDB() IBankDo + As(alias string) gen.Dao + Session(config *gorm.Session) IBankDo + Columns(cols ...field.Expr) gen.Columns + Clauses(conds ...clause.Expression) IBankDo + Not(conds ...gen.Condition) IBankDo + Or(conds ...gen.Condition) IBankDo + Select(conds ...field.Expr) IBankDo + Where(conds ...gen.Condition) IBankDo + Order(conds ...field.Expr) IBankDo + Distinct(cols ...field.Expr) IBankDo + Omit(cols ...field.Expr) IBankDo + Join(table schema.Tabler, on ...field.Expr) IBankDo + LeftJoin(table schema.Tabler, on ...field.Expr) IBankDo + RightJoin(table schema.Tabler, on ...field.Expr) IBankDo + Group(cols ...field.Expr) IBankDo + Having(conds ...gen.Condition) IBankDo + Limit(limit int) IBankDo + Offset(offset int) IBankDo + Count() (count int64, err error) + Scopes(funcs ...func(gen.Dao) gen.Dao) IBankDo + Unscoped() IBankDo + Create(values ...*model.Bank) error + CreateInBatches(values []*model.Bank, batchSize int) error + Save(values ...*model.Bank) error + First() (*model.Bank, error) + Take() (*model.Bank, error) + Last() (*model.Bank, error) + Find() ([]*model.Bank, error) + FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Bank, err error) + FindInBatches(result *[]*model.Bank, batchSize int, fc func(tx gen.Dao, batch int) error) error + Pluck(column field.Expr, dest interface{}) error + Delete(...*model.Bank) (info gen.ResultInfo, err error) + Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error) + UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error) + Updates(value interface{}) (info gen.ResultInfo, err error) + UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error) + UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error) + UpdateColumns(value interface{}) (info gen.ResultInfo, err error) + UpdateFrom(q gen.SubQuery) gen.Dao + Attrs(attrs ...field.AssignExpr) IBankDo + Assign(attrs ...field.AssignExpr) IBankDo + Joins(fields ...field.RelationField) IBankDo + Preload(fields ...field.RelationField) IBankDo + FirstOrInit() (*model.Bank, error) + FirstOrCreate() (*model.Bank, error) + FindByPage(offset int, limit int) (result []*model.Bank, 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) IBankDo + UnderlyingDB() *gorm.DB + schema.Tabler +} + +func (b bankDo) Debug() IBankDo { + return b.withDO(b.DO.Debug()) +} + +func (b bankDo) WithContext(ctx context.Context) IBankDo { + return b.withDO(b.DO.WithContext(ctx)) +} + +func (b bankDo) ReadDB() IBankDo { + return b.Clauses(dbresolver.Read) +} + +func (b bankDo) WriteDB() IBankDo { + return b.Clauses(dbresolver.Write) } -func (r *bankDo) GetInstance(do gen.Dao) IBankDo { - _r := &bankDo{} - _r.DO = *do.(*gen.DO) - _r.RealDO = _r - return _r +func (b bankDo) Session(config *gorm.Session) IBankDo { + return b.withDO(b.DO.Session(config)) +} + +func (b bankDo) Clauses(conds ...clause.Expression) IBankDo { + return b.withDO(b.DO.Clauses(conds...)) +} + +func (b bankDo) Returning(value interface{}, columns ...string) IBankDo { + return b.withDO(b.DO.Returning(value, columns...)) +} + +func (b bankDo) Not(conds ...gen.Condition) IBankDo { + return b.withDO(b.DO.Not(conds...)) +} + +func (b bankDo) Or(conds ...gen.Condition) IBankDo { + return b.withDO(b.DO.Or(conds...)) +} + +func (b bankDo) Select(conds ...field.Expr) IBankDo { + return b.withDO(b.DO.Select(conds...)) +} + +func (b bankDo) Where(conds ...gen.Condition) IBankDo { + return b.withDO(b.DO.Where(conds...)) +} + +func (b bankDo) Order(conds ...field.Expr) IBankDo { + return b.withDO(b.DO.Order(conds...)) +} + +func (b bankDo) Distinct(cols ...field.Expr) IBankDo { + return b.withDO(b.DO.Distinct(cols...)) +} + +func (b bankDo) Omit(cols ...field.Expr) IBankDo { + return b.withDO(b.DO.Omit(cols...)) +} + +func (b bankDo) Join(table schema.Tabler, on ...field.Expr) IBankDo { + return b.withDO(b.DO.Join(table, on...)) +} + +func (b bankDo) LeftJoin(table schema.Tabler, on ...field.Expr) IBankDo { + return b.withDO(b.DO.LeftJoin(table, on...)) +} + +func (b bankDo) RightJoin(table schema.Tabler, on ...field.Expr) IBankDo { + return b.withDO(b.DO.RightJoin(table, on...)) +} + +func (b bankDo) Group(cols ...field.Expr) IBankDo { + return b.withDO(b.DO.Group(cols...)) +} + +func (b bankDo) Having(conds ...gen.Condition) IBankDo { + return b.withDO(b.DO.Having(conds...)) +} + +func (b bankDo) Limit(limit int) IBankDo { + return b.withDO(b.DO.Limit(limit)) +} + +func (b bankDo) Offset(offset int) IBankDo { + return b.withDO(b.DO.Offset(offset)) +} + +func (b bankDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IBankDo { + return b.withDO(b.DO.Scopes(funcs...)) +} + +func (b bankDo) Unscoped() IBankDo { + return b.withDO(b.DO.Unscoped()) +} + +func (b bankDo) Create(values ...*model.Bank) error { + if len(values) == 0 { + return nil + } + return b.DO.Create(values) } + +func (b bankDo) CreateInBatches(values []*model.Bank, 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 bankDo) Save(values ...*model.Bank) error { + if len(values) == 0 { + return nil + } + return b.DO.Save(values) +} + +func (b bankDo) First() (*model.Bank, error) { + if result, err := b.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.Bank), nil + } +} + +func (b bankDo) Take() (*model.Bank, error) { + if result, err := b.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.Bank), nil + } +} + +func (b bankDo) Last() (*model.Bank, error) { + if result, err := b.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.Bank), nil + } +} + +func (b bankDo) Find() ([]*model.Bank, error) { + result, err := b.DO.Find() + return result.([]*model.Bank), err +} + +func (b bankDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Bank, err error) { + buf := make([]*model.Bank, 0, batchSize) + err = b.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (b bankDo) FindInBatches(result *[]*model.Bank, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return b.DO.FindInBatches(result, batchSize, fc) +} + +func (b bankDo) Attrs(attrs ...field.AssignExpr) IBankDo { + return b.withDO(b.DO.Attrs(attrs...)) +} + +func (b bankDo) Assign(attrs ...field.AssignExpr) IBankDo { + return b.withDO(b.DO.Assign(attrs...)) +} + +func (b bankDo) Joins(fields ...field.RelationField) IBankDo { + for _, _f := range fields { + b = *b.withDO(b.DO.Joins(_f)) + } + return &b +} + +func (b bankDo) Preload(fields ...field.RelationField) IBankDo { + for _, _f := range fields { + b = *b.withDO(b.DO.Preload(_f)) + } + return &b +} + +func (b bankDo) FirstOrInit() (*model.Bank, error) { + if result, err := b.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.Bank), nil + } +} + +func (b bankDo) FirstOrCreate() (*model.Bank, error) { + if result, err := b.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.Bank), nil + } +} + +func (b bankDo) FindByPage(offset int, limit int) (result []*model.Bank, 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 +} + +func (b bankDo) 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 +} + +func (b bankDo) Scan(result interface{}) (err error) { + return b.DO.Scan(result) +} + +func (b bankDo) Delete(models ...*model.Bank) (result gen.ResultInfo, err error) { + return b.DO.Delete(models) +} + +func (b *bankDo) withDO(do gen.Dao) *bankDo { + b.DO = *do.(*gen.DO) + return b +} \ No newline at end of file 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..a28c0343 --- /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/gen_test.go b/tests/.expect/dal_7/query/gen_test.go new file mode 100644 index 00000000..2ecba939 --- /dev/null +++ b/tests/.expect/dal_7/query/gen_test.go @@ -0,0 +1,122 @@ +// 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" + "fmt" + "reflect" + "sync" + "testing" + + "gorm.io/driver/sqlite" + "gorm.io/gorm" +) + +type Input struct { + Args []interface{} +} + +type Expectation struct { + Ret []interface{} +} + +type TestCase struct { + Input + Expectation +} + +const _gen_test_db_name = "gen_test.db" + +var _gen_test_db *gorm.DB +var _gen_test_once sync.Once + +func init() { + InitializeDB() + _gen_test_db.AutoMigrate(&_another{}) +} + +func InitializeDB() { + _gen_test_once.Do(func() { + var err error + _gen_test_db, err = gorm.Open(sqlite.Open(_gen_test_db_name), &gorm.Config{}) + if err != nil { + panic(fmt.Errorf("open sqlite %q fail: %w", _gen_test_db_name, err)) + } + }) +} + +func assert(t *testing.T, methodName string, res, exp interface{}) { + if !reflect.DeepEqual(res, exp) { + t.Errorf("%v() gotResult = %v, want %v", methodName, res, exp) + } +} + +type _another struct { + ID uint64 `gorm:"primaryKey"` +} + +func (*_another) TableName() string { return "another_for_unit_test" } + +func Test_Available(t *testing.T) { + if !Use(_gen_test_db).Available() { + t.Errorf("query.Available() == false") + } +} + +func Test_WithContext(t *testing.T) { + query := Use(_gen_test_db) + if !query.Available() { + t.Errorf("query Use(_gen_test_db) fail: query.Available() == false") + } + + type Content string + var key, value Content = "gen_tag", "unit_test" + qCtx := query.WithContext(context.WithValue(context.Background(), key, value)) + + for _, ctx := range []context.Context{ + qCtx.Bank.UnderlyingDB().Statement.Context, + qCtx.CreditCard.UnderlyingDB().Statement.Context, + qCtx.Customer.UnderlyingDB().Statement.Context, + qCtx.Person.UnderlyingDB().Statement.Context, + qCtx.User.UnderlyingDB().Statement.Context, + } { + if v := ctx.Value(key); v != value { + t.Errorf("get value from context fail, expect %q, got %q", value, v) + } + } +} + +func Test_Transaction(t *testing.T) { + query := Use(_gen_test_db) + if !query.Available() { + t.Errorf("query Use(_gen_test_db) fail: query.Available() == false") + } + + err := query.Transaction(func(tx *Query) error { return nil }) + if err != nil { + t.Errorf("query.Transaction execute fail: %s", err) + } + + tx := query.Begin() + + err = tx.SavePoint("point") + if err != nil { + t.Errorf("query tx SavePoint fail: %s", err) + } + err = tx.RollbackTo("point") + if err != nil { + t.Errorf("query tx RollbackTo fail: %s", err) + } + err = tx.Commit() + if err != nil { + t.Errorf("query tx Commit fail: %s", err) + } + + err = query.Begin().Rollback() + if err != nil { + t.Errorf("query tx Rollback fail: %s", err) + } +} 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..d5b44843 --- /dev/null +++ b/tests/.expect/dal_7/query/users.gen.go @@ -0,0 +1,912 @@ +// 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/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + "gorm.io/gen/helper" + + "gorm.io/plugin/dbresolver" + + "gorm.io/gen/tests/.gen/dal_4/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 +} \ No newline at end of file diff --git a/tests/.expect/dal_7/query/users.gen_test.go b/tests/.expect/dal_7/query/users.gen_test.go new file mode 100644 index 00000000..2c9a7c44 --- /dev/null +++ b/tests/.expect/dal_7/query/users.gen_test.go @@ -0,0 +1,564 @@ +// 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" + "fmt" + "strconv" + "testing" + "time" + + "gorm.io/gen" + "gorm.io/gen/field" + "gorm.io/gen/tests/.gen/dal_4/model" + "gorm.io/gorm/clause" +) + +func init() { + InitializeDB() + err := _gen_test_db.AutoMigrate(&model.User{}) + if err != nil { + fmt.Printf("Error: AutoMigrate(&model.User{}) fail: %s", err) + } +} + +func Test_userQuery(t *testing.T) { + user := newUser(_gen_test_db) + user = *user.As(user.TableName()) + _do := user.WithContext(context.Background()).Debug() + + primaryKey := field.NewString(user.TableName(), clause.PrimaryKey) + _, err := _do.Unscoped().Where(primaryKey.IsNotNull()).Delete() + if err != nil { + t.Error("clean table fail:", err) + return + } + + _, ok := user.GetFieldByName("") + if ok { + t.Error("GetFieldByName(\"\") from user success") + } + + err = _do.Create(&model.User{}) + if err != nil { + t.Error("create item in table fail:", err) + } + + err = _do.Save(&model.User{}) + if err != nil { + t.Error("create item in table fail:", err) + } + + err = _do.CreateInBatches([]*model.User{{}, {}}, 10) + if err != nil { + t.Error("create item in table fail:", err) + } + + _, err = _do.Select(user.ALL).Take() + if err != nil { + t.Error("Take() on table fail:", err) + } + + _, err = _do.First() + if err != nil { + t.Error("First() on table fail:", err) + } + + _, err = _do.Last() + if err != nil { + t.Error("First() on table fail:", err) + } + + _, err = _do.Where(primaryKey.IsNotNull()).FindInBatch(10, func(tx gen.Dao, batch int) error { return nil }) + if err != nil { + t.Error("FindInBatch() on table fail:", err) + } + + err = _do.Where(primaryKey.IsNotNull()).FindInBatches(&[]*model.User{}, 10, func(tx gen.Dao, batch int) error { return nil }) + if err != nil { + t.Error("FindInBatches() on table fail:", err) + } + + _, err = _do.Select(user.ALL).Where(primaryKey.IsNotNull()).Order(primaryKey.Desc()).Find() + if err != nil { + t.Error("Find() on table fail:", err) + } + + _, err = _do.Distinct(primaryKey).Take() + if err != nil { + t.Error("select Distinct() on table fail:", err) + } + + _, err = _do.Select(user.ALL).Omit(primaryKey).Take() + if err != nil { + t.Error("Omit() on table fail:", err) + } + + _, err = _do.Group(primaryKey).Find() + if err != nil { + t.Error("Group() on table fail:", err) + } + + _, err = _do.Scopes(func(dao gen.Dao) gen.Dao { return dao.Where(primaryKey.IsNotNull()) }).Find() + if err != nil { + t.Error("Scopes() on table fail:", err) + } + + _, _, err = _do.FindByPage(0, 1) + if err != nil { + t.Error("FindByPage() on table fail:", err) + } + + _, err = _do.ScanByPage(&model.User{}, 0, 1) + if err != nil { + t.Error("ScanByPage() on table fail:", err) + } + + _, err = _do.Attrs(primaryKey).Assign(primaryKey).FirstOrInit() + if err != nil { + t.Error("FirstOrInit() on table fail:", err) + } + + _, err = _do.Attrs(primaryKey).Assign(primaryKey).FirstOrCreate() + if err != nil { + t.Error("FirstOrCreate() on table fail:", err) + } + + var _a _another + var _aPK = field.NewString(_a.TableName(), "id") + + err = _do.Join(&_a, primaryKey.EqCol(_aPK)).Scan(map[string]interface{}{}) + if err != nil { + t.Error("Join() on table fail:", err) + } + + err = _do.LeftJoin(&_a, primaryKey.EqCol(_aPK)).Scan(map[string]interface{}{}) + if err != nil { + t.Error("LeftJoin() on table fail:", err) + } + + _, err = _do.Not().Or().Clauses().Take() + if err != nil { + t.Error("Not/Or/Clauses on table fail:", err) + } +} + +var UserFindByUsersTestCase = []TestCase{} + +func Test_user_FindByUsers(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserFindByUsersTestCase { + t.Run("FindByUsers_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.FindByUsers(tt.Input.Args[0].(model.User)) + assert(t, "FindByUsers", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserFindByComplexIfTestCase = []TestCase{} + +func Test_user_FindByComplexIf(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserFindByComplexIfTestCase { + t.Run("FindByComplexIf_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.FindByComplexIf(tt.Input.Args[0].(*model.User)) + assert(t, "FindByComplexIf", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserFindByIfTimeTestCase = []TestCase{} + +func Test_user_FindByIfTime(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserFindByIfTimeTestCase { + t.Run("FindByIfTime_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.FindByIfTime(tt.Input.Args[0].(time.Time)) + assert(t, "FindByIfTime", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserTestForTestCase = []TestCase{} + +func Test_user_TestFor(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestForTestCase { + t.Run("TestFor_"+strconv.Itoa(i), func(t *testing.T) { + res1, res2 := do.TestFor(tt.Input.Args[0].([]string)) + assert(t, "TestFor", res1, tt.Expectation.Ret[0]) + assert(t, "TestFor", res2, tt.Expectation.Ret[1]) + }) + } +} + +var UserTestForKeyTestCase = []TestCase{} + +func Test_user_TestForKey(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestForKeyTestCase { + t.Run("TestForKey_"+strconv.Itoa(i), func(t *testing.T) { + res1, res2 := do.TestForKey(tt.Input.Args[0].([]string), tt.Input.Args[1].(string), tt.Input.Args[2].(string)) + assert(t, "TestForKey", res1, tt.Expectation.Ret[0]) + assert(t, "TestForKey", res2, tt.Expectation.Ret[1]) + }) + } +} + +var UserTestForOrTestCase = []TestCase{} + +func Test_user_TestForOr(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestForOrTestCase { + t.Run("TestForOr_"+strconv.Itoa(i), func(t *testing.T) { + res1, res2 := do.TestForOr(tt.Input.Args[0].([]string)) + assert(t, "TestForOr", res1, tt.Expectation.Ret[0]) + assert(t, "TestForOr", res2, tt.Expectation.Ret[1]) + }) + } +} + +var UserTestIfInForTestCase = []TestCase{} + +func Test_user_TestIfInFor(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestIfInForTestCase { + t.Run("TestIfInFor_"+strconv.Itoa(i), func(t *testing.T) { + res1, res2 := do.TestIfInFor(tt.Input.Args[0].([]string), tt.Input.Args[1].(string)) + assert(t, "TestIfInFor", res1, tt.Expectation.Ret[0]) + assert(t, "TestIfInFor", res2, tt.Expectation.Ret[1]) + }) + } +} + +var UserTestForInIfTestCase = []TestCase{} + +func Test_user_TestForInIf(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestForInIfTestCase { + t.Run("TestForInIf_"+strconv.Itoa(i), func(t *testing.T) { + res1, res2 := do.TestForInIf(tt.Input.Args[0].([]string), tt.Input.Args[1].(string)) + assert(t, "TestForInIf", res1, tt.Expectation.Ret[0]) + assert(t, "TestForInIf", res2, tt.Expectation.Ret[1]) + }) + } +} + +var UserTestForInWhereTestCase = []TestCase{} + +func Test_user_TestForInWhere(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestForInWhereTestCase { + t.Run("TestForInWhere_"+strconv.Itoa(i), func(t *testing.T) { + res1, res2 := do.TestForInWhere(tt.Input.Args[0].([]string), tt.Input.Args[1].(string), tt.Input.Args[2].(string)) + assert(t, "TestForInWhere", res1, tt.Expectation.Ret[0]) + assert(t, "TestForInWhere", res2, tt.Expectation.Ret[1]) + }) + } +} + +var UserTestForUserListTestCase = []TestCase{} + +func Test_user_TestForUserList(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestForUserListTestCase { + t.Run("TestForUserList_"+strconv.Itoa(i), func(t *testing.T) { + res1, res2 := do.TestForUserList(tt.Input.Args[0].(*[]model.User), tt.Input.Args[1].(string)) + assert(t, "TestForUserList", res1, tt.Expectation.Ret[0]) + assert(t, "TestForUserList", res2, tt.Expectation.Ret[1]) + }) + } +} + +var UserTestForMapTestCase = []TestCase{} + +func Test_user_TestForMap(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestForMapTestCase { + t.Run("TestForMap_"+strconv.Itoa(i), func(t *testing.T) { + res1, res2 := do.TestForMap(tt.Input.Args[0].(map[string]string), tt.Input.Args[1].(string)) + assert(t, "TestForMap", res1, tt.Expectation.Ret[0]) + assert(t, "TestForMap", res2, tt.Expectation.Ret[1]) + }) + } +} + +var UserTestIfInIfTestCase = []TestCase{} + +func Test_user_TestIfInIf(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestIfInIfTestCase { + t.Run("TestIfInIf_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.TestIfInIf(tt.Input.Args[0].(string)) + assert(t, "TestIfInIf", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserTestMoreForTestCase = []TestCase{} + +func Test_user_TestMoreFor(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestMoreForTestCase { + t.Run("TestMoreFor_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.TestMoreFor(tt.Input.Args[0].([]string), tt.Input.Args[1].([]int)) + assert(t, "TestMoreFor", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserTestMoreFor2TestCase = []TestCase{} + +func Test_user_TestMoreFor2(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestMoreFor2TestCase { + t.Run("TestMoreFor2_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.TestMoreFor2(tt.Input.Args[0].([]string), tt.Input.Args[1].([]int)) + assert(t, "TestMoreFor2", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserTestForInSetTestCase = []TestCase{} + +func Test_user_TestForInSet(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestForInSetTestCase { + t.Run("TestForInSet_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.TestForInSet(tt.Input.Args[0].([]model.User)) + assert(t, "TestForInSet", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserTestInsertMoreInfoTestCase = []TestCase{} + +func Test_user_TestInsertMoreInfo(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestInsertMoreInfoTestCase { + t.Run("TestInsertMoreInfo_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.TestInsertMoreInfo(tt.Input.Args[0].([]model.User)) + assert(t, "TestInsertMoreInfo", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserTestIfElseForTestCase = []TestCase{} + +func Test_user_TestIfElseFor(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestIfElseForTestCase { + t.Run("TestIfElseFor_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.TestIfElseFor(tt.Input.Args[0].(string), tt.Input.Args[1].([]model.User)) + assert(t, "TestIfElseFor", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserTestForLikeTestCase = []TestCase{} + +func Test_user_TestForLike(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserTestForLikeTestCase { + t.Run("TestForLike_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.TestForLike(tt.Input.Args[0].([]string)) + assert(t, "TestForLike", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserAddUserTestCase = []TestCase{} + +func Test_user_AddUser(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserAddUserTestCase { + t.Run("AddUser_"+strconv.Itoa(i), func(t *testing.T) { + res1, res2 := do.AddUser(tt.Input.Args[0].(string), tt.Input.Args[1].(int)) + assert(t, "AddUser", res1, tt.Expectation.Ret[0]) + assert(t, "AddUser", res2, tt.Expectation.Ret[1]) + }) + } +} + +var UserAddUser1TestCase = []TestCase{} + +func Test_user_AddUser1(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserAddUser1TestCase { + t.Run("AddUser1_"+strconv.Itoa(i), func(t *testing.T) { + res1, res2 := do.AddUser1(tt.Input.Args[0].(string), tt.Input.Args[1].(int)) + assert(t, "AddUser1", res1, tt.Expectation.Ret[0]) + assert(t, "AddUser1", res2, tt.Expectation.Ret[1]) + }) + } +} + +var UserAddUser2TestCase = []TestCase{} + +func Test_user_AddUser2(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserAddUser2TestCase { + t.Run("AddUser2_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.AddUser2(tt.Input.Args[0].(string), tt.Input.Args[1].(int)) + assert(t, "AddUser2", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserAddUser3TestCase = []TestCase{} + +func Test_user_AddUser3(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserAddUser3TestCase { + t.Run("AddUser3_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.AddUser3(tt.Input.Args[0].(string), tt.Input.Args[1].(int)) + assert(t, "AddUser3", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserAddUser4TestCase = []TestCase{} + +func Test_user_AddUser4(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserAddUser4TestCase { + t.Run("AddUser4_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.AddUser4(tt.Input.Args[0].(string), tt.Input.Args[1].(int)) + assert(t, "AddUser4", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserAddUser5TestCase = []TestCase{} + +func Test_user_AddUser5(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserAddUser5TestCase { + t.Run("AddUser5_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.AddUser5(tt.Input.Args[0].(string), tt.Input.Args[1].(int)) + assert(t, "AddUser5", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserAddUser6TestCase = []TestCase{} + +func Test_user_AddUser6(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserAddUser6TestCase { + t.Run("AddUser6_"+strconv.Itoa(i), func(t *testing.T) { + res1, res2 := do.AddUser6(tt.Input.Args[0].(string), tt.Input.Args[1].(int)) + assert(t, "AddUser6", res1, tt.Expectation.Ret[0]) + assert(t, "AddUser6", res2, tt.Expectation.Ret[1]) + }) + } +} + +var UserFindByIDTestCase = []TestCase{} + +func Test_user_FindByID(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserFindByIDTestCase { + t.Run("FindByID_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.FindByID(tt.Input.Args[0].(int)) + assert(t, "FindByID", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserLikeSearchTestCase = []TestCase{} + +func Test_user_LikeSearch(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserLikeSearchTestCase { + t.Run("LikeSearch_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.LikeSearch(tt.Input.Args[0].(string)) + assert(t, "LikeSearch", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserInSearchTestCase = []TestCase{} + +func Test_user_InSearch(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserInSearchTestCase { + t.Run("InSearch_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.InSearch(tt.Input.Args[0].([]string)) + assert(t, "InSearch", res1, tt.Expectation.Ret[0]) + }) + } +} + +var UserColumnSearchTestCase = []TestCase{} + +func Test_user_ColumnSearch(t *testing.T) { + user := newUser(_gen_test_db) + do := user.WithContext(context.Background()).Debug() + + for i, tt := range UserColumnSearchTestCase { + t.Run("ColumnSearch_"+strconv.Itoa(i), func(t *testing.T) { + res1 := do.ColumnSearch(tt.Input.Args[0].(string), tt.Input.Args[1].([]string)) + assert(t, "ColumnSearch", res1, tt.Expectation.Ret[0]) + }) + } +} diff --git a/tests/generate_test.go b/tests/generate_test.go index 9b1bec22..08382afe 100644 --- a/tests/generate_test.go +++ b/tests/generate_test.go @@ -118,6 +118,23 @@ 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, + + WithUnitTest: true, + + 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) { From 989656884901ad8c0b5a4e87c48c5b6f755f88ec Mon Sep 17 00:00:00 2001 From: qqxhb <1252905006@qq.com> Date: Wed, 15 Jan 2025 20:28:23 +0800 Subject: [PATCH 13/18] feat: version --- go.mod | 6 ++++-- go.sum | 13 ++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) 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= From 18c4d3033c5683e3ed211dfa126383cb5b055b8b Mon Sep 17 00:00:00 2001 From: qqxhb <1252905006@qq.com> Date: Wed, 15 Jan 2025 21:07:43 +0800 Subject: [PATCH 14/18] feat: add field method --- field/field.go | 2 +- field/generics.go | 10 ++++++++++ field/number.go | 5 +++++ field/string.go | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/field/field.go b/field/field.go index 0c5c073c..aa8be782 100644 --- a/field/field.go +++ b/field/field.go @@ -3,4 +3,4 @@ package field import "database/sql/driver" // Field a standard field struct -type Field genericsField[driver.Valuer] +type Field = genericsField[driver.Valuer] diff --git a/field/generics.go b/field/generics.go index adbbc06f..80698fe3 100644 --- a/field/generics.go +++ b/field/generics.go @@ -28,6 +28,11 @@ 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}} @@ -73,6 +78,11 @@ 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 { diff --git a/field/number.go b/field/number.go index ac78a17e..83d87d01 100644 --- a/field/number.go +++ b/field/number.go @@ -137,3 +137,8 @@ func (field Number[T]) Floor() Number[T] { 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/string.go b/field/string.go index cdb56a3c..8cbaddd5 100644 --- a/field/string.go +++ b/field/string.go @@ -83,6 +83,41 @@ func (field Chars[T]) Concat(before, after string) Chars[T] { } } +// Substring https://dev.mysql.com/doc/refman/8.4/en/string-functions.html#function_substring +func (field Chars[T]) Substring(params ...int) Chars[T] { + if len(params) == 0 { + return field + } + if len(params) == 1 { + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{ + SQL: fmt.Sprintf("SUBSTRING(?,%d)", params[0]), + Vars: []interface{}{field.RawExpr()}, + }}}} + } + 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 +// https://dev.mysql.com/doc/refman/8.4/en/string-functions.html#function_substring +func (field Chars[T]) Substr(params ...int) Chars[T] { + if len(params) == 0 { + return field + } + if len(params) == 1 { + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{ + SQL: fmt.Sprintf("SUBSTR(?,%d)", params[0]), + Vars: []interface{}{field.RawExpr()}, + }}}} + } + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{ + SQL: fmt.Sprintf("SUBSTR(?,%d,%d)", params[0], params[1]), + Vars: []interface{}{field.RawExpr()}, + }}}} +} + // 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] { @@ -91,3 +126,18 @@ func (field Chars[T]) SubstringIndex(delim string, count int) Chars[T] { Vars: []interface{}{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 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 Chars[T]) Upper() Chars[T] { + return Chars[T]{genericsField: genericsField[T]{expr{e: clause.Expr{SQL: "UPPER(?)", Vars: []interface{}{field.RawExpr()}}}}} +} From c0fbf3f0688c6097d00a6dec8b88eaa5c485f875 Mon Sep 17 00:00:00 2001 From: qqxhb <1252905006@qq.com> Date: Wed, 15 Jan 2025 21:38:01 +0800 Subject: [PATCH 15/18] feat: fmt --- generics.go | 42 +++++++++++++++++++++++++++++++++++++ internal/template/struct.go | 4 +++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/generics.go b/generics.go index e9c9fbb8..7a236150 100644 --- a/generics.go +++ b/generics.go @@ -82,98 +82,122 @@ type GenericsDo[T IGenericsDo[T, E], E any] struct { 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 @@ -181,6 +205,7 @@ func (b GenericsDo[T, E]) Create(values ...E) error { return b.DO.Create(values) } +// CreateInBatches ... func (b GenericsDo[T, E]) CreateInBatches(values []E, batchSize int) error { return b.DO.CreateInBatches(values, batchSize) } @@ -194,6 +219,7 @@ func (b GenericsDo[T, E]) Save(values ...E) error { 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 { @@ -203,6 +229,7 @@ func (b GenericsDo[T, E]) First() (E, error) { } } +// Take ... func (b GenericsDo[T, E]) Take() (E, error) { var e E if result, err := b.DO.Take(); err != nil { @@ -212,6 +239,7 @@ func (b GenericsDo[T, E]) Take() (E, error) { } } +// Last ... func (b GenericsDo[T, E]) Last() (E, error) { var e E if result, err := b.DO.Last(); err != nil { @@ -221,11 +249,13 @@ func (b GenericsDo[T, E]) Last() (E, error) { } } +// 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 { @@ -235,18 +265,22 @@ func (b GenericsDo[T, E]) FindInBatch(batchSize int, fc func(tx Dao, batch int) 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 { @@ -255,6 +289,7 @@ func (b GenericsDo[T, E]) Joins(fields ...field.RelationField) T { return b.withDO(do) } +// Preload ... func (b GenericsDo[T, E]) Preload(fields ...field.RelationField) T { var do Dao = &b.DO for _, _f := range fields { @@ -263,6 +298,7 @@ func (b GenericsDo[T, E]) Preload(fields ...field.RelationField) T { return b.withDO(do) } +// FirstOrInit ... func (b GenericsDo[T, E]) FirstOrInit() (E, error) { var e E if result, err := b.DO.FirstOrInit(); err != nil { @@ -272,6 +308,7 @@ func (b GenericsDo[T, E]) FirstOrInit() (E, error) { } } +// FirstOrCreate ... func (b GenericsDo[T, E]) FirstOrCreate() (E, error) { var e E if result, err := b.DO.FirstOrCreate(); err != nil { @@ -281,6 +318,7 @@ func (b GenericsDo[T, E]) FirstOrCreate() (E, error) { } } +// 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 { @@ -296,6 +334,7 @@ func (b GenericsDo[T, E]) FindByPage(offset int, limit int) (result []E, count i 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 { @@ -305,14 +344,17 @@ func (b GenericsDo[T, E]) ScanByPage(result interface{}, offset int, limit int) 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)) diff --git a/internal/template/struct.go b/internal/template/struct.go index 6475bf99..c4f18120 100644 --- a/internal/template/struct.go +++ b/internal/template/struct.go @@ -30,7 +30,9 @@ const ( ` + getFieldMethod + fillFieldMapMethod + cloneMethod + replaceMethod + relationship // TableQueryIface table query interface - TableQueryIface = defineDoInterface + TableQueryIface = defineDoInterface + + // TableGenericQueryIface table generic query interface TableGenericQueryIface = defineGenericsDoInterface //DefineGenericsMethodStruct generics do struct From cd044493c756145123ea49564f54284587d49d0e Mon Sep 17 00:00:00 2001 From: qqxhb <1252905006@qq.com> Date: Wed, 15 Jan 2025 21:52:28 +0800 Subject: [PATCH 16/18] feat: test --- tests/.expect/dal_3/query/banks.gen.go | 2 +- tests/.expect/dal_7/query/gen.go | 22 ++++++++++----------- tests/.expect/dal_7/query/users.gen.go | 11 +++-------- tests/.expect/dal_7/query/users.gen_test.go | 2 +- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/tests/.expect/dal_3/query/banks.gen.go b/tests/.expect/dal_3/query/banks.gen.go index 1265fefb..c644b19a 100644 --- a/tests/.expect/dal_3/query/banks.gen.go +++ b/tests/.expect/dal_3/query/banks.gen.go @@ -400,4 +400,4 @@ func (b bankDo) Delete(models ...*model.Bank) (result gen.ResultInfo, err error) func (b *bankDo) withDO(do gen.Dao) *bankDo { b.DO = *do.(*gen.DO) return b -} \ No newline at end of file +} diff --git a/tests/.expect/dal_7/query/gen.go b/tests/.expect/dal_7/query/gen.go index a28c0343..a19d931b 100644 --- a/tests/.expect/dal_7/query/gen.go +++ b/tests/.expect/dal_7/query/gen.go @@ -16,8 +16,8 @@ import ( ) var ( - Q = new(Query) - User *user + Q = new(Query) + User *user ) func SetDefault(db *gorm.DB, opts ...gen.DOOption) { @@ -27,23 +27,23 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) { func Use(db *gorm.DB, opts ...gen.DOOption) *Query { return &Query{ - db: db, - User: newUser(db, opts...), + db: db, + User: newUser(db, opts...), } } type Query struct { db *gorm.DB - User user + 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), + db: db, + User: q.User.clone(db), } } @@ -57,18 +57,18 @@ func (q *Query) WriteDB() *Query { func (q *Query) ReplaceDB(db *gorm.DB) *Query { return &Query{ - db: db, - User: q.User.replaceDB(db), + db: db, + User: q.User.replaceDB(db), } } type queryCtx struct { - User IUserDo + User IUserDo } func (q *Query) WithContext(ctx context.Context) *queryCtx { return &queryCtx{ - User: q.User.WithContext(ctx), + User: q.User.WithContext(ctx), } } diff --git a/tests/.expect/dal_7/query/users.gen.go b/tests/.expect/dal_7/query/users.gen.go index d5b44843..46f8c75a 100644 --- a/tests/.expect/dal_7/query/users.gen.go +++ b/tests/.expect/dal_7/query/users.gen.go @@ -9,17 +9,12 @@ import ( "database/sql" "strings" - "gorm.io/gorm" - "gorm.io/gorm/clause" - "gorm.io/gorm/schema" - "gorm.io/gen" "gorm.io/gen/field" "gorm.io/gen/helper" + "gorm.io/gorm" - "gorm.io/plugin/dbresolver" - - "gorm.io/gen/tests/.gen/dal_4/model" + "gorm.io/gen/tests/.gen/dal_7/model" "time" ) @@ -909,4 +904,4 @@ func (u userDo) ColumnSearch(name string, names []string) (result []*model.User) _ = executeSQL return -} \ No newline at end of file +} diff --git a/tests/.expect/dal_7/query/users.gen_test.go b/tests/.expect/dal_7/query/users.gen_test.go index 2c9a7c44..cfe8b158 100644 --- a/tests/.expect/dal_7/query/users.gen_test.go +++ b/tests/.expect/dal_7/query/users.gen_test.go @@ -13,7 +13,7 @@ import ( "gorm.io/gen" "gorm.io/gen/field" - "gorm.io/gen/tests/.gen/dal_4/model" + "gorm.io/gen/tests/.gen/dal_7/model" "gorm.io/gorm/clause" ) From ecd818ad1e028f1f60f534b1bd50e674f3c6d3cc Mon Sep 17 00:00:00 2001 From: qqxhb <1252905006@qq.com> Date: Wed, 15 Jan 2025 22:01:02 +0800 Subject: [PATCH 17/18] feat: rm test --- tests/.expect/dal_7/query/gen_test.go | 122 ----- tests/.expect/dal_7/query/users.gen_test.go | 564 -------------------- tests/generate_test.go | 2 - 3 files changed, 688 deletions(-) delete mode 100644 tests/.expect/dal_7/query/gen_test.go delete mode 100644 tests/.expect/dal_7/query/users.gen_test.go diff --git a/tests/.expect/dal_7/query/gen_test.go b/tests/.expect/dal_7/query/gen_test.go deleted file mode 100644 index 2ecba939..00000000 --- a/tests/.expect/dal_7/query/gen_test.go +++ /dev/null @@ -1,122 +0,0 @@ -// 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" - "fmt" - "reflect" - "sync" - "testing" - - "gorm.io/driver/sqlite" - "gorm.io/gorm" -) - -type Input struct { - Args []interface{} -} - -type Expectation struct { - Ret []interface{} -} - -type TestCase struct { - Input - Expectation -} - -const _gen_test_db_name = "gen_test.db" - -var _gen_test_db *gorm.DB -var _gen_test_once sync.Once - -func init() { - InitializeDB() - _gen_test_db.AutoMigrate(&_another{}) -} - -func InitializeDB() { - _gen_test_once.Do(func() { - var err error - _gen_test_db, err = gorm.Open(sqlite.Open(_gen_test_db_name), &gorm.Config{}) - if err != nil { - panic(fmt.Errorf("open sqlite %q fail: %w", _gen_test_db_name, err)) - } - }) -} - -func assert(t *testing.T, methodName string, res, exp interface{}) { - if !reflect.DeepEqual(res, exp) { - t.Errorf("%v() gotResult = %v, want %v", methodName, res, exp) - } -} - -type _another struct { - ID uint64 `gorm:"primaryKey"` -} - -func (*_another) TableName() string { return "another_for_unit_test" } - -func Test_Available(t *testing.T) { - if !Use(_gen_test_db).Available() { - t.Errorf("query.Available() == false") - } -} - -func Test_WithContext(t *testing.T) { - query := Use(_gen_test_db) - if !query.Available() { - t.Errorf("query Use(_gen_test_db) fail: query.Available() == false") - } - - type Content string - var key, value Content = "gen_tag", "unit_test" - qCtx := query.WithContext(context.WithValue(context.Background(), key, value)) - - for _, ctx := range []context.Context{ - qCtx.Bank.UnderlyingDB().Statement.Context, - qCtx.CreditCard.UnderlyingDB().Statement.Context, - qCtx.Customer.UnderlyingDB().Statement.Context, - qCtx.Person.UnderlyingDB().Statement.Context, - qCtx.User.UnderlyingDB().Statement.Context, - } { - if v := ctx.Value(key); v != value { - t.Errorf("get value from context fail, expect %q, got %q", value, v) - } - } -} - -func Test_Transaction(t *testing.T) { - query := Use(_gen_test_db) - if !query.Available() { - t.Errorf("query Use(_gen_test_db) fail: query.Available() == false") - } - - err := query.Transaction(func(tx *Query) error { return nil }) - if err != nil { - t.Errorf("query.Transaction execute fail: %s", err) - } - - tx := query.Begin() - - err = tx.SavePoint("point") - if err != nil { - t.Errorf("query tx SavePoint fail: %s", err) - } - err = tx.RollbackTo("point") - if err != nil { - t.Errorf("query tx RollbackTo fail: %s", err) - } - err = tx.Commit() - if err != nil { - t.Errorf("query tx Commit fail: %s", err) - } - - err = query.Begin().Rollback() - if err != nil { - t.Errorf("query tx Rollback fail: %s", err) - } -} diff --git a/tests/.expect/dal_7/query/users.gen_test.go b/tests/.expect/dal_7/query/users.gen_test.go deleted file mode 100644 index cfe8b158..00000000 --- a/tests/.expect/dal_7/query/users.gen_test.go +++ /dev/null @@ -1,564 +0,0 @@ -// 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" - "fmt" - "strconv" - "testing" - "time" - - "gorm.io/gen" - "gorm.io/gen/field" - "gorm.io/gen/tests/.gen/dal_7/model" - "gorm.io/gorm/clause" -) - -func init() { - InitializeDB() - err := _gen_test_db.AutoMigrate(&model.User{}) - if err != nil { - fmt.Printf("Error: AutoMigrate(&model.User{}) fail: %s", err) - } -} - -func Test_userQuery(t *testing.T) { - user := newUser(_gen_test_db) - user = *user.As(user.TableName()) - _do := user.WithContext(context.Background()).Debug() - - primaryKey := field.NewString(user.TableName(), clause.PrimaryKey) - _, err := _do.Unscoped().Where(primaryKey.IsNotNull()).Delete() - if err != nil { - t.Error("clean table fail:", err) - return - } - - _, ok := user.GetFieldByName("") - if ok { - t.Error("GetFieldByName(\"\") from user success") - } - - err = _do.Create(&model.User{}) - if err != nil { - t.Error("create item in table fail:", err) - } - - err = _do.Save(&model.User{}) - if err != nil { - t.Error("create item in table fail:", err) - } - - err = _do.CreateInBatches([]*model.User{{}, {}}, 10) - if err != nil { - t.Error("create item in table fail:", err) - } - - _, err = _do.Select(user.ALL).Take() - if err != nil { - t.Error("Take() on table fail:", err) - } - - _, err = _do.First() - if err != nil { - t.Error("First() on table fail:", err) - } - - _, err = _do.Last() - if err != nil { - t.Error("First() on table fail:", err) - } - - _, err = _do.Where(primaryKey.IsNotNull()).FindInBatch(10, func(tx gen.Dao, batch int) error { return nil }) - if err != nil { - t.Error("FindInBatch() on table fail:", err) - } - - err = _do.Where(primaryKey.IsNotNull()).FindInBatches(&[]*model.User{}, 10, func(tx gen.Dao, batch int) error { return nil }) - if err != nil { - t.Error("FindInBatches() on table fail:", err) - } - - _, err = _do.Select(user.ALL).Where(primaryKey.IsNotNull()).Order(primaryKey.Desc()).Find() - if err != nil { - t.Error("Find() on table fail:", err) - } - - _, err = _do.Distinct(primaryKey).Take() - if err != nil { - t.Error("select Distinct() on table fail:", err) - } - - _, err = _do.Select(user.ALL).Omit(primaryKey).Take() - if err != nil { - t.Error("Omit() on table fail:", err) - } - - _, err = _do.Group(primaryKey).Find() - if err != nil { - t.Error("Group() on table fail:", err) - } - - _, err = _do.Scopes(func(dao gen.Dao) gen.Dao { return dao.Where(primaryKey.IsNotNull()) }).Find() - if err != nil { - t.Error("Scopes() on table fail:", err) - } - - _, _, err = _do.FindByPage(0, 1) - if err != nil { - t.Error("FindByPage() on table fail:", err) - } - - _, err = _do.ScanByPage(&model.User{}, 0, 1) - if err != nil { - t.Error("ScanByPage() on table fail:", err) - } - - _, err = _do.Attrs(primaryKey).Assign(primaryKey).FirstOrInit() - if err != nil { - t.Error("FirstOrInit() on table fail:", err) - } - - _, err = _do.Attrs(primaryKey).Assign(primaryKey).FirstOrCreate() - if err != nil { - t.Error("FirstOrCreate() on table fail:", err) - } - - var _a _another - var _aPK = field.NewString(_a.TableName(), "id") - - err = _do.Join(&_a, primaryKey.EqCol(_aPK)).Scan(map[string]interface{}{}) - if err != nil { - t.Error("Join() on table fail:", err) - } - - err = _do.LeftJoin(&_a, primaryKey.EqCol(_aPK)).Scan(map[string]interface{}{}) - if err != nil { - t.Error("LeftJoin() on table fail:", err) - } - - _, err = _do.Not().Or().Clauses().Take() - if err != nil { - t.Error("Not/Or/Clauses on table fail:", err) - } -} - -var UserFindByUsersTestCase = []TestCase{} - -func Test_user_FindByUsers(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserFindByUsersTestCase { - t.Run("FindByUsers_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.FindByUsers(tt.Input.Args[0].(model.User)) - assert(t, "FindByUsers", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserFindByComplexIfTestCase = []TestCase{} - -func Test_user_FindByComplexIf(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserFindByComplexIfTestCase { - t.Run("FindByComplexIf_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.FindByComplexIf(tt.Input.Args[0].(*model.User)) - assert(t, "FindByComplexIf", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserFindByIfTimeTestCase = []TestCase{} - -func Test_user_FindByIfTime(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserFindByIfTimeTestCase { - t.Run("FindByIfTime_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.FindByIfTime(tt.Input.Args[0].(time.Time)) - assert(t, "FindByIfTime", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserTestForTestCase = []TestCase{} - -func Test_user_TestFor(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestForTestCase { - t.Run("TestFor_"+strconv.Itoa(i), func(t *testing.T) { - res1, res2 := do.TestFor(tt.Input.Args[0].([]string)) - assert(t, "TestFor", res1, tt.Expectation.Ret[0]) - assert(t, "TestFor", res2, tt.Expectation.Ret[1]) - }) - } -} - -var UserTestForKeyTestCase = []TestCase{} - -func Test_user_TestForKey(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestForKeyTestCase { - t.Run("TestForKey_"+strconv.Itoa(i), func(t *testing.T) { - res1, res2 := do.TestForKey(tt.Input.Args[0].([]string), tt.Input.Args[1].(string), tt.Input.Args[2].(string)) - assert(t, "TestForKey", res1, tt.Expectation.Ret[0]) - assert(t, "TestForKey", res2, tt.Expectation.Ret[1]) - }) - } -} - -var UserTestForOrTestCase = []TestCase{} - -func Test_user_TestForOr(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestForOrTestCase { - t.Run("TestForOr_"+strconv.Itoa(i), func(t *testing.T) { - res1, res2 := do.TestForOr(tt.Input.Args[0].([]string)) - assert(t, "TestForOr", res1, tt.Expectation.Ret[0]) - assert(t, "TestForOr", res2, tt.Expectation.Ret[1]) - }) - } -} - -var UserTestIfInForTestCase = []TestCase{} - -func Test_user_TestIfInFor(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestIfInForTestCase { - t.Run("TestIfInFor_"+strconv.Itoa(i), func(t *testing.T) { - res1, res2 := do.TestIfInFor(tt.Input.Args[0].([]string), tt.Input.Args[1].(string)) - assert(t, "TestIfInFor", res1, tt.Expectation.Ret[0]) - assert(t, "TestIfInFor", res2, tt.Expectation.Ret[1]) - }) - } -} - -var UserTestForInIfTestCase = []TestCase{} - -func Test_user_TestForInIf(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestForInIfTestCase { - t.Run("TestForInIf_"+strconv.Itoa(i), func(t *testing.T) { - res1, res2 := do.TestForInIf(tt.Input.Args[0].([]string), tt.Input.Args[1].(string)) - assert(t, "TestForInIf", res1, tt.Expectation.Ret[0]) - assert(t, "TestForInIf", res2, tt.Expectation.Ret[1]) - }) - } -} - -var UserTestForInWhereTestCase = []TestCase{} - -func Test_user_TestForInWhere(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestForInWhereTestCase { - t.Run("TestForInWhere_"+strconv.Itoa(i), func(t *testing.T) { - res1, res2 := do.TestForInWhere(tt.Input.Args[0].([]string), tt.Input.Args[1].(string), tt.Input.Args[2].(string)) - assert(t, "TestForInWhere", res1, tt.Expectation.Ret[0]) - assert(t, "TestForInWhere", res2, tt.Expectation.Ret[1]) - }) - } -} - -var UserTestForUserListTestCase = []TestCase{} - -func Test_user_TestForUserList(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestForUserListTestCase { - t.Run("TestForUserList_"+strconv.Itoa(i), func(t *testing.T) { - res1, res2 := do.TestForUserList(tt.Input.Args[0].(*[]model.User), tt.Input.Args[1].(string)) - assert(t, "TestForUserList", res1, tt.Expectation.Ret[0]) - assert(t, "TestForUserList", res2, tt.Expectation.Ret[1]) - }) - } -} - -var UserTestForMapTestCase = []TestCase{} - -func Test_user_TestForMap(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestForMapTestCase { - t.Run("TestForMap_"+strconv.Itoa(i), func(t *testing.T) { - res1, res2 := do.TestForMap(tt.Input.Args[0].(map[string]string), tt.Input.Args[1].(string)) - assert(t, "TestForMap", res1, tt.Expectation.Ret[0]) - assert(t, "TestForMap", res2, tt.Expectation.Ret[1]) - }) - } -} - -var UserTestIfInIfTestCase = []TestCase{} - -func Test_user_TestIfInIf(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestIfInIfTestCase { - t.Run("TestIfInIf_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.TestIfInIf(tt.Input.Args[0].(string)) - assert(t, "TestIfInIf", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserTestMoreForTestCase = []TestCase{} - -func Test_user_TestMoreFor(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestMoreForTestCase { - t.Run("TestMoreFor_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.TestMoreFor(tt.Input.Args[0].([]string), tt.Input.Args[1].([]int)) - assert(t, "TestMoreFor", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserTestMoreFor2TestCase = []TestCase{} - -func Test_user_TestMoreFor2(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestMoreFor2TestCase { - t.Run("TestMoreFor2_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.TestMoreFor2(tt.Input.Args[0].([]string), tt.Input.Args[1].([]int)) - assert(t, "TestMoreFor2", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserTestForInSetTestCase = []TestCase{} - -func Test_user_TestForInSet(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestForInSetTestCase { - t.Run("TestForInSet_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.TestForInSet(tt.Input.Args[0].([]model.User)) - assert(t, "TestForInSet", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserTestInsertMoreInfoTestCase = []TestCase{} - -func Test_user_TestInsertMoreInfo(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestInsertMoreInfoTestCase { - t.Run("TestInsertMoreInfo_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.TestInsertMoreInfo(tt.Input.Args[0].([]model.User)) - assert(t, "TestInsertMoreInfo", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserTestIfElseForTestCase = []TestCase{} - -func Test_user_TestIfElseFor(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestIfElseForTestCase { - t.Run("TestIfElseFor_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.TestIfElseFor(tt.Input.Args[0].(string), tt.Input.Args[1].([]model.User)) - assert(t, "TestIfElseFor", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserTestForLikeTestCase = []TestCase{} - -func Test_user_TestForLike(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserTestForLikeTestCase { - t.Run("TestForLike_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.TestForLike(tt.Input.Args[0].([]string)) - assert(t, "TestForLike", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserAddUserTestCase = []TestCase{} - -func Test_user_AddUser(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserAddUserTestCase { - t.Run("AddUser_"+strconv.Itoa(i), func(t *testing.T) { - res1, res2 := do.AddUser(tt.Input.Args[0].(string), tt.Input.Args[1].(int)) - assert(t, "AddUser", res1, tt.Expectation.Ret[0]) - assert(t, "AddUser", res2, tt.Expectation.Ret[1]) - }) - } -} - -var UserAddUser1TestCase = []TestCase{} - -func Test_user_AddUser1(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserAddUser1TestCase { - t.Run("AddUser1_"+strconv.Itoa(i), func(t *testing.T) { - res1, res2 := do.AddUser1(tt.Input.Args[0].(string), tt.Input.Args[1].(int)) - assert(t, "AddUser1", res1, tt.Expectation.Ret[0]) - assert(t, "AddUser1", res2, tt.Expectation.Ret[1]) - }) - } -} - -var UserAddUser2TestCase = []TestCase{} - -func Test_user_AddUser2(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserAddUser2TestCase { - t.Run("AddUser2_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.AddUser2(tt.Input.Args[0].(string), tt.Input.Args[1].(int)) - assert(t, "AddUser2", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserAddUser3TestCase = []TestCase{} - -func Test_user_AddUser3(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserAddUser3TestCase { - t.Run("AddUser3_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.AddUser3(tt.Input.Args[0].(string), tt.Input.Args[1].(int)) - assert(t, "AddUser3", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserAddUser4TestCase = []TestCase{} - -func Test_user_AddUser4(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserAddUser4TestCase { - t.Run("AddUser4_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.AddUser4(tt.Input.Args[0].(string), tt.Input.Args[1].(int)) - assert(t, "AddUser4", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserAddUser5TestCase = []TestCase{} - -func Test_user_AddUser5(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserAddUser5TestCase { - t.Run("AddUser5_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.AddUser5(tt.Input.Args[0].(string), tt.Input.Args[1].(int)) - assert(t, "AddUser5", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserAddUser6TestCase = []TestCase{} - -func Test_user_AddUser6(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserAddUser6TestCase { - t.Run("AddUser6_"+strconv.Itoa(i), func(t *testing.T) { - res1, res2 := do.AddUser6(tt.Input.Args[0].(string), tt.Input.Args[1].(int)) - assert(t, "AddUser6", res1, tt.Expectation.Ret[0]) - assert(t, "AddUser6", res2, tt.Expectation.Ret[1]) - }) - } -} - -var UserFindByIDTestCase = []TestCase{} - -func Test_user_FindByID(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserFindByIDTestCase { - t.Run("FindByID_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.FindByID(tt.Input.Args[0].(int)) - assert(t, "FindByID", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserLikeSearchTestCase = []TestCase{} - -func Test_user_LikeSearch(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserLikeSearchTestCase { - t.Run("LikeSearch_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.LikeSearch(tt.Input.Args[0].(string)) - assert(t, "LikeSearch", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserInSearchTestCase = []TestCase{} - -func Test_user_InSearch(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserInSearchTestCase { - t.Run("InSearch_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.InSearch(tt.Input.Args[0].([]string)) - assert(t, "InSearch", res1, tt.Expectation.Ret[0]) - }) - } -} - -var UserColumnSearchTestCase = []TestCase{} - -func Test_user_ColumnSearch(t *testing.T) { - user := newUser(_gen_test_db) - do := user.WithContext(context.Background()).Debug() - - for i, tt := range UserColumnSearchTestCase { - t.Run("ColumnSearch_"+strconv.Itoa(i), func(t *testing.T) { - res1 := do.ColumnSearch(tt.Input.Args[0].(string), tt.Input.Args[1].([]string)) - assert(t, "ColumnSearch", res1, tt.Expectation.Ret[0]) - }) - } -} diff --git a/tests/generate_test.go b/tests/generate_test.go index 08382afe..2309808e 100644 --- a/tests/generate_test.go +++ b/tests/generate_test.go @@ -123,8 +123,6 @@ var generateCase = map[string]func(dir string) *gen.Generator{ OutPath: dir + "/query", Mode: gen.WithDefaultQuery | gen.WithGeneric, - WithUnitTest: true, - FieldNullable: true, FieldCoverable: true, FieldWithIndexTag: true, From e266bb4a525f254d86f0e4daacdc9a6e9b208ca8 Mon Sep 17 00:00:00 2001 From: qqxhb <1252905006@qq.com> Date: Mon, 24 Feb 2025 11:54:37 +0800 Subject: [PATCH 18/18] feat: NotRegxp -> NotRegexp --- field/export_test.go | 2 +- field/string.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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/string.go b/field/string.go index 8cbaddd5..dff04240 100644 --- a/field/string.go +++ b/field/string.go @@ -44,8 +44,8 @@ func (field Chars[T]) Regexp(value string) Expr { return field.regexp(value) } -// NotRegxp ... -func (field Chars[T]) NotRegxp(value string) Expr { +// NotRegexp ... +func (field Chars[T]) NotRegexp(value string) Expr { return expr{e: clause.Not(field.Regexp(value).expression())} }