wp-go/model/querycondition.go
2023-02-02 13:19:43 +08:00

142 lines
3.2 KiB
Go

package model
import (
"context"
"database/sql"
"fmt"
"strings"
)
// Finds 比 Find 多一个offset
//
// Conditions 中可用 Where Fields Group Having Join Order Offset Limit In 函数
func Finds[T Model](ctx context.Context, q *QueryCondition) (r []T, err error) {
var rr T
w := ""
var args []any
if q.where != nil {
w, args, err = q.where.ParseWhere(&q.in)
if err != nil {
return r, err
}
}
h := ""
if q.having != nil {
hh, arg, err := q.having.ParseWhere(&q.in)
if err != nil {
return r, err
}
args = append(args, arg...)
h = strings.Replace(hh, " where", " having", 1)
}
j := q.join.parseJoin()
groupBy := ""
if q.group != "" {
g := strings.Builder{}
g.WriteString(" group by ")
g.WriteString(q.group)
groupBy = g.String()
}
tp := "select %s from %s %s %s %s %s %s %s"
l := ""
if q.limit > 0 {
l = fmt.Sprintf(" limit %d", q.limit)
}
if q.offset > 0 {
l = fmt.Sprintf(" %s offset %d", l, q.offset)
}
sq := fmt.Sprintf(tp, q.fields, rr.Table(), j, w, groupBy, h, q.order.parseOrderBy(), l)
err = globalBb.Select(ctx, &r, sq, args...)
return
}
// ChunkFind 分片查询并直接返回所有结果
//
// Conditions 中可用 Where Fields Group Having Join Order Limit In 函数
func ChunkFind[T Model](ctx context.Context, perLimit int, q *QueryCondition) (r []T, err error) {
i := 1
var rr []T
var total int
var offset int
for {
if 1 == i {
rr, total, err = SimplePagination[T](ctx, q.where, q.fields, q.group, i, perLimit, q.order, q.join, q.having, q.in...)
} else {
rr, err = Finds[T](ctx, Conditions(
Where(q.where),
Fields(q.fields),
Group(q.group),
Having(q.having),
Join(q.join),
Order(q.order),
Offset(offset),
Limit(perLimit),
In(q.in...),
))
}
offset += perLimit
if (err != nil && err != sql.ErrNoRows) || len(rr) < 1 {
return
}
r = append(r, rr...)
if len(r) >= total {
break
}
i++
}
return
}
// Chunk 分片查询并函数过虑返回新类型的切片
//
// Conditions 中可用 Where Fields Group Having Join Order Limit In 函数
func Chunk[T Model, R any](ctx context.Context, perLimit int, fn func(rows T) (R, bool), q *QueryCondition) (r []R, err error) {
i := 1
var rr []T
var count int
var total int
var offset int
for {
if 1 == i {
rr, total, err = SimplePagination[T](ctx, q.where, q.fields, q.group, i, perLimit, q.order, q.join, q.having, q.in...)
} else {
rr, err = Finds[T](ctx, Conditions(
Where(q.where),
Fields(q.fields),
Group(q.group),
Having(q.having),
Join(q.join),
Order(q.order),
Offset(offset),
Limit(perLimit),
In(q.in...),
))
}
offset += perLimit
if (err != nil && err != sql.ErrNoRows) || len(rr) < 1 {
return
}
for _, t := range rr {
v, ok := fn(t)
if ok {
r = append(r, v)
}
}
count += len(rr)
if count >= total {
break
}
i++
}
return
}
// Pagination 同 SimplePagination
//
// Condition 中可使用 Where Fields Group Having Join Order Page Limit In 函数
func Pagination[T Model](ctx context.Context, q *QueryCondition) ([]T, int, error) {
return SimplePagination[T](ctx, q.where, q.fields, q.group, q.page, q.limit, q.order, q.join, q.having, q.in...)
}