import files, add README & LICENSE
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
package cursor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gitea.auvem.com/go-toolkit/dbx"
|
||||
"github.com/go-jet/jet/v2/mysql"
|
||||
)
|
||||
|
||||
// PageQuery runs a paginated SELECT and builds a Connection from the results.
|
||||
type PageQuery[T any, IE mysql.Expression, IC mysql.Column] struct {
|
||||
Sqlo dbx.Queryable
|
||||
Stmt mysql.SelectStatement
|
||||
Conds mysql.BoolExpression
|
||||
Cursor *Cursor[IE, IC]
|
||||
Default func() *Cursor[IE, IC]
|
||||
Limit int
|
||||
CountFn QueryCountFn
|
||||
ToEdge func(active *Cursor[IE, IC], item *T) (GenericCursor, error)
|
||||
// Scan runs the paginated query into dest. When nil, Run uses Stmt.Query.
|
||||
Scan func(stmt mysql.SelectStatement, dest *[]*T) error
|
||||
// AfterScan optionally transforms rows after the query and before building edges.
|
||||
AfterScan func(items []*T) ([]*T, error)
|
||||
}
|
||||
|
||||
// Run executes the paginated query and returns a Connection.
|
||||
func (q PageQuery[T, IE, IC]) Run() (*Connection[T], error) {
|
||||
active := q.Cursor
|
||||
if active == nil {
|
||||
active = q.Default()
|
||||
}
|
||||
|
||||
stmt := q.Stmt
|
||||
stmt.WHERE(q.Conds.AND(PaginateConds(q.Cursor)))
|
||||
stmt.ORDER_BY(OrderByClauses(active)...)
|
||||
if q.Limit > 0 {
|
||||
stmt = stmt.LIMIT(int64(q.Limit))
|
||||
}
|
||||
|
||||
var items []*T
|
||||
scan := q.Scan
|
||||
if scan == nil {
|
||||
scan = func(s mysql.SelectStatement, dest *[]*T) error {
|
||||
return s.Query(q.Sqlo, dest)
|
||||
}
|
||||
}
|
||||
if err := scan(stmt, &items); err != nil {
|
||||
return nil, fmt.Errorf("failed to run paginated query: %w", err)
|
||||
}
|
||||
|
||||
if q.AfterScan != nil {
|
||||
var err error
|
||||
items, err = q.AfterScan(items)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return BuildEdges(q.Sqlo, q.CountFn, items, func(item *T) (GenericCursor, error) {
|
||||
return q.ToEdge(active, item)
|
||||
})
|
||||
}
|
||||
|
||||
// ConnectionFromRelayArgs parses Relay pagination args and calls list with the
|
||||
// decoded cursor and limit. newZero supplies the cursor template for decoding
|
||||
// (same as NewXCursor).
|
||||
func ConnectionFromRelayArgs[T any, IE mysql.Expression, IC mysql.Column](
|
||||
after *string,
|
||||
first *int,
|
||||
newZero func() *Cursor[IE, IC],
|
||||
list func(cursor *Cursor[IE, IC], limit int) (*Connection[T], error),
|
||||
) (*Connection[T], error) {
|
||||
limit := 0
|
||||
if first != nil {
|
||||
limit = *first
|
||||
}
|
||||
|
||||
c, err := NewCursorFromAfterPtr(newZero, after)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list(c, limit)
|
||||
}
|
||||
Reference in New Issue
Block a user