diff --git a/do_test.go b/do_test.go index 2c0c99a8..75f1e8a0 100644 --- a/do_test.go +++ b/do_test.go @@ -108,6 +108,30 @@ func TestDO_methods(t *testing.T) { Expr: teacher.Select(teacher.Name.As("n")).Distinct(), Result: "SELECT DISTINCT `teacher`.`name` AS `n`", }, + { + Expr: teacher.Select(field.ALL), + Result: "SELECT *", + }, + { + Expr: teacher.Select(field.ALL.Count()), + Result: "SELECT COUNT(*)", + }, + { + Expr: teacher.Select(field.ALL.Distinct().Count()), + Result: "SELECT COUNT(DISTINCT *)", + }, + { + Expr: teacher.Select(teacher.ALL), + Result: "SELECT `teacher`.*", + }, + { + Expr: teacher.Select(teacher.ALL.Count()), + Result: "SELECT COUNT(`teacher`.*)", + }, + { + Expr: teacher.Select(teacher.ALL.Distinct().Count()), + Result: "SELECT COUNT(DISTINCT `teacher`.*)", + }, { Expr: teacher.Select(teacher.ID.As("i"), teacher.Name.As("n")).Distinct(), Result: "SELECT DISTINCT `teacher`.`id` AS `i`,`teacher`.`name` AS `n`", diff --git a/field/asterisk.go b/field/asterisk.go new file mode 100644 index 00000000..a1f4f3f1 --- /dev/null +++ b/field/asterisk.go @@ -0,0 +1,56 @@ +package field + +import ( + "gorm.io/gorm" + "gorm.io/gorm/clause" +) + +// Asterisk a type of xxx.* +type Asterisk struct{ asteriskExpr } + +// Count count +func (a Asterisk) Count() Asterisk { + var expr *clause.Expr + switch { + case a.e != nil: + expr = &clause.Expr{ + SQL: "COUNT(?)", + Vars: []interface{}{a.e}, + } + case a.col.Table == "": + expr = &clause.Expr{SQL: "COUNT(*)"} + default: + expr = &clause.Expr{ + SQL: "COUNT(?.*)", + Vars: []interface{}{clause.Table{Name: a.col.Table}}, + } + } + return Asterisk{asteriskExpr{expr: a.setE(expr)}} +} + +// Distinct distinct +func (a Asterisk) Distinct() Asterisk { + var expr *clause.Expr + if a.col.Table == "" { + expr = &clause.Expr{SQL: "DISTINCT *"} + } else { + expr = &clause.Expr{ + SQL: "DISTINCT ?.*", + Vars: []interface{}{clause.Table{Name: a.col.Table}}, + } + } + return Asterisk{asteriskExpr{expr: a.setE(expr)}} +} + +type asteriskExpr struct{ expr } + +func (e asteriskExpr) BuildWithArgs(*gorm.Statement) (query sql, args []interface{}) { + // if e.expr has no expression it must be directly calling for "*" or "xxx.*" + if e.e != nil { + return "?", []interface{}{e.e} + } + if e.col.Table == "" { + return "*", nil + } + return "?.*", []interface{}{clause.Table{Name: e.col.Table}} +} diff --git a/field/export.go b/field/export.go index ec396609..dc3af70a 100644 --- a/field/export.go +++ b/field/export.go @@ -10,7 +10,7 @@ import ( var ( // Star a symbol of "*" - Star = NewString("", "*") + Star = NewAsterisk("") // ALL same with Star ALL = Star ) @@ -32,6 +32,11 @@ func NewField(table, column string, opts ...Option) Field { return Field{expr: expr{col: toColumn(table, column, opts...)}} } +// NewAsterisk create new * field +func NewAsterisk(table string, opts ...Option) Asterisk { + return Asterisk{asteriskExpr: asteriskExpr{expr{col: toColumn(table, "*", opts...)}}} +} + // ======================== integer ======================= // NewInt create new Int diff --git a/field/export_test.go b/field/export_test.go index bd0d02aa..e93156b0 100644 --- a/field/export_test.go +++ b/field/export_test.go @@ -125,6 +125,22 @@ func TestExpr_Build(t *testing.T) { Result: "`t1`.`a` + `t2`.`b`+? > `t`.`c`", ExpectedVars: []interface{}{int(1)}, }, + { + Expr: field.ALL.Count(), + Result: "COUNT(*)", + }, + { + Expr: field.ALL.Distinct().Count(), + Result: "COUNT(DISTINCT *)", + }, + { + Expr: field.NewAsterisk("user").Count(), + Result: "COUNT(`user`.*)", + }, + { + Expr: field.NewAsterisk("user").Distinct().Count(), + Result: "COUNT(DISTINCT `user`.*)", + }, // ======================== integer ======================== { Expr: field.NewUint("", "id"), diff --git a/generator_test.go b/generator_test.go index b0e1f1ad..1ab13f2c 100644 --- a/generator_test.go +++ b/generator_test.go @@ -85,6 +85,7 @@ func (TeacherRaw) TableName() string { type user struct { userDo + ALL field.Asterisk ID field.Uint Name field.String Age field.Int @@ -254,6 +255,7 @@ func (u userDo) FindByPage(offset int, limit int) (result []*user, count int64, var u = func() *user { u := user{ + ALL: field.NewAsterisk(""), ID: field.NewUint("", "id"), Name: field.NewString("", "name"), Age: field.NewInt("", "age"), @@ -270,6 +272,7 @@ var u = func() *user { type Student struct { DO + ALL field.Asterisk ID field.Int64 Name field.String Age field.Int @@ -278,6 +281,7 @@ type Student struct { var student = func() *Student { s := Student{ + ALL: field.NewAsterisk("student"), ID: field.NewInt64("student", "id"), Name: field.NewString("student", "name"), Age: field.NewInt("student", "age"), @@ -291,12 +295,14 @@ var student = func() *Student { type Teacher struct { DO + ALL field.Asterisk ID field.Int64 Name field.String } var teacher = func() Teacher { t := Teacher{ + ALL: field.NewAsterisk("teacher"), ID: field.NewInt64("teacher", "id"), Name: field.NewString("teacher", "name"), } diff --git a/internal/template/struct.go b/internal/template/struct.go index 2ae49ddf..43eb2d23 100644 --- a/internal/template/struct.go +++ b/internal/template/struct.go @@ -38,7 +38,7 @@ const ( _{{.QueryStructName}}.{{.QueryStructName}}Do.UseModel(&{{.StructInfo.Package}}.{{.StructInfo.Type}}{}) tableName := _{{.QueryStructName}}.{{.QueryStructName}}Do.TableName() - _{{$.QueryStructName}}.ALL = field.NewField(tableName, "*") + _{{$.QueryStructName}}.ALL = field.NewAsterisk(tableName) {{range .Fields -}} {{if not .IsRelation -}} {{- if .ColumnName -}}_{{$.QueryStructName}}.{{.Name}} = field.New{{.GenType}}(tableName, "{{.ColumnName}}"){{- end -}} @@ -57,7 +57,7 @@ const ( } ` fields = ` - ALL field.Field + ALL field.Asterisk {{range .Fields -}} {{if not .IsRelation -}} {{- if .ColumnName -}}{{.Name}} field.{{.GenType}}{{- end -}} @@ -83,7 +83,7 @@ func ({{.S}} {{.QueryStructName}}) As(alias string) *{{.QueryStructName}} { ` updateFieldMethod = ` func ({{.S}} *{{.QueryStructName}}) updateTableName(table string) *{{.QueryStructName}} { - {{.S}}.ALL = field.NewField(table, "*") + {{.S}}.ALL = field.NewAsterisk(table) {{range .Fields -}} {{if not .IsRelation -}} {{- if .ColumnName -}}{{$.S}}.{{.Name}} = field.New{{.GenType}}(table, "{{.ColumnName}}"){{- end -}}