core/internal/adapter/bun_utils.go

122 lines
2.6 KiB
Go

package adapter
import (
"errors"
"slices"
"github.com/uptrace/bun"
)
func appendODSetClauses(q *bun.InsertQuery) *bun.InsertQuery {
return q.Set("rank_att = EXCLUDED.rank_att").
Set("score_att = EXCLUDED.score_att").
Set("rank_def = EXCLUDED.rank_def").
Set("score_def = EXCLUDED.score_def").
Set("rank_sup = EXCLUDED.rank_sup").
Set("score_sup = EXCLUDED.score_sup").
Set("rank_total = EXCLUDED.rank_total").
Set("score_total = EXCLUDED.score_total")
}
func separateListResultAndNext[T any](res []T, limit int) ([]T, T) {
var next T
if len(res) > limit {
next = res[limit]
res = res[:limit]
}
return res, next
}
type sortDirection uint8
var errInvalidSortDirection = errors.New("invalid sort direction")
const (
sortDirectionASC sortDirection = iota + 1
sortDirectionDESC
)
func (sd sortDirection) Bun() bun.Safe {
return bun.Safe(sd.String())
}
func (sd sortDirection) String() string {
switch sd {
case sortDirectionASC:
return "ASC"
case sortDirectionDESC:
return "DESC"
default:
return "unknown"
}
}
type cursorPaginationApplierDataElement struct {
unique bool
column bun.Safe
direction sortDirection
value any
}
type cursorPaginationApplier struct {
data []cursorPaginationApplierDataElement
}
var errCursorNoUniqueFieldUsedForSorting = errors.New("cursor - no unique field used for sorting")
func (a cursorPaginationApplier) apply(q *bun.SelectQuery) *bun.SelectQuery {
if len(a.data) == 0 {
return q
}
uniqueIndex := slices.IndexFunc(a.data, func(element cursorPaginationApplierDataElement) bool {
return element.unique
})
if uniqueIndex < 0 {
return q.Err(errCursorNoUniqueFieldUsedForSorting)
}
return q.WhereGroup(" AND ", func(q *bun.SelectQuery) *bun.SelectQuery {
dataLen := len(a.data)
// based on https://github.com/prisma/prisma/issues/19159#issuecomment-1713389245
return q.WhereGroup(" OR ", func(q *bun.SelectQuery) *bun.SelectQuery {
for i := range dataLen {
q.WhereGroup(" OR ", func(q *bun.SelectQuery) *bun.SelectQuery {
current := a.data[i]
for j := range i {
prev := a.data[j]
q = q.Where("? = ?", prev.column, prev.value)
}
column := current.column
greaterSymbol := bun.Safe(">")
lessSymbol := bun.Safe("<")
if i == dataLen-1 {
greaterSymbol = ">="
lessSymbol = "<="
}
switch current.direction {
case sortDirectionASC:
q = q.Where("? ? ?", column, greaterSymbol, current.value)
case sortDirectionDESC:
q = q.Where("? ? ?", column, lessSymbol, current.value)
default:
return q.Err(errInvalidSortDirection)
}
return q
})
}
return q
})
})
}