122 lines
2.6 KiB
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
|
|
})
|
|
})
|
|
}
|