Skip to content

Commit

Permalink
feat: add EXISTS and NOT EXISTS support
Browse files Browse the repository at this point in the history
  • Loading branch information
myml authored and tr1v3r committed Jan 13, 2022
1 parent 865f069 commit 131b2a8
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 6 deletions.
6 changes: 6 additions & 0 deletions README.ZH_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,12 @@ orders, err := o.WithContext(ctx).Where(u.Columns(o.Amount).Gt(o.WithContext(ctx
subQuery := u.WithContext(ctx).Select(u.Age.Avg()).Where(u.Name.Like("name%"))
users, err := u.WithContext(ctx).Select(u.Age.Avg().As("avgage")).Group(u.Name).Having(u.Columns(u.Age.Avg()).Gt(subQuery).Find()
// SELECT AVG(age) as avgage FROM `users` GROUP BY `name` HAVING AVG(age) > (SELECT AVG(age) FROM `users` WHERE name LIKE "name%")

// 找出交易数量在100和200之间的用户
subQuery1 := o.WithContext(ctx).Select(o.ID).Where(o.UserID.EqCol(u.ID), o.Amount.Gt(100))
subQuery2 := o.WithContext(ctx).Select(o.ID).Where(o.UserID.EqCol(u.ID), o.Amount.Gt(200))
u.WithContext(ctx).Exists(subQuery1).Not(u.WithContext(ctx).Exists(subQuery2)).Find()
// SELECT * FROM `users` WHERE EXISTS (SELECT `orders`.`id` FROM `orders` WHERE `orders`.`user_id` = `users`.`id` AND `orders`.`amount` > 100 AND `orders`.`deleted_at` IS NULL) AND NOT EXISTS (SELECT `orders`.`id` FROM `orders` WHERE `orders`.`user_id` = `users`.`id` AND `orders`.`amount` > 200 AND `orders`.`deleted_at` IS NULL) AND `users`.`deleted_at` IS NULL
```

###### <span id="from-subquery">From 子查询</span>
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,12 @@ orders, err := o.WithContext(ctx).Where(u.Columns(o.Amount).Gt(o.WithContext(ctx
subQuery := u.WithContext(ctx).Select(u.Age.Avg()).Where(u.Name.Like("name%"))
users, err := u.WithContext(ctx).Select(u.Age.Avg().As("avgage")).Group(u.Name).Having(u.Columns(u.Age.Avg()).Gt(subQuery).Find()
// SELECT AVG(age) as avgage FROM `users` GROUP BY `name` HAVING AVG(age) > (SELECT AVG(age) FROM `users` WHERE name LIKE "name%")

// Select users with orders between 100 and 200
subQuery1 := o.WithContext(ctx).Select(o.ID).Where(o.UserID.EqCol(u.ID), o.Amount.Gt(100))
subQuery2 := o.WithContext(ctx).Select(o.ID).Where(o.UserID.EqCol(u.ID), o.Amount.Gt(200))
u.WithContext(ctx).Exists(subQuery1).Not(u.WithContext(ctx).Exists(subQuery2)).Find()
// SELECT * FROM `users` WHERE EXISTS (SELECT `orders`.`id` FROM `orders` WHERE `orders`.`user_id` = `users`.`id` AND `orders`.`amount` > 100 AND `orders`.`deleted_at` IS NULL) AND NOT EXISTS (SELECT `orders`.`id` FROM `orders` WHERE `orders`.`user_id` = `users`.`id` AND `orders`.`amount` > 200 AND `orders`.`deleted_at` IS NULL) AND `users`.`deleted_at` IS NULL
```

###### From SubQuery
Expand Down
19 changes: 13 additions & 6 deletions field/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,22 @@ func AssignSubQuery(columns []Expr, subQuery *gorm.DB) AssignExpr {
type CompareOperate string

const (
EqOp CompareOperate = " = "
NeqOp CompareOperate = " <> "
GtOp CompareOperate = " > "
GteOp CompareOperate = " >= "
LtOp CompareOperate = " < "
LteOp CompareOperate = " <= "
EqOp CompareOperate = " = "
NeqOp CompareOperate = " <> "
GtOp CompareOperate = " > "
GteOp CompareOperate = " >= "
LtOp CompareOperate = " < "
LteOp CompareOperate = " <= "
ExistsOp CompareOperate = "EXISTS "
)

func CompareSubQuery(op CompareOperate, column Expr, subQuery *gorm.DB) Expr {
if op == ExistsOp {
return expr{e: clause.Expr{
SQL: fmt.Sprint(op, "(?)"),
Vars: []interface{}{subQuery},
}}
}
return expr{e: clause.Expr{
SQL: fmt.Sprint("?", op, "(?)"),
Vars: []interface{}{column.RawExpr(), subQuery},
Expand Down
4 changes: 4 additions & 0 deletions internal/template/method.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ func ({{.S}} {{.NewStructName}}Do) Where(conds ...gen.Condition) *{{.NewStructNa
return {{.S}}.withDO({{.S}}.DO.Where(conds...))
}
func ({{.S}} {{.NewStructName}}Do) Exists(subquery interface{UnderlyingDB() *gorm.DB}) *{{.NewStructName}}Do {
return {{.S}}.Where(field.CompareSubQuery(field.ExistsOp, nil, subquery.UnderlyingDB()))
}
func ({{.S}} {{.NewStructName}}Do) Order(conds ...field.Expr) *{{.NewStructName}}Do {
return {{.S}}.withDO({{.S}}.DO.Order(conds...))
}
Expand Down

0 comments on commit 131b2a8

Please sign in to comment.