Documentation
¶
Index ¶
- Constants
- func IsLastPage[CursorType Cursor, T any](initialPager *CursorPager[CursorType], resultSet []T) bool
- func IsNormalizedLimitMax(limit int, maxLimit int) (int, bool)
- func NormalizeLimit(limit int) int
- func NormalizeLimitMax(limit int, maxLimit int) int
- func TrimResultSet[CursorType Cursor, T any](initialPager *CursorPager[CursorType], resultSet []T) []T
- type ColumnAlias
- type ColumnMapping
- type Cursor
- type CursorElement
- type CursorPager
- func (c *CursorPager[CursorType]) GetCursor() CursorType
- func (c *CursorPager[CursorType]) GetDatasetLimit() int
- func (c *CursorPager[CursorType]) GetLimit() int
- func (c *CursorPager[CursorType]) GetSort() Orderings
- func (c *CursorPager[CursorType]) IsLookahead() bool
- func (c *CursorPager[CursorType]) IsUnlimited() bool
- func (c *CursorPager[CursorType]) Paginate(db *gorm.DB) (*gorm.DB, error)
- func (c *CursorPager[CursorType]) WithCursor(cursor CursorType) *CursorPager[CursorType]
- func (c *CursorPager[CursorType]) WithLimit(limit int) *CursorPager[CursorType]
- func (c *CursorPager[CursorType]) WithLookahead() *CursorPager[CursorType]
- func (c *CursorPager[CursorType]) WithSort(orderBy ...OrderBy) *CursorPager[CursorType]
- func (c *CursorPager[CursorType]) WithSubstitutedSort(orderBy ...OrderBy) *CursorPager[CursorType]
- func (c *CursorPager[CursorType]) WithUnlimited() *CursorPager[CursorType]
- type DefaultCursor
- func DecodeCursor(b64String string) (*DefaultCursor, error)
- func NewCursor(elements ...CursorElement) *DefaultCursor
- func NewDefaultCursor(elements ...CursorElement) *DefaultCursor
- func NextPageCursor[T any](initialPager *CursorPager[*DefaultCursor], resultSet []T, getters Getters[T]) ([]T, *DefaultCursor, error)
- func (c *DefaultCursor) Apply(db *gorm.DB) *gorm.DB
- func (c *DefaultCursor) GetElements() []CursorElement
- func (c *DefaultCursor) IsEmpty() bool
- func (c *DefaultCursor) String() string
- func (c *DefaultCursor) ToSQL() (string, []driver.Value)
- func (c *DefaultCursor) WithElements(elements []CursorElement) *DefaultCursor
- type Direction
- type Getters
- type Operator
- type OrderBy
- type Orderings
- type PaginationResult
- type PseudoCursor
- type RawCursorPager
Constants ¶
const ( NoLimit = -1 MaxLimit = 100 DefaultLimit = 10 )
Variables ¶
This section is empty.
Functions ¶
func IsLastPage ¶
func IsLastPage[CursorType Cursor, T any](initialPager *CursorPager[CursorType], resultSet []T) bool
IsLastPage returns true if the result set is the last page in the dataset.
The last page is determined by one of two conditions:
- The number of returned records is less than Limit.
- Lookahead = true and the number of returned records is less than or equal to Limit.
In these cases, return the result set unchanged with an empty token to signal the end of the dataset to the client.
func NormalizeLimit ¶
func NormalizeLimitMax ¶
func TrimResultSet ¶
func TrimResultSet[CursorType Cursor, T any](initialPager *CursorPager[CursorType], resultSet []T) []T
TrimResultSet trims the result set to what should be returned to the client.
If lookahead = true, drop the last element before returning. Suppose resultSet = [a, b, c].
- With lookahead → resultSet becomes [a, b].
- Without lookahead → resultSet remains unchanged.
This enables building pagination based on a STRICT comparison with the last element of the result set.
Types ¶
type ColumnAlias ¶
type ColumnAlias = string
type ColumnMapping ¶
type ColumnMapping = map[ColumnAlias]string
ColumnMapping maps external column aliases to fully qualified column names. Use it when bare column names could cause an "ambiguous column name" error. Key is an external alias, value is an internal column name.
type CursorElement ¶
type CursorElement struct {
Column string `json:"c"`
Value any `json:"v"`
Operator Operator `json:"o"`
}
CursorElement represents a triplet (c v o), where:
- c: an object's field (column)
- v: the value compared against the field
- o: the operator applied to the pair (c, v)
type CursorPager ¶
type CursorPager[CursorType Cursor] struct { // contains filtered or unexported fields }
func DecodeCursorPager ¶
func DecodeCursorPager(limit int, rawStartToken string, orderBy ...OrderBy) (*CursorPager[*DefaultCursor], error)
DecodeCursorPager decodes a cursor token into *CursorPager.
Usage guide: https://doc.office.lan/spaces/MBCSHCH/pages/417057947
func DecodePseudoCursorPager ¶
func DecodePseudoCursorPager(limit int, rawStartToken string, orderBy ...OrderBy) (*CursorPager[*PseudoCursor], error)
DecodePseudoCursorPager decodes a pseudo-cursor token into *CursorPager.
Usage guide: https://doc.office.lan/spaces/MBCSHCH/pages/417057947
func NewCursorPager ¶
func NewCursorPager[CursorType Cursor]() *CursorPager[CursorType]
func (*CursorPager[CursorType]) GetCursor ¶
func (c *CursorPager[CursorType]) GetCursor() CursorType
GetCursor returns the cursor stored in CursorPager as-is.
func (*CursorPager[CursorType]) GetDatasetLimit ¶
func (c *CursorPager[CursorType]) GetDatasetLimit() int
GetDatasetLimit returns the limit adjusted for lookahead:
- if Lookahead = true → GetLimit() + 1
- if Lookahead = false → GetLimit()
func (*CursorPager[CursorType]) GetLimit ¶
func (c *CursorPager[CursorType]) GetLimit() int
GetLimit returns the limit as it is stored in CursorPager. The return value is >= 0. Returning NoLimit is equivalent to no limit.
func (*CursorPager[CursorType]) GetSort ¶
func (c *CursorPager[CursorType]) GetSort() Orderings
GetSort returns orderings that will be applied to the dataset.
func (*CursorPager[CursorType]) IsLookahead ¶
func (c *CursorPager[CursorType]) IsLookahead() bool
IsLookahead returns true if lookahead pagination is enabled.
func (*CursorPager[CursorType]) IsUnlimited ¶
func (c *CursorPager[CursorType]) IsUnlimited() bool
IsUnlimited returns true if the limit equals NoLimit (unbounded number of records).
func (*CursorPager[CursorType]) Paginate ¶
Paginate applies pagination to the dataset. Returns an error if pagination cannot be applied.
func (*CursorPager[CursorType]) WithCursor ¶
func (c *CursorPager[CursorType]) WithCursor(cursor CursorType) *CursorPager[CursorType]
WithCursor sets the cursor explicitly.
func (*CursorPager[CursorType]) WithLimit ¶
func (c *CursorPager[CursorType]) WithLimit(limit int) *CursorPager[CursorType]
WithLimit sets the maximum number of returned records.
IMPORTANT:
- NoLimit cannot be used together with WithLookahead.
- If the limit is not NoLimit, NormalizeLimit will be applied.
func (*CursorPager[CursorType]) WithLookahead ¶
func (c *CursorPager[CursorType]) WithLookahead() *CursorPager[CursorType]
WithLookahead enables lookahead pagination, which checks the next page to determine whether the current page is the last.
IMPORTANT: Cannot be used together with WithUnlimited() or WithLimit(NoLimit).
func (*CursorPager[CursorType]) WithSort ¶
func (c *CursorPager[CursorType]) WithSort(orderBy ...OrderBy) *CursorPager[CursorType]
WithSort appends sort orderings without overwriting existing ones. Order is preserved as if calling:
OrderBy(o1).ThenBy(o2).ThenBy(o3)...
func (*CursorPager[CursorType]) WithSubstitutedSort ¶
func (c *CursorPager[CursorType]) WithSubstitutedSort(orderBy ...OrderBy) *CursorPager[CursorType]
WithSubstitutedSort resets previous orderings and applies the provided ones.
func (*CursorPager[CursorType]) WithUnlimited ¶
func (c *CursorPager[CursorType]) WithUnlimited() *CursorPager[CursorType]
WithUnlimited allows returning all records without a limit.
IMPORTANT: Cannot be used together with WithLookahead.
type DefaultCursor ¶
type DefaultCursor struct {
// contains filtered or unexported fields
}
DefaultCursor represents a pagination token that defines the starting position for the requested page. An empty token means the beginning of the dataset.
IMPORTANT: The token MUST always include a condition on a unique column!
The token consists of a set of conditions of the form:
[(C1, O1, V1), (C2, O2, V2)... (Cn, On, Vn)]
func DecodeCursor ¶
func DecodeCursor(b64String string) (*DefaultCursor, error)
DecodeCursor attempts to parse a base64-encoded string into *DefaultCursor.
func NewCursor ¶
func NewCursor(elements ...CursorElement) *DefaultCursor
func NewDefaultCursor ¶
func NewDefaultCursor(elements ...CursorElement) *DefaultCursor
func NextPageCursor ¶
func NextPageCursor[T any]( initialPager *CursorPager[*DefaultCursor], resultSet []T, getters Getters[T], ) ([]T, *DefaultCursor, error)
NextPageCursor builds a cursor for the next page of the dataset.
func (*DefaultCursor) Apply ¶
func (c *DefaultCursor) Apply(db *gorm.DB) *gorm.DB
Apply - implements Cursor. Applies filter-based offset to the gorm query.
func (*DefaultCursor) GetElements ¶
func (c *DefaultCursor) GetElements() []CursorElement
GetElements returns token elements. Cursor elements are a compressed set of filter conditions.
IMPORTANT: These filter conditions must NOT be applied directly to data, as they are not complete. During pagination they are inflated into a full set of filtering conditions.
func (*DefaultCursor) String ¶
func (c *DefaultCursor) String() string
String - implements fmt.Stringer.
func (*DefaultCursor) ToSQL ¶
func (c *DefaultCursor) ToSQL() (string, []driver.Value)
ToSQL - implements Cursor. Returns the SQL expression representing the filter.
Usage:
query := fmt.Sprintf("SELECT * FROM table WHERE %s", p.ToSQL())
func (*DefaultCursor) WithElements ¶
func (c *DefaultCursor) WithElements(elements []CursorElement) *DefaultCursor
WithElements explicitly sets the token elements.
type Direction ¶
type Direction string
Direction defines the sort direction for the requested dataset.
func (Direction) ForOperator ¶
type Getters ¶
Getters is a map of getters for a type. Specify the columns used for pagination. Example:
pager.Getters[models.PlayerPushTarget]{
"id": func(last models.PlayerPushTarget) any { return last.ID },
"deposit_sum": func(last models.PlayerPushTarget) any { return last.DepositSum },
}
type Operator ¶
type Operator string
Operator defines a comparison operator for filtering by column. Used in pagination filtering conditions.
func (Operator) ForOrdering ¶
type Orderings ¶
type Orderings []OrderBy
func ParseSort ¶
func ParseSort(stringsOrderings []string, columnMapping ColumnMapping) (Orderings, error)
ParseSort builds Orderings from a list of strings in the format "column asc|desc". Column aliases are resolved via ColumnMapping. Returns an error if an alias is not found in the mapping.
func (Orderings) ToSQL ¶
ToSQL converts Orderings to a single string "<order_column_1> <order_direction_1>, <order_column_2> <order_direction_2>" suitable for embedding into an SQL query. Example: for [{"a", "ASC"}, {"b", "DESC"}] returns "a ASC, b DESC".
Usage:
query := fmt.Sprintf("SELECT * FROM table ORDER BY %s", orderings.ToSQL())
func (Orderings) ToSQLSlice ¶
ToSQLSlice converts Orderings to a slice of strings in the form "<order_column> <order_direction>" suitable for SQL query builders.
Example: for Orderings: [{"a", "ASC"}, {"b", "DESC"}] returns ["a ASC", "b DESC"].
type PaginationResult ¶
type PaginationResult[T any, CursorType Cursor] struct { // Items result elements. Items []T // Total number of elements. Total int64 // AppliedLimit effective limit used for the query. AppliedLimit int // NextPageToken token for the next page. NextPageToken CursorType }
PaginationResult is a generic paginated result container.
type PseudoCursor ¶
type PseudoCursor struct {
// contains filtered or unexported fields
}
PseudoCursor is used when an API requires cursor-based pagination but only LIMIT/OFFSET pagination is available.
It implements Cursor and generates a token based on the last offset within the dataset.
func DecodePseudoCursor ¶
func DecodePseudoCursor(b64String string) (*PseudoCursor, error)
DecodePseudoCursor attempts to parse a base64-encoded string into *PseudoCursor.
func NewPseudoCursor ¶
func NewPseudoCursor(offset int) *PseudoCursor
func NextPagePseudoCursor ¶
func NextPagePseudoCursor[T any]( initialPager *CursorPager[*PseudoCursor], resultSet []T, ) ([]T, *PseudoCursor, error)
NextPagePseudoCursor builds a pseudo-cursor for the next page of the dataset.
func (*PseudoCursor) Apply ¶
func (p *PseudoCursor) Apply(db *gorm.DB) *gorm.DB
Apply - implements Cursor. Applies the offset to a gorm query.
func (*PseudoCursor) GetOffset ¶
func (p *PseudoCursor) GetOffset() int
GetOffset returns the numeric offset value.
func (*PseudoCursor) String ¶
func (p *PseudoCursor) String() string
String - implements fmt.Stringer.
func (*PseudoCursor) ToSQL ¶
func (p *PseudoCursor) ToSQL() string
ToSQL - implements Cursor. Returns the string form of the numeric offset value.
Usage:
query := fmt.Sprintf("SELECT * FROM table OFFSET %s", p.ToSQL())
func (*PseudoCursor) WithOffset ¶
func (p *PseudoCursor) WithOffset(offset int) *PseudoCursor
WithOffset sets the numeric offset value and returns the cursor.
type RawCursorPager ¶
type RawCursorPager struct {
// Limit - maximum number of records to return in the response.
Limit int `json:"limit"`
// StartToken - base64-encoded cursor token obtained via Cursor.String().
// If empty, the first page with Limit records is returned.
StartToken string `json:"startToken"`
}
RawCursorPager is intended for API payloads. For proper code generation, inline it:
type MyFilter struct {
Paging RawCursorPager `json:",inline"`
}
func (RawCursorPager) Decode ¶
func (p RawCursorPager) Decode(orderBy ...OrderBy) (*CursorPager[*DefaultCursor], error)
Decode converts RawCursorPager into *CursorPager[*DefaultCursor], normalizing Limit and validating StartToken. Returns *CursorPager[*DefaultCursor] with WithSort applied.
func (RawCursorPager) DecodePseudo ¶
func (p RawCursorPager) DecodePseudo(orderBy ...OrderBy) (*CursorPager[*PseudoCursor], error)
DecodePseudo converts RawCursorPager into *CursorPager[*PseudoCursor], normalizing Limit and validating StartToken. Returns *CursorPager[*PseudoCursor] with WithSort applied.